diff --git a/src/main/java/fr/themode/minestom/entity/Entity.java b/src/main/java/fr/themode/minestom/entity/Entity.java index c44974e07..7bc3af2b7 100644 --- a/src/main/java/fr/themode/minestom/entity/Entity.java +++ b/src/main/java/fr/themode/minestom/entity/Entity.java @@ -4,10 +4,12 @@ import fr.themode.minestom.instance.Chunk; import fr.themode.minestom.instance.Instance; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; public class Entity { - private static volatile int lastEntityId; + private static AtomicInteger lastEntityId = new AtomicInteger(); + protected Instance instance; protected double lastX, lastY, lastZ; protected double x, y, z; @@ -22,7 +24,7 @@ public class Entity { } private static int generateId() { - return ++lastEntityId; + return lastEntityId.incrementAndGet(); } public int getEntityId() { diff --git a/src/main/java/fr/themode/minestom/entity/EntityManager.java b/src/main/java/fr/themode/minestom/entity/EntityManager.java index f600469c4..2e866b542 100644 --- a/src/main/java/fr/themode/minestom/entity/EntityManager.java +++ b/src/main/java/fr/themode/minestom/entity/EntityManager.java @@ -18,7 +18,6 @@ public class EntityManager { for (Instance instance : instanceManager.getInstances()) { // Creatures - //long time = System.nanoTime(); for (EntityCreature creature : instance.getCreatures()) { creaturesPool.submit(() -> { boolean shouldRemove = creature.shouldRemove(); @@ -31,19 +30,16 @@ public class EntityManager { } }); } - /*creaturesPool.shutdown(); - while (!creaturesPool.isTerminated()) { - - } - System.out.println("delay: " + (System.nanoTime() - time)); - creaturesPool = Executors.newFixedThreadPool(4);*/ // Players for (Player player : instance.getPlayers()) { playersPool.submit(() -> { - player.update(); boolean shouldRemove = player.shouldRemove(); - if (shouldRemove) { + if (!shouldRemove) { + player.update(); + } + + if (player.shouldRemove()) { instance.removeEntity(player); } }); diff --git a/src/main/java/fr/themode/minestom/entity/Player.java b/src/main/java/fr/themode/minestom/entity/Player.java index c910721c0..bed8701e0 100644 --- a/src/main/java/fr/themode/minestom/entity/Player.java +++ b/src/main/java/fr/themode/minestom/entity/Player.java @@ -1,9 +1,9 @@ package fr.themode.minestom.entity; import fr.themode.minestom.Main; -import fr.themode.minestom.net.packet.server.play.EntityTeleportPacket; -import fr.themode.minestom.net.packet.server.play.PlayerPositionAndLookPacket; -import fr.themode.minestom.net.packet.server.play.UpdateViewPositionPacket; +import fr.themode.minestom.inventory.PlayerInventory; +import fr.themode.minestom.item.ItemStack; +import fr.themode.minestom.net.packet.server.play.*; import fr.themode.minestom.net.player.PlayerConnection; import java.util.UUID; @@ -18,11 +18,17 @@ public class Player extends LivingEntity { private String username; private PlayerConnection playerConnection; + private GameMode gameMode; + private PlayerInventory inventory; + private short heldSlot; + // TODO set proper UUID public Player(UUID uuid, String username, PlayerConnection playerConnection) { this.uuid = uuid; this.username = username; this.playerConnection = playerConnection; + + this.inventory = new PlayerInventory(this); } @Override @@ -63,6 +69,43 @@ public class Player extends LivingEntity { return playerConnection; } + public PlayerInventory getInventory() { + return inventory; + } + + public GameMode getGameMode() { + return gameMode; + } + + public void setGameMode(GameMode gameMode) { + ChangeGameStatePacket changeGameStatePacket = new ChangeGameStatePacket(); + changeGameStatePacket.reason = ChangeGameStatePacket.Reason.CHANGE_GAMEMODE; + changeGameStatePacket.value = gameMode.getId(); + playerConnection.sendPacket(changeGameStatePacket); + refreshGameMode(gameMode); + } + + public void setHeldItemSlot(short slot) { + if (slot < 0 || slot > 8) + throw new IllegalArgumentException("Slot has to be between 0 and 8"); + HeldItemChangePacket heldItemChangePacket = new HeldItemChangePacket(); + heldItemChangePacket.slot = slot; + playerConnection.sendPacket(heldItemChangePacket); + refreshHeldSlot(slot); + } + + public short getHeldSlot() { + return heldSlot; + } + + public ItemStack getHeldItemStack() { + return inventory.getItemStack(heldSlot); + } + + public void refreshGameMode(GameMode gameMode) { + this.gameMode = gameMode; + } + public void refreshView(float yaw, float pitch) { this.yaw = yaw; this.pitch = pitch; @@ -84,6 +127,10 @@ public class Player extends LivingEntity { this.lastKeepAlive = lastKeepAlive; } + public void refreshHeldSlot(short slot) { + this.heldSlot = slot; + } + public long getLastKeepAlive() { return lastKeepAlive; } diff --git a/src/main/java/fr/themode/minestom/instance/Instance.java b/src/main/java/fr/themode/minestom/instance/Instance.java index 94f11f183..f6b36476e 100644 --- a/src/main/java/fr/themode/minestom/instance/Instance.java +++ b/src/main/java/fr/themode/minestom/instance/Instance.java @@ -3,18 +3,19 @@ package fr.themode.minestom.instance; import fr.themode.minestom.entity.Entity; import fr.themode.minestom.entity.EntityCreature; import fr.themode.minestom.entity.Player; +import fr.themode.minestom.net.packet.server.play.ChunkDataPacket; import fr.themode.minestom.utils.GroupedCollections; import java.util.Collections; -import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CopyOnWriteArraySet; public class Instance { private UUID uniqueId; - private Set chunksSet = Collections.synchronizedSet(new HashSet<>()); + private Set chunksSet = new CopyOnWriteArraySet<>(); public Instance(UUID uniqueId) { this.uniqueId = uniqueId; @@ -30,6 +31,7 @@ public class Instance { } synchronized (chunk) { chunk.setBlock(x % 16, y, z % 16, block); + sendChunkUpdate(chunk); // TODO partial chunk data } } @@ -61,7 +63,9 @@ public class Instance { // TODO based on distance with players getPlayers().forEach(p -> ((EntityCreature) entity).addViewer(p)); } else if (entity instanceof Player) { - getCreatures().forEach(entityCreature -> entityCreature.addViewer((Player) entity)); + Player player = (Player) entity; + sendChunks(player); + getCreatures().forEach(entityCreature -> entityCreature.addViewer(player)); } Chunk chunk = getChunkAt(entity.getX(), entity.getZ()); @@ -107,4 +111,20 @@ public class Instance { this.chunksSet.add(chunk); return chunk; } + + private void sendChunks(Player player) { + ChunkDataPacket chunkDataPacket = new ChunkDataPacket(); + chunkDataPacket.fullChunk = true; + for (Chunk chunk : getChunks()) { + chunkDataPacket.chunk = chunk; + player.getPlayerConnection().sendPacket(chunkDataPacket); + } + } + + private void sendChunkUpdate(Chunk chunk) { + ChunkDataPacket chunkDataPacket = new ChunkDataPacket(); + chunkDataPacket.fullChunk = true; + chunkDataPacket.chunk = chunk; + getPlayers().forEach(player -> player.getPlayerConnection().sendPacket(chunkDataPacket)); + } } diff --git a/src/main/java/fr/themode/minestom/inventory/PlayerInventory.java b/src/main/java/fr/themode/minestom/inventory/PlayerInventory.java new file mode 100644 index 000000000..14e0c7d91 --- /dev/null +++ b/src/main/java/fr/themode/minestom/inventory/PlayerInventory.java @@ -0,0 +1,62 @@ +package fr.themode.minestom.inventory; + +import fr.themode.minestom.entity.Player; +import fr.themode.minestom.item.ItemStack; +import fr.themode.minestom.net.packet.server.play.WindowItemsPacket; +import fr.themode.minestom.net.player.PlayerConnection; + +public class PlayerInventory { + + private Player player; + private ItemStack[] items = new ItemStack[45]; + + public PlayerInventory(Player player) { + this.player = player; + } + + public ItemStack getItemStack(int slot) { + ItemStack item = this.items[convertSlot(slot)]; + return item != null ? item : ItemStack.AIR_ITEM; + } + + public void setItemStack(int slot, ItemStack itemStack) { + this.items[convertSlot(slot)] = itemStack; + } + + public void setHelmet(ItemStack itemStack) { + this.items[5] = itemStack; + } + + public void setChestplate(ItemStack itemStack) { + this.items[6] = itemStack; + } + + public void setLeggings(ItemStack itemStack) { + this.items[7] = itemStack; + } + + public void setBoots(ItemStack itemStack) { + this.items[8] = itemStack; + } + + public void update() { + PlayerConnection playerConnection = player.getPlayerConnection(); + + WindowItemsPacket windowItemsPacket = new WindowItemsPacket(); + windowItemsPacket.windowId = 0; // player inventory ID + windowItemsPacket.count = (short) items.length; + windowItemsPacket.items = items; + playerConnection.sendPacket(windowItemsPacket); + } + + private int convertSlot(int slot) { + if (slot >= 0 && slot <= 9 * 4) { + int row = slot / 9; + int place = slot % 9; + int converted = 9 * (4 - 1 - row) + place + 9; + return converted; + } + return slot; + } + +} diff --git a/src/main/java/fr/themode/minestom/item/ItemStack.java b/src/main/java/fr/themode/minestom/item/ItemStack.java new file mode 100644 index 000000000..a31220a90 --- /dev/null +++ b/src/main/java/fr/themode/minestom/item/ItemStack.java @@ -0,0 +1,22 @@ +package fr.themode.minestom.item; + +public class ItemStack { + + public static final ItemStack AIR_ITEM = new ItemStack(0, (byte) 1); + + private int itemId; + private byte count; + + public ItemStack(int itemId, byte count) { + this.itemId = itemId; + this.count = count; + } + + public int getItemId() { + return itemId; + } + + public byte getCount() { + return count; + } +} diff --git a/src/main/java/fr/themode/minestom/net/packet/client/handler/ClientPlayPacketsHandler.java b/src/main/java/fr/themode/minestom/net/packet/client/handler/ClientPlayPacketsHandler.java index d4df63f13..0a1938f92 100644 --- a/src/main/java/fr/themode/minestom/net/packet/client/handler/ClientPlayPacketsHandler.java +++ b/src/main/java/fr/themode/minestom/net/packet/client/handler/ClientPlayPacketsHandler.java @@ -18,5 +18,8 @@ public class ClientPlayPacketsHandler extends ClientPacketsHandler { register(0x1B, ClientEntityActionPacket.class); register(0x0E, ClientUseEntityPacket.class); register(0x03, ClientChatMessagePacket.class); + register(0x1A, ClientPlayerDiggingPacket.class); + register(0x2C, ClientPlayerBlockPlacementPacket.class); + register(0x23, ClientHeldItemChangePacket.class); } } diff --git a/src/main/java/fr/themode/minestom/net/packet/client/login/LoginStartPacket.java b/src/main/java/fr/themode/minestom/net/packet/client/login/LoginStartPacket.java index 4e6bf31cc..1b9e8653c 100644 --- a/src/main/java/fr/themode/minestom/net/packet/client/login/LoginStartPacket.java +++ b/src/main/java/fr/themode/minestom/net/packet/client/login/LoginStartPacket.java @@ -6,14 +6,18 @@ import fr.themode.minestom.entity.GameMode; import fr.themode.minestom.entity.Player; import fr.themode.minestom.entity.demo.ChickenCreature; import fr.themode.minestom.instance.Block; -import fr.themode.minestom.instance.Chunk; import fr.themode.minestom.instance.Instance; +import fr.themode.minestom.inventory.PlayerInventory; +import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.net.ConnectionManager; import fr.themode.minestom.net.ConnectionState; import fr.themode.minestom.net.packet.client.ClientPreplayPacket; import fr.themode.minestom.net.packet.server.login.JoinGamePacket; import fr.themode.minestom.net.packet.server.login.LoginSuccessPacket; -import fr.themode.minestom.net.packet.server.play.*; +import fr.themode.minestom.net.packet.server.play.PlayerInfoPacket; +import fr.themode.minestom.net.packet.server.play.PlayerPositionAndLookPacket; +import fr.themode.minestom.net.packet.server.play.SpawnPlayerPacket; +import fr.themode.minestom.net.packet.server.play.SpawnPositionPacket; import fr.themode.minestom.net.player.PlayerConnection; import fr.themode.minestom.utils.Utils; import fr.themode.minestom.world.Dimension; @@ -32,7 +36,7 @@ public class LoginStartPacket implements ClientPreplayPacket { instance = Main.getInstanceManager().createInstance(); for (int x = -64; x < 64; x++) for (int z = -64; z < 64; z++) { - instance.setBlock(x, 4, z, new Block(1)); + instance.setBlock(x, 4, z, new Block(10)); } } @@ -52,11 +56,14 @@ public class LoginStartPacket implements ClientPreplayPacket { connection.setConnectionState(ConnectionState.PLAY); connectionManager.createPlayer(uuids.get(username), username, connection); Player player = connectionManager.getPlayer(connection); + GameMode gameMode = GameMode.CREATIVE; + + player.refreshGameMode(gameMode); // TODO complete login sequence with optionals packets JoinGamePacket joinGamePacket = new JoinGamePacket(); joinGamePacket.entityId = player.getEntityId(); - joinGamePacket.gameMode = GameMode.CREATIVE; + joinGamePacket.gameMode = gameMode; joinGamePacket.dimension = Dimension.OVERWORLD; joinGamePacket.maxPlayers = 0; // Unused joinGamePacket.levelType = "default"; @@ -71,12 +78,6 @@ public class LoginStartPacket implements ClientPreplayPacket { // TODO player abilities player.setInstance(instance); - ChunkDataPacket chunkDataPacket = new ChunkDataPacket(); - chunkDataPacket.fullChunk = true; - for (Chunk chunk : instance.getChunks()) { - chunkDataPacket.chunk = chunk; - connection.sendPacket(chunkDataPacket); - } SpawnPositionPacket spawnPositionPacket = new SpawnPositionPacket(); @@ -102,13 +103,12 @@ public class LoginStartPacket implements ClientPreplayPacket { playerInfoPacket.playerInfos.add(addPlayer); connection.sendPacket(playerInfoPacket); - for (int x = -10; x < 10; x++) - for (int z = -10; z < 10; z++) { + for (int x = -5; x < 5; x++) + for (int z = -5; z < 5; z++) { // TODO test entity ChickenCreature chickenCreature = new ChickenCreature(); chickenCreature.refreshPosition(0 + (double) x * 1, 5, 0 + (double) z * 1); chickenCreature.setInstance(instance); - //instance.addEntity(chickenCreature); } @@ -138,7 +138,12 @@ public class LoginStartPacket implements ClientPreplayPacket { connection.sendPacket(pInfoPacket); connection.sendPacket(spawnPacket); } - System.out.println("HAHAHAHHAHHAH " + player.getUuid()); + //System.out.println("HAHAHAHHAHHAH " + player.getUuid()); + + PlayerInventory inventory = player.getInventory(); + inventory.setItemStack(1, new ItemStack(1, (byte) 1)); + inventory.update(); + } @Override diff --git a/src/main/java/fr/themode/minestom/net/packet/client/play/ClientHeldItemChangePacket.java b/src/main/java/fr/themode/minestom/net/packet/client/play/ClientHeldItemChangePacket.java new file mode 100644 index 000000000..94733cddd --- /dev/null +++ b/src/main/java/fr/themode/minestom/net/packet/client/play/ClientHeldItemChangePacket.java @@ -0,0 +1,22 @@ +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 short slot; + + @Override + public void process(Player player) { + if (slot < 0 || slot > 8) + return; + player.refreshHeldSlot(slot); + } + + @Override + public void read(Buffer buffer) { + buffer.getShort(); + } +} diff --git a/src/main/java/fr/themode/minestom/net/packet/client/play/ClientPlayerBlockPlacementPacket.java b/src/main/java/fr/themode/minestom/net/packet/client/play/ClientPlayerBlockPlacementPacket.java new file mode 100644 index 000000000..d30eaaddb --- /dev/null +++ b/src/main/java/fr/themode/minestom/net/packet/client/play/ClientPlayerBlockPlacementPacket.java @@ -0,0 +1,43 @@ +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.Block; +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 Hand hand; + public Position position; + public ClientPlayerDiggingPacket.BlockFace blockFace; + public float cursorPositionX, cursorPositionY, cursorPositionZ; + public boolean insideBlock; + + @Override + public void process(Player player) { + Instance instance = player.getInstance(); + if (instance == null) + return; + instance.setBlock(position.getX(), position.getY(), position.getZ(), new Block(2)); + } + + @Override + public void read(Buffer buffer) { + this.hand = Hand.values()[Utils.readVarInt(buffer)]; + this.position = Utils.readPosition(buffer); + this.blockFace = ClientPlayerDiggingPacket.BlockFace.values()[Utils.readVarInt(buffer)]; + this.cursorPositionX = buffer.getFloat(); + this.cursorPositionY = buffer.getFloat(); + this.cursorPositionZ = buffer.getFloat(); + this.insideBlock = buffer.getBoolean(); + } + + public enum Hand { + MAIN_HAND, + OFF_HAND; + } + +} diff --git a/src/main/java/fr/themode/minestom/net/packet/client/play/ClientPlayerDiggingPacket.java b/src/main/java/fr/themode/minestom/net/packet/client/play/ClientPlayerDiggingPacket.java new file mode 100644 index 000000000..0a1c1e390 --- /dev/null +++ b/src/main/java/fr/themode/minestom/net/packet/client/play/ClientPlayerDiggingPacket.java @@ -0,0 +1,58 @@ +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.Block; +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 ClientPlayerDiggingPacket implements 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(), new Block(0)); + } + } + break; + } + } + + @Override + public void read(Buffer buffer) { + this.status = Status.values()[Utils.readVarInt(buffer)]; + this.position = Utils.readPosition(buffer); + this.blockFace = BlockFace.values()[Utils.readVarInt(buffer)]; + } + + public enum Status { + STARTED_DIGGING, + CANCELLED_DIGGING, + FINISHED_DIGGING, + DROP_ITEM_STACK, + DROP_ITEM, + UPDATE_ITEM_STATE, + SWAP_ITEM_HAND; + } + + public enum BlockFace { + BOTTOM, + TOP, + NORTH, + SOUTH, + WEST, + EAST; + } + +} diff --git a/src/main/java/fr/themode/minestom/net/packet/server/play/ChangeGameStatePacket.java b/src/main/java/fr/themode/minestom/net/packet/server/play/ChangeGameStatePacket.java new file mode 100644 index 000000000..3bab03153 --- /dev/null +++ b/src/main/java/fr/themode/minestom/net/packet/server/play/ChangeGameStatePacket.java @@ -0,0 +1,36 @@ +package fr.themode.minestom.net.packet.server.play; + +import fr.adamaq01.ozao.net.Buffer; +import fr.themode.minestom.net.packet.server.ServerPacket; + +public class ChangeGameStatePacket implements ServerPacket { + + public Reason reason; + public float value; + + @Override + public void write(Buffer buffer) { + buffer.putByte((byte) reason.ordinal()); + buffer.putFloat(value); + } + + @Override + public int getId() { + return 0x1E; + } + + public enum Reason { + INVALID_BED, + END_RAINING, + BEGIN_RAINING, + CHANGE_GAMEMODE, + EXIT_END, + DEMO_MESSAGE, + ARROW_HITTING_PLAYER, + FADE_VALUE, + FADE_TIME, + PLAY_PUFFERFISH_STING_SOUND, + PLAYER_ELDER_GUARDIAN_MOB_APPEARANCE; + } + +} diff --git a/src/main/java/fr/themode/minestom/net/packet/server/play/HeldItemChangePacket.java b/src/main/java/fr/themode/minestom/net/packet/server/play/HeldItemChangePacket.java new file mode 100644 index 000000000..233f1e285 --- /dev/null +++ b/src/main/java/fr/themode/minestom/net/packet/server/play/HeldItemChangePacket.java @@ -0,0 +1,19 @@ +package fr.themode.minestom.net.packet.server.play; + +import fr.adamaq01.ozao.net.Buffer; +import fr.themode.minestom.net.packet.server.ServerPacket; + +public class HeldItemChangePacket implements ServerPacket { + + public short slot; + + @Override + public void write(Buffer buffer) { + buffer.putShort(slot); + } + + @Override + public int getId() { + return 0x3F; + } +} diff --git a/src/main/java/fr/themode/minestom/net/packet/server/play/WindowItemsPacket.java b/src/main/java/fr/themode/minestom/net/packet/server/play/WindowItemsPacket.java index 4b255af34..644c913b7 100644 --- a/src/main/java/fr/themode/minestom/net/packet/server/play/WindowItemsPacket.java +++ b/src/main/java/fr/themode/minestom/net/packet/server/play/WindowItemsPacket.java @@ -1,12 +1,15 @@ package fr.themode.minestom.net.packet.server.play; import fr.adamaq01.ozao.net.Buffer; +import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.net.packet.server.ServerPacket; +import fr.themode.minestom.utils.Utils; public class WindowItemsPacket implements ServerPacket { public byte windowId; public short count; + public ItemStack[] items; // TODO slot data (Array of Slot) @@ -14,12 +17,24 @@ public class WindowItemsPacket implements ServerPacket { public void write(Buffer buffer) { buffer.putByte(windowId); buffer.putShort(count); - // TODO replace with actual array of slot - buffer.putBoolean(false); // Not present + + if (items == null) + return; + for (int i = 0; i < items.length; i++) { + ItemStack item = items[i]; + if (item == null) { + buffer.putBoolean(false); + } else { + buffer.putBoolean(true); + Utils.writeVarInt(buffer, item.getItemId()); + buffer.putByte(item.getCount()); + buffer.putByte((byte) 0); // End nbt TODO + } + } } @Override public int getId() { - return 0x15; + return 0x14; } } diff --git a/src/main/java/fr/themode/minestom/utils/Position.java b/src/main/java/fr/themode/minestom/utils/Position.java new file mode 100644 index 000000000..9ef537750 --- /dev/null +++ b/src/main/java/fr/themode/minestom/utils/Position.java @@ -0,0 +1,36 @@ +package fr.themode.minestom.utils; + +public class Position { + + private int x, y, z; + + public Position(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + public int getZ() { + return z; + } + + public void setZ(int z) { + this.z = z; + } +} diff --git a/src/main/java/fr/themode/minestom/utils/Utils.java b/src/main/java/fr/themode/minestom/utils/Utils.java index 73f3ff874..02ea63fcc 100644 --- a/src/main/java/fr/themode/minestom/utils/Utils.java +++ b/src/main/java/fr/themode/minestom/utils/Utils.java @@ -121,7 +121,15 @@ public class Utils { } public static void writePosition(Buffer buffer, int x, int y, int z) { - buffer.putLong(((x & 0x3FFFFFF) << 38) | ((y & 0xFFF) << 26) | (z & 0x3FFFFFF)); + buffer.putLong(((x & 0x3FFFFFF) << 38) | ((z & 0x3FFFFFF) << 12) | (y & 0xFFF)); + } + + public static Position readPosition(Buffer buffer) { + long val = buffer.getLong(); + int x = (int) (val >> 38); + int y = (int) (val & 0xFFF); + int z = (int) (val << 26 >> 38); + return new Position(x, y, z); } public static void writeBlocks(Buffer buffer, Block[] blocks, int bitsPerEntry) {