Rewrite of packets listener and added callbacks

This commit is contained in:
TheMode 2019-08-20 17:41:07 +02:00
parent bdde4af581
commit 729d82abd4
51 changed files with 788 additions and 400 deletions

View File

@ -10,6 +10,7 @@ import fr.themode.minestom.entity.Player;
import fr.themode.minestom.instance.BlockManager;
import fr.themode.minestom.instance.InstanceManager;
import fr.themode.minestom.instance.demo.StoneBlock;
import fr.themode.minestom.listener.PacketListenerManager;
import fr.themode.minestom.net.ConnectionManager;
import fr.themode.minestom.net.PacketProcessor;
import fr.themode.minestom.net.packet.server.play.DestroyEntitiesPacket;
@ -21,9 +22,12 @@ import java.lang.reflect.InvocationTargetException;
public class Main {
public static final int TICK_MS = 50;
// Networking
private static ConnectionManager connectionManager;
private static PacketProcessor packetProcessor;
private static PacketListenerManager packetListenerManager;
private static Server server;
// In-Game Manager
@ -34,6 +38,7 @@ public class Main {
public static void main(String[] args) {
connectionManager = new ConnectionManager();
packetProcessor = new PacketProcessor();
packetListenerManager = new PacketListenerManager();
instanceManager = new InstanceManager();
blockManager = new BlockManager();
@ -95,7 +100,7 @@ public class Main {
server.bind(25565);
System.out.println("Server started");
long tickDistance = 50 * 1000000; // 50 ms
long tickDistance = TICK_MS * 1000000;
long nextTick = System.nanoTime();
long currentTime;
while (true) {
@ -121,6 +126,10 @@ public class Main {
}
}
public static PacketListenerManager getPacketListenerManager() {
return packetListenerManager;
}
public static Server getServer() {
return server;
}

View File

@ -81,12 +81,12 @@ public class BossBar implements Viewable {
updateStyle();
}
public void remove() {
public void delete() {
BossBarPacket bossBarPacket = new BossBarPacket();
bossBarPacket.uuid = uuid;
bossBarPacket.action = BossBarPacket.Action.REMOVE;
sendPacket(bossBarPacket);
// TODO remove bar from player class
getViewers().forEach(player -> player.refreshRemoveBossbar(this));
}
private void addToPlayer(Player player) {

View File

@ -1,14 +1,26 @@
package fr.themode.minestom.entity;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.Main;
import fr.themode.minestom.Viewable;
import fr.themode.minestom.event.Callback;
import fr.themode.minestom.event.CancellableEvent;
import fr.themode.minestom.event.Event;
import fr.themode.minestom.instance.Chunk;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.play.SetPassengersPacket;
import fr.themode.minestom.utils.Utils;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class Entity {
public abstract class Entity implements Viewable {
private static AtomicInteger lastEntityId = new AtomicInteger();
@ -27,6 +39,12 @@ public abstract class Entity {
protected double x, y, z;
protected float yaw, pitch;
private int id;
protected Entity vehicle;
private Map<Class<Event>, Callback> eventCallbacks = new ConcurrentHashMap<>();
private Set<Player> viewers = new CopyOnWriteArraySet<>();
private Set<Entity> passengers = new CopyOnWriteArraySet<>();
// Metadata
protected boolean onFire;
protected UUID uuid;
@ -61,6 +79,26 @@ public abstract class Entity {
public abstract void update();
@Override
public void addViewer(Player player) {
this.viewers.add(player);
}
@Override
public void removeViewer(Player player) {
synchronized (viewers) {
if (!viewers.contains(player))
return;
this.viewers.remove(player);
// TODO send packet to remove entity
}
}
@Override
public Set<Player> getViewers() {
return Collections.unmodifiableSet(viewers);
}
public void tick() {
if (shouldUpdate()) {
update();
@ -68,6 +106,27 @@ public abstract class Entity {
}
}
public <E extends Event> void setEventCallback(Class<E> eventClass, Callback<E> callback) {
this.eventCallbacks.put((Class<Event>) eventClass, callback);
}
public <E extends Event> Callback<E> getEventCallback(Class<E> eventClass) {
return this.eventCallbacks.getOrDefault(eventClass, null);
}
public <E extends Event> void callEvent(Class<E> eventClass, E event) {
Callback<E> callback = getEventCallback(eventClass);
if (callback != null)
getEventCallback(eventClass).run(event);
}
public <E extends CancellableEvent> void callCancellableEvent(Class<E> eventClass, E event, Runnable runnable) {
callEvent(eventClass, event);
if (!event.isCancelled()) {
runnable.run();
}
}
public int getEntityId() {
return id;
}
@ -105,6 +164,25 @@ public abstract class Entity {
return (float) Math.sqrt(Math.pow(entity.getX() - getX(), 2) + Math.pow(entity.getY() - getY(), 2) + Math.pow(entity.getZ() - getZ(), 2));
}
public void addPassenger(Entity entity) {
this.passengers.add(entity);
entity.vehicle = this;
if (instance != null) {
SetPassengersPacket passengersPacket = new SetPassengersPacket();
passengersPacket.vehicleEntityId = getEntityId();
passengersPacket.passengersId = new int[]{entity.getEntityId()};
sendPacketToViewers(passengersPacket);
}
}
public boolean hasPassenger() {
return !passengers.isEmpty();
}
public Set<Entity> getPassengers() {
return Collections.unmodifiableSet(passengers);
}
public void refreshPosition(double x, double y, double z) {
this.lastX = this.x;
this.lastY = this.y;
@ -152,6 +230,10 @@ public abstract class Entity {
this.shouldRemove = true;
}
protected void sendPacketToViewers(ServerPacket packet) {
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(packet));
}
public Buffer getMetadataBuffer() {
Buffer buffer = Buffer.create();
fillMetadataIndex(buffer, 0);
@ -222,7 +304,7 @@ public abstract class Entity {
}
private boolean shouldUpdate() {
return (float) (System.currentTimeMillis() - lastUpdate) >= 50f * 0.9f; // Margin of error
return (float) (System.currentTimeMillis() - lastUpdate) >= Main.TICK_MS * 0.9f; // Margin of error
}
public enum Pose {

View File

@ -1,17 +1,9 @@
package fr.themode.minestom.entity;
import fr.themode.minestom.Viewable;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.play.*;
import fr.themode.minestom.net.player.PlayerConnection;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public abstract class EntityCreature extends LivingEntity implements Viewable {
private Set<Player> viewers = new CopyOnWriteArraySet<>();
public abstract class EntityCreature extends LivingEntity {
public EntityCreature(int entityType) {
super(entityType);
@ -53,7 +45,7 @@ public abstract class EntityCreature extends LivingEntity implements Viewable {
@Override
public void addViewer(Player player) {
this.viewers.add(player);
super.addViewer(player);
PlayerConnection playerConnection = player.getPlayerConnection();
EntityPacket entityPacket = new EntityPacket();
@ -75,23 +67,4 @@ public abstract class EntityCreature extends LivingEntity implements Viewable {
playerConnection.sendPacket(spawnMobPacket);
playerConnection.sendPacket(entityMetaDataPacket);
}
@Override
public void removeViewer(Player player) {
synchronized (viewers) {
if (!viewers.contains(player))
return;
this.viewers.remove(player);
// TODO send packet to remove entity
}
}
@Override
public Set<Player> getViewers() {
return Collections.unmodifiableSet(viewers);
}
protected void sendPacketToViewers(ServerPacket packet) {
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(packet));
}
}

View File

@ -3,18 +3,22 @@ package fr.themode.minestom.entity;
import fr.themode.minestom.Main;
import fr.themode.minestom.bossbar.BossBar;
import fr.themode.minestom.chat.Chat;
import fr.themode.minestom.event.BlockPlaceEvent;
import fr.themode.minestom.event.PickupItemEvent;
import fr.themode.minestom.instance.Chunk;
import fr.themode.minestom.instance.CustomBlock;
import fr.themode.minestom.inventory.Inventory;
import fr.themode.minestom.inventory.PlayerInventory;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.net.packet.server.play.*;
import fr.themode.minestom.net.player.PlayerConnection;
import fr.themode.minestom.utils.GroupedCollections;
import fr.themode.minestom.utils.Position;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArraySet;
public class Player extends LivingEntity {
@ -23,6 +27,7 @@ public class Player extends LivingEntity {
private String username;
private PlayerConnection playerConnection;
private ConcurrentLinkedQueue<ClientPlayPacket> packets = new ConcurrentLinkedQueue<>();
private GameMode gameMode;
private PlayerInventory inventory;
@ -35,6 +40,10 @@ public class Player extends LivingEntity {
private Set<BossBar> bossBars = new CopyOnWriteArraySet<>();
// Vehicle
private float sideways;
private float forward;
// TODO set proper UUID
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
super(93); // TODO correct ?
@ -43,10 +52,31 @@ public class Player extends LivingEntity {
this.playerConnection = playerConnection;
this.inventory = new PlayerInventory(this);
/*setEventCallback(PickupItemEvent.class, event -> {
sendMessage("Hey you're trying to pick an item!");
event.setCancelled(true);
});*/
/*setEventCallback(StartDiggingEvent.class, event -> {
Random random = new Random();
boolean cancel = random.nextBoolean();
event.setCancelled(cancel);
sendMessage("Cancelled: " + cancel);
});*/
setEventCallback(BlockPlaceEvent.class, event -> {
event.setCancelled(true);
sendMessage("CANCELLED");
});
}
@Override
public void update() {
while (!packets.isEmpty()) {
ClientPlayPacket packet = packets.remove();
packet.process(this);
}
// Target block stage
if (instance != null && targetCustomBlock != null) {
@ -64,13 +94,30 @@ public class Player extends LivingEntity {
// Item pickup
if (instance != null) {
GroupedCollections<ObjectEntity> objectEntities = instance.getObjectEntities();
Chunk chunk = instance.getChunkAt(getX(), getZ());
Set<ObjectEntity> objectEntities = chunk.getObjectEntities();
for (ObjectEntity objectEntity : objectEntities) {
if (objectEntity instanceof ItemEntity) {
ItemEntity itemEntity = (ItemEntity) objectEntity;
if (!itemEntity.isPickable())
continue;
float distance = getDistance(objectEntity);
if (distance <= 1) { // FIXME set correct value
getInventory().addItemStack(((ItemEntity) objectEntity).getItemStack());
objectEntity.remove();
if (distance <= 2.04) {
synchronized (itemEntity) {
if (itemEntity.shouldRemove())
continue;
ItemStack item = itemEntity.getItemStack();
PickupItemEvent pickupItemEvent = new PickupItemEvent(item);
callCancellableEvent(PickupItemEvent.class, pickupItemEvent, () -> {
CollectItemPacket collectItemPacket = new CollectItemPacket();
collectItemPacket.collectedEntityId = itemEntity.getEntityId();
collectItemPacket.collectorEntityId = getEntityId();
collectItemPacket.pickupItemCount = item.getAmount();
instance.getPlayers().forEach(player -> player.getPlayerConnection().sendPacket(collectItemPacket));
getInventory().addItemStack(item);
objectEntity.remove();
});
}
}
}
}
@ -108,11 +155,11 @@ public class Player extends LivingEntity {
particlePacket.x = x;
particlePacket.y = y;
particlePacket.z = z;
particlePacket.offsetX = 0.55f;
particlePacket.offsetY = 0.75f;
particlePacket.offsetZ = 0.55f;
particlePacket.particleData = 0.25f;
particlePacket.particleCount = 100;
particlePacket.offsetX = 0.4f;
particlePacket.offsetY = 0.65f;
particlePacket.offsetZ = 0.4f;
particlePacket.particleData = 0.3f;
particlePacket.particleCount = 75;
particlePacket.blockId = blockId;
playerConnection.sendPacket(particlePacket);
}
@ -187,6 +234,14 @@ public class Player extends LivingEntity {
return Collections.unmodifiableSet(bossBars);
}
public float getVehicleSideways() {
return sideways;
}
public float getVehicleForward() {
return forward;
}
public void openInventory(Inventory inventory) {
if (inventory == null)
throw new IllegalArgumentException("Inventory cannot be null, use Player#closeInventory() to close current");
@ -218,6 +273,10 @@ public class Player extends LivingEntity {
inventory.update();
}
public void addPacketToQueue(ClientPlayPacket packet) {
this.packets.add(packet);
}
public void refreshGameMode(GameMode gameMode) {
this.gameMode = gameMode;
}
@ -271,6 +330,11 @@ public class Player extends LivingEntity {
this.bossBars.remove(bossBar);
}
public void refreshVehicleSteer(float sideways, float forward) {
this.sideways = sideways;
this.forward = forward;
}
public long getLastKeepAlive() {
return lastKeepAlive;
}

View File

@ -1,8 +1,6 @@
package fr.themode.minestom.entity.demo;
import fr.themode.minestom.Main;
import fr.themode.minestom.entity.EntityCreature;
import fr.themode.minestom.entity.Player;
public class ChickenCreature extends EntityCreature {
@ -12,13 +10,37 @@ public class ChickenCreature extends EntityCreature {
@Override
public void update() {
double speed = 0.075;
float speed = 0.075f;
Player player = Main.getConnectionManager().getPlayer("TheMode911");
if (player != null) {
//teleport(player.getX(), 5, player.getZ());
}
/*if (hasPassenger()) {
Entity passenger = getPassengers().iterator().next();
if (passenger instanceof Player) {
Player player = (Player) passenger;
float sideways = player.getVehicleSideways();
float forward = player.getVehicleForward();
if (sideways == 0f && forward == 0f)
return;
float yaw = player.getYaw();
yaw %= 360;
if (forward > 0) {
forward = yaw * forward;
} else {
forward = yaw - forward * 180;
}
sideways = yaw - sideways * 90;
yaw = (forward + sideways) / 2 % 360;
System.out.println("test: " + forward + " : " + sideways);
double radian = Math.toRadians(yaw + 90);
double cos = Math.cos(radian);
double sin = Math.sin(radian);
//System.out.println(sideways + " : " + forward);
//System.out.println(cos + " : " + sin);
double x = cos;
double z = sin;
move(x * speed, 0, z * speed);
}
}*/
move(0, 0, speed);
}
}

View File

@ -0,0 +1,14 @@
package fr.themode.minestom.event;
public class BlockPlaceEvent extends CancellableEvent {
private short blockId;
public BlockPlaceEvent(short blockId) {
this.blockId = blockId;
}
public short getBlockId() {
return blockId;
}
}

View File

@ -0,0 +1,7 @@
package fr.themode.minestom.event;
public interface Callback<E extends Event> {
void run(E event);
}

View File

@ -0,0 +1,15 @@
package fr.themode.minestom.event;
public class CancellableEvent extends Event {
private boolean cancelled;
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
}

View File

@ -0,0 +1,4 @@
package fr.themode.minestom.event;
public class Event {
}

View File

@ -0,0 +1,16 @@
package fr.themode.minestom.event;
import fr.themode.minestom.item.ItemStack;
public class PickupItemEvent extends CancellableEvent {
private ItemStack itemStack;
public PickupItemEvent(ItemStack itemStack) {
this.itemStack = itemStack;
}
public ItemStack getItemStack() {
return itemStack;
}
}

View File

@ -0,0 +1,16 @@
package fr.themode.minestom.event;
import fr.themode.minestom.instance.CustomBlock;
public class StartDiggingEvent extends CancellableEvent {
private CustomBlock customBlock;
public StartDiggingEvent(CustomBlock customBlock) {
this.customBlock = customBlock;
}
public CustomBlock getBlock() {
return customBlock;
}
}

View File

@ -1,6 +1,5 @@
package fr.themode.minestom.instance;
import fr.themode.minestom.Viewable;
import fr.themode.minestom.entity.Entity;
import fr.themode.minestom.entity.EntityCreature;
import fr.themode.minestom.entity.ObjectEntity;
@ -8,6 +7,7 @@ import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.server.play.ChunkDataPacket;
import fr.themode.minestom.net.packet.server.play.DestroyEntitiesPacket;
import fr.themode.minestom.utils.GroupedCollections;
import fr.themode.minestom.utils.Position;
import java.util.Collection;
import java.util.Collections;
@ -78,6 +78,10 @@ public class Instance implements BlockModifier {
return getChunk(chunkX, chunkZ);
}
public Chunk getChunkAt(Position position) {
return getChunkAt(position.getX(), position.getZ());
}
public void setChunkGenerator(ChunkGenerator chunkGenerator) {
this.chunkGenerator = chunkGenerator;
}
@ -92,14 +96,13 @@ public class Instance implements BlockModifier {
lastInstance.removeEntity(entity);
}
if (entity instanceof Viewable) {
// TODO based on distance with players
Viewable viewable = (Viewable) entity;
getPlayers().forEach(p -> ((Viewable) entity).addViewer(p));
} else if (entity instanceof Player) {
if (entity instanceof Player) {
Player player = (Player) entity;
sendChunks(player);
getCreatures().forEach(entityCreature -> entityCreature.addViewer(player));
} else {
// TODO based on distance with players
getPlayers().forEach(p -> entity.addViewer(p));
}
Chunk chunk = getChunkAt(entity.getX(), entity.getZ());
@ -111,13 +114,12 @@ public class Instance implements BlockModifier {
if (entityInstance == null || entityInstance != this)
return;
if (entity instanceof Viewable) {
if (!(entity instanceof Player)) {
DestroyEntitiesPacket destroyEntitiesPacket = new DestroyEntitiesPacket();
destroyEntitiesPacket.entityIds = new int[]{entity.getEntityId()};
Viewable viewable = (Viewable) entity;
viewable.getViewers().forEach(p -> p.getPlayerConnection().sendPacket(destroyEntitiesPacket)); // TODO destroy batch
viewable.getViewers().forEach(p -> viewable.removeViewer(p));
entity.getViewers().forEach(p -> p.getPlayerConnection().sendPacket(destroyEntitiesPacket)); // TODO destroy batch
entity.getViewers().forEach(p -> entity.removeViewer(p));
}
Chunk chunk = getChunkAt(entity.getX(), entity.getZ());
@ -140,6 +142,13 @@ public class Instance implements BlockModifier {
return uniqueId;
}
public void sendChunkUpdate(Player player, Chunk chunk) {
ChunkDataPacket chunkDataPacket = new ChunkDataPacket();
chunkDataPacket.fullChunk = false;
chunkDataPacket.chunk = chunk;
player.getPlayerConnection().sendPacket(chunkDataPacket);
}
protected Chunk createChunk(int chunkX, int chunkZ) {
Biome biome = chunkGenerator != null ? chunkGenerator.getBiome(chunkX, chunkZ) : Biome.VOID;
Chunk chunk = new Chunk(biome, chunkX, chunkZ);
@ -161,7 +170,7 @@ public class Instance implements BlockModifier {
protected void sendChunkUpdate(Chunk chunk) {
ChunkDataPacket chunkDataPacket = new ChunkDataPacket();
chunkDataPacket.fullChunk = false; // TODO partial chunk data
chunkDataPacket.fullChunk = false;
chunkDataPacket.chunk = chunk;
getPlayers().forEach(player -> player.getPlayerConnection().sendPacket(chunkDataPacket));
}

View File

@ -0,0 +1,45 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.event.BlockPlaceEvent;
import fr.themode.minestom.instance.Chunk;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.net.packet.client.play.ClientPlayerBlockPlacementPacket;
import fr.themode.minestom.net.packet.client.play.ClientPlayerDiggingPacket;
import fr.themode.minestom.utils.Position;
public class BlockPlacementListener {
public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) {
ClientPlayerDiggingPacket.BlockFace blockFace = packet.blockFace;
Position position = packet.position;
Instance instance = player.getInstance();
if (instance == null)
return;
int offsetX = blockFace == ClientPlayerDiggingPacket.BlockFace.WEST ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.EAST ? 1 : 0;
int offsetY = blockFace == ClientPlayerDiggingPacket.BlockFace.BOTTOM ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.TOP ? 1 : 0;
int offsetZ = blockFace == ClientPlayerDiggingPacket.BlockFace.NORTH ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.SOUTH ? 1 : 0;
BlockPlaceEvent blockPlaceEvent = new BlockPlaceEvent((short) 10);
player.callEvent(BlockPlaceEvent.class, blockPlaceEvent);
if (!blockPlaceEvent.isCancelled()) {
instance.setBlock(position.getX() + offsetX, position.getY() + offsetY, position.getZ() + offsetZ, "custom_block");
// TODO consume block in hand for survival players
} else {
Chunk chunk = instance.getChunkAt(position);
instance.sendChunkUpdate(player, chunk);
}
player.getInventory().refreshSlot(player.getHeldSlot());
/*Random random = new Random();
BlockBatch blockBatch = instance.createBlockBatch();
for (int x = -64; x < 64; x++)
for (int z = -64; z < 64; z++) {
if (random.nextInt(100) > 75)
blockBatch.setBlock(x, position.getY() + 1, z, new Block(1));
}
blockBatch.flush();*/
}
}

View File

@ -0,0 +1,13 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.Main;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.play.ClientChatMessagePacket;
public class ChatMessageListener {
public static void listener(ClientChatMessagePacket packet, Player player) {
Main.getConnectionManager().getOnlinePlayers().forEach(p -> p.sendMessage(String.format("<%s> %s", player.getUsername(), packet.message)));
}
}

View File

@ -0,0 +1,26 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.play.ClientEntityActionPacket;
public class EntityActionListener {
public static void listener(ClientEntityActionPacket packet, Player player) {
ClientEntityActionPacket.Action action = packet.action;
switch (action) {
case START_SNEAKING:
player.refreshSneaking(true);
break;
case STOP_SNEAKING:
player.refreshSneaking(false);
break;
case START_SPRINTING:
player.refreshSprinting(true);
break;
case STOP_SPRINTING:
player.refreshSprinting(false);
break;
// TODO do remaining actions
}
}
}

View File

@ -0,0 +1,17 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.chat.Chat;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.play.ClientKeepAlivePacket;
import fr.themode.minestom.net.packet.server.play.DisconnectPacket;
public class KeepAliveListener {
public static void listener(ClientKeepAlivePacket packet, Player player) {
if (packet.id != player.getLastKeepAlive()) {
player.getPlayerConnection().sendPacket(new DisconnectPacket(Chat.rawText("Bad Keep Alive packet")));
player.getPlayerConnection().getConnection().close();
}
}
}

View File

@ -0,0 +1,45 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.net.packet.client.play.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
public class PacketListenerManager {
private Map<Class<? extends ClientPlayPacket>, BiConsumer<? extends ClientPlayPacket, Player>> listeners = new ConcurrentHashMap<>();
public PacketListenerManager() {
addListener(ClientKeepAlivePacket.class, KeepAliveListener::listener);
addListener(ClientChatMessagePacket.class, ChatMessageListener::listener);
addListener(ClientClickWindowPacket.class, WindowListener::clickWindowListener);
addListener(ClientCloseWindow.class, WindowListener::closeWindowListener);
addListener(ClientEntityActionPacket.class, EntityActionListener::listener);
addListener(ClientHeldItemChangePacket.class, PlayerHeldListener::heldListener);
addListener(ClientPlayerBlockPlacementPacket.class, BlockPlacementListener::listener);
addListener(ClientSteerVehiclePacket.class, PlayerVehicleListener::steerVehicleListener);
addListener(ClientPlayerPacket.class, PlayerPositionListener::playerPacketListener);
addListener(ClientPlayerLookPacket.class, PlayerPositionListener::playerLookListener);
addListener(ClientPlayerPositionPacket.class, PlayerPositionListener::playerPositionListener);
addListener(ClientPlayerPositionAndLookPacket.class, PlayerPositionListener::playerPositionAndLookListener);
addListener(ClientPlayerDiggingPacket.class, PlayerDiggingListener::playerDiggingListener);
}
public <T extends ClientPlayPacket> void process(T packet, Player player) {
BiConsumer<T, Player> biConsumer = (BiConsumer<T, Player>) listeners.get(packet.getClass());
if (biConsumer == null) {
// System.err.println("Packet " + packet.getClass() + " does not have any listener!");
return;
}
biConsumer.accept(packet, player);
}
public <T extends ClientPlayPacket> void addListener(Class<T> packetClass, BiConsumer<T, Player> consumer) {
this.listeners.put(packetClass, consumer);
}
}

View File

@ -0,0 +1,80 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.GameMode;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.event.StartDiggingEvent;
import fr.themode.minestom.instance.CustomBlock;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.net.packet.client.play.ClientPlayerDiggingPacket;
import fr.themode.minestom.net.packet.server.play.EntityEffectPacket;
import fr.themode.minestom.net.packet.server.play.RemoveEntityEffectPacket;
import fr.themode.minestom.utils.Position;
public class PlayerDiggingListener {
public static void playerDiggingListener(ClientPlayerDiggingPacket packet, Player player) {
ClientPlayerDiggingPacket.Status status = packet.status;
Position position = packet.position;
switch (status) {
case STARTED_DIGGING:
if (player.getGameMode() == GameMode.CREATIVE) {
Instance instance = player.getInstance();
if (instance != null) {
instance.setBlock(position.getX(), position.getY(), position.getZ(), (short) 0);
}
} else if (player.getGameMode() == GameMode.SURVIVAL) {
Instance instance = player.getInstance();
if (instance != null) {
CustomBlock customBlock = instance.getCustomBlock(position.getX(), position.getY(), position.getZ());
if (customBlock != null) {
StartDiggingEvent startDiggingEvent = new StartDiggingEvent(customBlock);
player.callEvent(StartDiggingEvent.class, startDiggingEvent);
if (!startDiggingEvent.isCancelled()) {
player.refreshTargetBlock(customBlock, position);
}
addEffect(player);
} else {
player.resetTargetBlock();
removeEffect(player);
}
}
}
break;
case CANCELLED_DIGGING:
// TODO BlockBreakEvent
player.sendBlockBreakAnimation(position, (byte) -1);
player.resetTargetBlock();
removeEffect(player);
break;
case FINISHED_DIGGING:
if (player.getCustomBlockTarget() != null) {
player.resetTargetBlock();
removeEffect(player);
} else {
Instance instance = player.getInstance();
if (instance != null) {
instance.setBlock(position.getX(), position.getY(), position.getZ(), (short) 0);
}
}
break;
}
}
private static void addEffect(Player player) {
EntityEffectPacket entityEffectPacket = new EntityEffectPacket();
entityEffectPacket.entityId = player.getEntityId();
entityEffectPacket.effectId = 4;
entityEffectPacket.amplifier = -1;
entityEffectPacket.duration = 0;
entityEffectPacket.flags = 0;
player.getPlayerConnection().sendPacket(entityEffectPacket);
}
private static void removeEffect(Player player) {
RemoveEntityEffectPacket removeEntityEffectPacket = new RemoveEntityEffectPacket();
removeEntityEffectPacket.entityId = player.getEntityId();
removeEntityEffectPacket.effectId = 4;
player.getPlayerConnection().sendPacket(removeEntityEffectPacket);
}
}

View File

@ -0,0 +1,15 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.play.ClientHeldItemChangePacket;
public class PlayerHeldListener {
public static void heldListener(ClientHeldItemChangePacket packet, Player player) {
short slot = packet.slot;
if (slot < 0 || slot > 8)
return;
player.refreshHeldSlot(slot);
}
}

View File

@ -0,0 +1,43 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.play.ClientPlayerLookPacket;
import fr.themode.minestom.net.packet.client.play.ClientPlayerPacket;
import fr.themode.minestom.net.packet.client.play.ClientPlayerPositionAndLookPacket;
import fr.themode.minestom.net.packet.client.play.ClientPlayerPositionPacket;
public class PlayerPositionListener {
public static void playerPacketListener(ClientPlayerPacket packet, Player player) {
player.refreshOnGround(packet.onGround);
}
public static void playerLookListener(ClientPlayerLookPacket packet, Player player) {
player.refreshView(packet.yaw, packet.pitch);
player.refreshOnGround(packet.onGround);
}
public static void playerPositionListener(ClientPlayerPositionPacket packet, Player player) {
boolean chunkTest = player.chunkTest(packet.x, packet.z);
if (chunkTest) {
player.teleport(player.getX(), player.getY(), player.getZ());
return;
}
player.refreshPosition(packet.x, packet.y, packet.z);
player.refreshOnGround(packet.onGround);
}
public static void playerPositionAndLookListener(ClientPlayerPositionAndLookPacket packet, Player player) {
boolean chunkTest = player.chunkTest(packet.x, packet.z);
if (chunkTest) {
player.teleport(player.getX(), player.getY(), player.getZ());
return;
}
player.refreshPosition(packet.x, packet.y, packet.z);
player.refreshView(packet.yaw, packet.pitch);
player.refreshOnGround(packet.onGround);
}
}

View File

@ -0,0 +1,12 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.play.ClientSteerVehiclePacket;
public class PlayerVehicleListener {
public static void steerVehicleListener(ClientSteerVehiclePacket packet, Player player) {
player.refreshVehicleSteer(packet.sideways, packet.forward);
}
}

View File

@ -0,0 +1,82 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.inventory.Inventory;
import fr.themode.minestom.inventory.InventoryClickHandler;
import fr.themode.minestom.inventory.PlayerInventory;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.client.play.ClientClickWindowPacket;
import fr.themode.minestom.net.packet.client.play.ClientCloseWindow;
import fr.themode.minestom.net.packet.server.play.ConfirmTransactionPacket;
import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
public class WindowListener {
public static void clickWindowListener(ClientClickWindowPacket packet, Player player) {
InventoryClickHandler clickHandler = player.getOpenInventory();
if (clickHandler == null) {
clickHandler = player.getInventory();
}
byte windowId = packet.windowId;
short slot = packet.slot;
byte button = packet.button;
short actionNumber = packet.actionNumber;
int mode = packet.mode;
System.out.println("Window id: " + windowId + " | slot: " + slot + " | button: " + button + " | mode: " + mode);
ConfirmTransactionPacket confirmTransactionPacket = new ConfirmTransactionPacket();
confirmTransactionPacket.windowId = windowId;
confirmTransactionPacket.actionNumber = actionNumber;
confirmTransactionPacket.accepted = true; // Change depending on output
switch (mode) {
case 0:
switch (button) {
case 0:
// Left click
clickHandler.leftClick(player, slot);
break;
case 1:
// Right click
clickHandler.rightClick(player, slot);
break;
}
break;
case 1:
clickHandler.shiftClick(player, slot); // Shift + left/right have identical behavior
break;
case 2:
clickHandler.changeHeld(player, slot, button);
break;
case 3:
// Middle click (only creative players in non-player inventories)
break;
case 4:
// Dropping functions
break;
case 5:
// Dragging
break;
case 6:
clickHandler.doubleClick(player, slot);
break;
}
ItemStack cursorItem = clickHandler instanceof Inventory ? ((Inventory) clickHandler).getCursorItem(player) : ((PlayerInventory) clickHandler).getCursorItem();
SetSlotPacket setSlotPacket = new SetSlotPacket();
setSlotPacket.windowId = -1;
setSlotPacket.slot = -1;
setSlotPacket.itemStack = cursorItem;
player.getPlayerConnection().sendPacket(setSlotPacket);
player.getPlayerConnection().sendPacket(confirmTransactionPacket);
}
public static void closeWindowListener(ClientCloseWindow packet, Player player) {
// if windowId == 0 then it is player's inventory, meaning that they hadn't been any open inventory packet
player.closeInventory();
}
}

View File

@ -14,7 +14,9 @@ import fr.themode.minestom.net.packet.client.handshake.HandshakePacket;
import fr.themode.minestom.net.player.PlayerConnection;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static fr.themode.minestom.net.protocol.MinecraftProtocol.PACKET_ID_IDENTIFIER;
@ -38,9 +40,13 @@ public class PacketProcessor {
this.playPacketsHandler = new ClientPlayPacketsHandler();
}
private List<Integer> printBlackList = Arrays.asList(17);
public void process(Connection connection, Packet packet) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
int id = packet.get(PACKET_ID_IDENTIFIER);
// System.out.println("RECEIVED ID: " + id);
if (!printBlackList.contains(id)) {
// System.out.println("RECEIVED ID: " + id);
}
Buffer buffer = packet.getPayload();
connectionPlayerConnectionMap.get(connection);
PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(connection, c -> new PlayerConnection(c));
@ -61,7 +67,7 @@ public class PacketProcessor {
Player player = connectionManager.getPlayer(playerConnection);
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
playPacket.read(buffer);
playPacket.process(player);
player.addPacketToQueue(playPacket); // Processed during player tick update
break;
case LOGIN:
ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();

View File

@ -1,10 +1,12 @@
package fr.themode.minestom.net.packet.client;
import fr.themode.minestom.Main;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPacket;
public interface ClientPlayPacket extends ClientPacket {
public abstract class ClientPlayPacket implements ClientPacket {
void process(Player player);
public void process(Player player) {
Main.getPacketListenerManager().process(this, player);
}
}

View File

@ -5,5 +5,7 @@ import fr.themode.minestom.net.player.PlayerConnection;
public interface ClientPreplayPacket extends ClientPacket {
void process(PlayerConnection connection, ConnectionManager connectionManager);
}

View File

@ -24,5 +24,6 @@ public class ClientPlayPacketsHandler extends ClientPacketsHandler {
register(0x09, ClientClickWindowPacket.class);
register(0x0A, ClientCloseWindow.class);
register(0x07, ClientConfirmTransactionPacket.class);
register(0x1C, ClientSteerVehiclePacket.class);
}
}

View File

@ -120,6 +120,9 @@ public class LoginStartPacket implements ClientPreplayPacket {
ChickenCreature chickenCreature = new ChickenCreature();
chickenCreature.refreshPosition(0 + (double) x * 1, 5, 0 + (double) z * 1);
chickenCreature.setInstance(instance);
if (x == 3 && z == 3) {
//chickenCreature.addPassenger(player);
}
}
@ -160,7 +163,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
inv.setItemStack(0, new ItemStack(1, (byte) 1));
player.openInventory(inv);
inv.setItemStack(1, new ItemStack(1, (byte) 2));
inv.updateItems();
//inv.updateItems();
BossBar bossBar = new BossBar("Le titre", BarColor.BLUE, BarDivision.SEGMENT_12);
bossBar.setProgress(0.75f);

View File

@ -5,14 +5,10 @@ import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Utils;
public class ClientAnimationPacket implements ClientPlayPacket {
public class ClientAnimationPacket extends ClientPlayPacket {
public Player.Hand hand;
@Override
public void process(Player player) {
}
@Override
public void read(Buffer buffer) {
this.hand = Player.Hand.values()[Utils.readVarInt(buffer)];

View File

@ -1,19 +1,12 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.Main;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Utils;
public class ClientChatMessagePacket implements ClientPlayPacket {
public class ClientChatMessagePacket extends ClientPlayPacket {
private String message;
@Override
public void process(Player player) {
Main.getConnectionManager().getOnlinePlayers().forEach(p -> p.sendMessage(String.format("<%s> %s", player.getUsername(), message)));
}
public String message;
@Override
public void read(Buffer buffer) {

View File

@ -1,17 +1,10 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.inventory.Inventory;
import fr.themode.minestom.inventory.InventoryClickHandler;
import fr.themode.minestom.inventory.PlayerInventory;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.net.packet.server.play.ConfirmTransactionPacket;
import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
import fr.themode.minestom.utils.Utils;
public class ClientClickWindowPacket implements ClientPlayPacket {
public class ClientClickWindowPacket extends ClientPlayPacket {
public byte windowId;
public short slot;
@ -20,62 +13,6 @@ public class ClientClickWindowPacket implements ClientPlayPacket {
public int mode;
// TODO clicked item
@Override
public void process(Player player) {
InventoryClickHandler clickHandler = player.getOpenInventory();
if (clickHandler == null) {
clickHandler = player.getInventory();
}
System.out.println("Window id: " + windowId + " | slot: " + slot + " | button: " + button + " | mode: " + mode);
ConfirmTransactionPacket confirmTransactionPacket = new ConfirmTransactionPacket();
confirmTransactionPacket.windowId = windowId;
confirmTransactionPacket.actionNumber = actionNumber;
confirmTransactionPacket.accepted = true; // Change depending on output
switch (mode) {
case 0:
switch (button) {
case 0:
// Left click
clickHandler.leftClick(player, slot);
break;
case 1:
// Right click
clickHandler.rightClick(player, slot);
break;
}
break;
case 1:
clickHandler.shiftClick(player, slot); // Shift + left/right have identical behavior
break;
case 2:
clickHandler.changeHeld(player, slot, button);
break;
case 3:
// Middle click (only creative players in non-player inventories)
break;
case 4:
// Dropping functions
break;
case 5:
// Dragging
break;
case 6:
clickHandler.doubleClick(player, slot);
break;
}
ItemStack cursorItem = clickHandler instanceof Inventory ? ((Inventory) clickHandler).getCursorItem(player) : ((PlayerInventory) clickHandler).getCursorItem();
SetSlotPacket setSlotPacket = new SetSlotPacket();
setSlotPacket.windowId = -1;
setSlotPacket.slot = -1;
setSlotPacket.itemStack = cursorItem;
player.getPlayerConnection().sendPacket(setSlotPacket);
player.getPlayerConnection().sendPacket(confirmTransactionPacket);
}
@Override
public void read(Buffer buffer) {
this.windowId = buffer.getByte();

View File

@ -1,20 +1,13 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Utils;
public class ClientCloseWindow implements ClientPlayPacket {
public class ClientCloseWindow extends ClientPlayPacket {
public int windowId;
@Override
public void process(Player player) {
// if windowId == 0 then it is player's inventory, meaning that they hadn't been any open inventory packet
player.closeInventory();
}
@Override
public void read(Buffer buffer) {
this.windowId = Utils.readVarInt(buffer);

View File

@ -1,22 +1,16 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientConfirmTransactionPacket implements ClientPlayPacket {
public class ClientConfirmTransactionPacket extends ClientPlayPacket {
public int windowId;
public short actionNumber;
public boolean accepted;
@Override
public void process(Player player) {
}
@Override
public void read(Buffer buffer) {
// TODO
}
}

View File

@ -1,35 +1,15 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Utils;
public class ClientEntityActionPacket implements ClientPlayPacket {
public class ClientEntityActionPacket extends ClientPlayPacket {
public int playerId;
public Action action;
public int horseJumpBoost;
@Override
public void process(Player player) {
switch (action) {
case START_SNEAKING:
player.refreshSneaking(true);
break;
case STOP_SNEAKING:
player.refreshSneaking(false);
break;
case START_SPRINTING:
player.refreshSprinting(true);
break;
case STOP_SPRINTING:
player.refreshSprinting(false);
break;
// TODO do remaining actions
}
}
@Override
public void read(Buffer buffer) {
this.playerId = Utils.readVarInt(buffer);

View File

@ -1,20 +1,12 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientHeldItemChangePacket implements ClientPlayPacket {
public class ClientHeldItemChangePacket extends ClientPlayPacket {
public short slot;
@Override
public void process(Player player) {
if (slot < 0 || slot > 8)
return;
player.refreshHeldSlot(slot);
}
@Override
public void read(Buffer buffer) {
this.slot = buffer.getShort();

View File

@ -1,21 +1,11 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.net.packet.server.play.DisconnectPacket;
public class ClientKeepAlivePacket implements ClientPlayPacket {
public class ClientKeepAlivePacket extends ClientPlayPacket {
private long id;
@Override
public void process(Player player) {
if (id != player.getLastKeepAlive()) {
player.getPlayerConnection().sendPacket(new DisconnectPacket("{\"text\": \"Bad Keep Alive packet\"}"));
player.getPlayerConnection().getConnection().close();
}
}
public long id;
@Override
public void read(Buffer buffer) {

View File

@ -1,19 +1,13 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientPlayerAbilitiesPacket implements ClientPlayPacket {
public class ClientPlayerAbilitiesPacket extends ClientPlayPacket {
private byte flags;
private float flyingSpeed;
private float walkingSpeed;
@Override
public void process(Player player) {
}
public byte flags;
public float flyingSpeed;
public float walkingSpeed;
@Override
public void read(Buffer buffer) {

View File

@ -1,13 +1,11 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Position;
import fr.themode.minestom.utils.Utils;
public class ClientPlayerBlockPlacementPacket implements ClientPlayPacket {
public class ClientPlayerBlockPlacementPacket extends ClientPlayPacket {
public Hand hand;
public Position position;
@ -15,29 +13,6 @@ public class ClientPlayerBlockPlacementPacket implements ClientPlayPacket {
public float cursorPositionX, cursorPositionY, cursorPositionZ;
public boolean insideBlock;
@Override
public void process(Player player) {
Instance instance = player.getInstance();
if (instance == null)
return;
int offsetX = blockFace == ClientPlayerDiggingPacket.BlockFace.WEST ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.EAST ? 1 : 0;
int offsetY = blockFace == ClientPlayerDiggingPacket.BlockFace.BOTTOM ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.TOP ? 1 : 0;
int offsetZ = blockFace == ClientPlayerDiggingPacket.BlockFace.NORTH ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.SOUTH ? 1 : 0;
instance.setBlock(position.getX() + offsetX, position.getY() + offsetY, position.getZ() + offsetZ, "custom_block");
player.getInventory().refreshSlot(player.getHeldSlot());
// TODO consume block in hand for survival players
/*Random random = new Random();
BlockBatch blockBatch = instance.createBlockBatch();
for (int x = -64; x < 64; x++)
for (int z = -64; z < 64; z++) {
if (random.nextInt(100) > 75)
blockBatch.setBlock(x, position.getY() + 1, z, new Block(1));
}
blockBatch.flush();*/
}
@Override
public void read(Buffer buffer) {
this.hand = Hand.values()[Utils.readVarInt(buffer)];

View File

@ -1,81 +1,16 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.GameMode;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.instance.CustomBlock;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.net.packet.server.play.EntityEffectPacket;
import fr.themode.minestom.net.packet.server.play.RemoveEntityEffectPacket;
import fr.themode.minestom.utils.Position;
import fr.themode.minestom.utils.Utils;
public class ClientPlayerDiggingPacket implements ClientPlayPacket {
public class ClientPlayerDiggingPacket extends ClientPlayPacket {
public Status status;
public Position position;
public BlockFace blockFace;
@Override
public void process(Player player) {
switch (status) {
case STARTED_DIGGING:
if (player.getGameMode() == GameMode.CREATIVE) {
Instance instance = player.getInstance();
if (instance != null) {
instance.setBlock(position.getX(), position.getY(), position.getZ(), (short) 0);
}
} else if (player.getGameMode() == GameMode.SURVIVAL) {
Instance instance = player.getInstance();
if (instance != null) {
CustomBlock customBlock = instance.getCustomBlock(position.getX(), position.getY(), position.getZ());
if (customBlock != null) {
player.refreshTargetBlock(customBlock, position);
addEffect(player);
} else {
player.resetTargetBlock();
removeEffect(player);
}
}
}
break;
case CANCELLED_DIGGING:
player.sendBlockBreakAnimation(position, (byte) -1);
player.resetTargetBlock();
removeEffect(player);
break;
case FINISHED_DIGGING:
if (player.getCustomBlockTarget() != null) {
player.resetTargetBlock();
removeEffect(player);
} else {
Instance instance = player.getInstance();
if (instance != null) {
instance.setBlock(position.getX(), position.getY(), position.getZ(), (short) 0);
}
}
break;
}
}
private void addEffect(Player player) {
EntityEffectPacket entityEffectPacket = new EntityEffectPacket();
entityEffectPacket.entityId = player.getEntityId();
entityEffectPacket.effectId = 4;
entityEffectPacket.amplifier = -1;
entityEffectPacket.duration = 0;
entityEffectPacket.flags = 0;
player.getPlayerConnection().sendPacket(entityEffectPacket);
}
private void removeEffect(Player player) {
RemoveEntityEffectPacket removeEntityEffectPacket = new RemoveEntityEffectPacket();
removeEntityEffectPacket.entityId = player.getEntityId();
removeEntityEffectPacket.effectId = 4;
player.getPlayerConnection().sendPacket(removeEntityEffectPacket);
}
@Override
public void read(Buffer buffer) {
this.status = Status.values()[Utils.readVarInt(buffer)];

View File

@ -1,20 +1,13 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientPlayerLookPacket implements ClientPlayPacket {
public class ClientPlayerLookPacket extends ClientPlayPacket {
public float yaw, pitch;
public boolean onGround;
@Override
public void process(Player player) {
player.refreshView(yaw, pitch);
player.refreshOnGround(onGround);
}
@Override
public void read(Buffer buffer) {
this.yaw = buffer.getFloat();

View File

@ -1,18 +1,12 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientPlayerPacket implements ClientPlayPacket {
public class ClientPlayerPacket extends ClientPlayPacket {
public boolean onGround;
@Override
public void process(Player player) {
player.refreshOnGround(onGround);
}
@Override
public void read(Buffer buffer) {
this.onGround = buffer.getBoolean();

View File

@ -1,28 +1,14 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientPlayerPositionAndLookPacket implements ClientPlayPacket {
public class ClientPlayerPositionAndLookPacket extends ClientPlayPacket {
public double x, y, z;
public float yaw, pitch;
public boolean onGround;
@Override
public void process(Player player) {
boolean chunkTest = player.chunkTest(x, z);
if (chunkTest) {
player.teleport(player.getX(), player.getY(), player.getZ());
return;
}
player.refreshPosition(x, y, z);
player.refreshView(yaw, pitch);
player.refreshOnGround(onGround);
}
@Override
public void read(Buffer buffer) {
this.x = buffer.getDouble();

View File

@ -1,26 +1,13 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientPlayerPositionPacket implements ClientPlayPacket {
public class ClientPlayerPositionPacket extends ClientPlayPacket {
public double x, y, z;
public boolean onGround;
@Override
public void process(Player player) {
boolean chunkTest = player.chunkTest(x, z);
if (chunkTest) {
player.teleport(player.getX(), player.getY(), player.getZ());
return;
}
player.refreshPosition(x, y, z);
player.refreshOnGround(onGround);
}
@Override
public void read(Buffer buffer) {
this.x = buffer.getDouble();

View File

@ -1,20 +1,14 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Utils;
public class ClientPluginMessagePacket implements ClientPlayPacket {
public class ClientPluginMessagePacket extends ClientPlayPacket {
private String identifier;
private byte[] data;
@Override
public void process(Player player) {
}
@Override
public void read(Buffer buffer) {
this.identifier = Utils.readString(buffer);

View File

@ -1,24 +1,18 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Utils;
public class ClientSettingsPacket implements ClientPlayPacket {
public class ClientSettingsPacket extends ClientPlayPacket {
private String locale;
private byte viewDistance;
public String locale;
public byte viewDistance;
// TODO chat mode
private boolean chatColors;
private byte displayedSkinParts;
public boolean chatColors;
public byte displayedSkinParts;
// TODO main hand
@Override
public void process(Player player) {
}
@Override
public void read(Buffer buffer) {
this.locale = Utils.readString(buffer);

View File

@ -0,0 +1,18 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientSteerVehiclePacket extends ClientPlayPacket {
public float sideways;
public float forward;
public byte flags;
@Override
public void read(Buffer buffer) {
this.sideways = buffer.getFloat();
this.forward = buffer.getFloat();
this.flags = buffer.getByte();
}
}

View File

@ -1,19 +1,13 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Utils;
public class ClientTeleportConfirmPacket implements ClientPlayPacket {
public class ClientTeleportConfirmPacket extends ClientPlayPacket {
public int teleportId;
@Override
public void process(Player player) {
}
@Override
public void read(Buffer buffer) {
this.teleportId = Utils.readVarInt(buffer);

View File

@ -5,7 +5,7 @@ import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.Utils;
public class ClientUseEntityPacket implements ClientPlayPacket {
public class ClientUseEntityPacket extends ClientPlayPacket {
private int target;
private Type type;
@ -14,11 +14,6 @@ public class ClientUseEntityPacket implements ClientPlayPacket {
private float z;
private Player.Hand hand;
@Override
public void process(Player player) {
}
@Override
public void read(Buffer buffer) {
this.target = Utils.readVarInt(buffer);
@ -32,7 +27,7 @@ public class ClientUseEntityPacket implements ClientPlayPacket {
this.hand = Player.Hand.values()[Utils.readVarInt(buffer)];
}
public static enum Type {
public enum Type {
INTERACT,
ATTACK,

View File

@ -1,18 +0,0 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class TestPacket implements ClientPlayPacket {
@Override
public void process(Player player) {
}
@Override
public void read(Buffer buffer) {
System.out.println("Hey c'est moi");
}
}

View File

@ -0,0 +1,24 @@
package fr.themode.minestom.net.packet.server.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.utils.Utils;
public class CollectItemPacket implements ServerPacket {
public int collectedEntityId;
public int collectorEntityId;
public int pickupItemCount;
@Override
public void write(Buffer buffer) {
Utils.writeVarInt(buffer, collectedEntityId);
Utils.writeVarInt(buffer, collectorEntityId);
Utils.writeVarInt(buffer, pickupItemCount);
}
@Override
public int getId() {
return 0x55;
}
}

View File

@ -0,0 +1,25 @@
package fr.themode.minestom.net.packet.server.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.utils.Utils;
public class SetPassengersPacket implements ServerPacket {
public int vehicleEntityId;
public int[] passengersId;
@Override
public void write(Buffer buffer) {
Utils.writeVarInt(buffer, vehicleEntityId);
Utils.writeVarInt(buffer, passengersId.length);
for (int passengerId : passengersId) {
Utils.writeVarInt(buffer, passengerId);
}
}
@Override
public int getId() {
return 0x4A;
}
}