diff --git a/src/main/java/ru/nanit/limbo/connection/ClientConnection.java b/src/main/java/ru/nanit/limbo/connection/ClientConnection.java index 4d4324b..72f7b98 100644 --- a/src/main/java/ru/nanit/limbo/connection/ClientConnection.java +++ b/src/main/java/ru/nanit/limbo/connection/ClientConnection.java @@ -131,6 +131,9 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { writePacket(PacketSnapshots.PACKET_JOIN_GAME); writePacket(PacketSnapshots.PACKET_PLAYER_ABILITIES); writePacket(PacketSnapshots.PACKET_PLAYER_POS); + if (clientVersion.moreOrEqual(Version.V1_19_3)) { + writePacket(PacketSnapshots.PACKET_SPAWN_POSITION); + } if (server.getConfig().isUsePlayerList() || clientVersion.equals(Version.V1_16_4)) writePacket(PacketSnapshots.PACKET_PLAYER_INFO); diff --git a/src/main/java/ru/nanit/limbo/connection/PacketSnapshots.java b/src/main/java/ru/nanit/limbo/connection/PacketSnapshots.java index 6d1f929..6c993bd 100644 --- a/src/main/java/ru/nanit/limbo/connection/PacketSnapshots.java +++ b/src/main/java/ru/nanit/limbo/connection/PacketSnapshots.java @@ -33,6 +33,7 @@ public final class PacketSnapshots { public static PacketSnapshot PACKET_LOGIN_SUCCESS; public static PacketSnapshot PACKET_JOIN_GAME; + public static PacketSnapshot PACKET_SPAWN_POSITION; public static PacketSnapshot PACKET_PLUGIN_MESSAGE; public static PacketSnapshot PACKET_PLAYER_ABILITIES; public static PacketSnapshot PACKET_PLAYER_INFO; @@ -99,8 +100,14 @@ public final class PacketSnapshots { info.setGameMode(server.getConfig().getGameMode()); info.setUuid(uuid); + PacketSpawnPosition packetSpawnPosition = new PacketSpawnPosition(); + packetSpawnPosition.setX((long) server.getConfig().getSpawnPosition().getX()); + packetSpawnPosition.setY((long) server.getConfig().getSpawnPosition().getY()); + packetSpawnPosition.setZ((long) server.getConfig().getSpawnPosition().getZ()); + PACKET_LOGIN_SUCCESS = PacketSnapshot.of(loginSuccess); PACKET_JOIN_GAME = PacketSnapshot.of(joinGame); + PACKET_SPAWN_POSITION = PacketSnapshot.of(packetSpawnPosition); PACKET_PLAYER_ABILITIES = PacketSnapshot.of(playerAbilities); PACKET_PLAYER_POS = PacketSnapshot.of(positionAndLook); PACKET_PLAYER_INFO = PacketSnapshot.of(info); diff --git a/src/main/java/ru/nanit/limbo/protocol/ByteMessage.java b/src/main/java/ru/nanit/limbo/protocol/ByteMessage.java index be4ef13..edc5995 100644 --- a/src/main/java/ru/nanit/limbo/protocol/ByteMessage.java +++ b/src/main/java/ru/nanit/limbo/protocol/ByteMessage.java @@ -34,6 +34,9 @@ import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.BitSet; +import java.util.EnumSet; import java.util.UUID; public class ByteMessage extends ByteBuf { @@ -190,6 +193,24 @@ public class ByteMessage extends ByteBuf { } } + public > void writeEnumSet(EnumSet enumset, Class oclass) { + E[] enums = oclass.getEnumConstants(); + BitSet bits = new BitSet(enums.length); + + for (int i = 0; i < enums.length; ++i) { + bits.set(i, enumset.contains(enums[i])); + } + + writeFixedBitSet(bits, enums.length, buf); + } + + private static void writeFixedBitSet(BitSet bits, int size, ByteBuf buf) { + if (bits.length() > size) { + throw new StackOverflowError("BitSet too large (expected " + size + " got " + bits.size() + ")"); + } + buf.writeBytes(Arrays.copyOf(bits.toByteArray(), (size + 8) >> 3)); + } + /* Delegated methods */ @Override diff --git a/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketPlayerInfo.java b/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketPlayerInfo.java index 4bb5fb3..efaa639 100644 --- a/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketPlayerInfo.java +++ b/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketPlayerInfo.java @@ -21,6 +21,7 @@ import ru.nanit.limbo.protocol.ByteMessage; import ru.nanit.limbo.protocol.PacketOut; import ru.nanit.limbo.protocol.registry.Version; +import java.util.EnumSet; import java.util.UUID; /** @@ -46,6 +47,24 @@ public class PacketPlayerInfo implements PacketOut { @Override public void encode(ByteMessage msg, Version version) { + if (version.moreOrEqual(Version.V1_19_3)) { + EnumSet actions = EnumSet.noneOf(Action.class); + actions.add(Action.ADD_PLAYER); + actions.add(Action.UPDATE_LISTED); + actions.add(Action.UPDATE_GAMEMODE); + msg.writeEnumSet(actions, Action.class); + + msg.writeVarInt(1); // Array length (1 element) + msg.writeUuid(uuid); // UUID + msg.writeString(username); //Username + msg.writeVarInt(0); //Properties (0 is empty) + + msg.writeBoolean(true); //Update listed + + msg.writeVarInt(gameMode); //Gamemode + + return; + } msg.writeVarInt(0); // Add player action msg.writeVarInt(1); msg.writeUuid(uuid); @@ -59,4 +78,13 @@ public class PacketPlayerInfo implements PacketOut { } } + public static enum Action { + + ADD_PLAYER, + INITIALIZE_CHAT, + UPDATE_GAMEMODE, + UPDATE_LISTED, + UPDATE_LATENCY, + UPDATE_DISPLAY_NAME; + } } diff --git a/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketSpawnPosition.java b/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketSpawnPosition.java new file mode 100644 index 0000000..559cdc3 --- /dev/null +++ b/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketSpawnPosition.java @@ -0,0 +1,34 @@ +package ru.nanit.limbo.protocol.packets.play; + +import ru.nanit.limbo.protocol.ByteMessage; +import ru.nanit.limbo.protocol.PacketOut; +import ru.nanit.limbo.protocol.registry.Version; + +public class PacketSpawnPosition implements PacketOut { + + private long x; + private long y; + private long z; + + public void setX(long x) { + this.x = x; + } + + public void setY(long y) { + this.y = y; + } + + public void setZ(long z) { + this.z = z; + } + + @Override + public void encode(ByteMessage msg, Version version) { + msg.writeLong(encodePosition(x, y ,z)); + msg.writeFloat(0); + } + + private static long encodePosition(long x, long y, long z) { + return ((x & 0x3FFFFFF) << 38) | ((z & 0x3FFFFFF) << 12) | (y & 0xFFF); + } +} diff --git a/src/main/java/ru/nanit/limbo/protocol/registry/State.java b/src/main/java/ru/nanit/limbo/protocol/registry/State.java index 2e419fc..378b9b9 100644 --- a/src/main/java/ru/nanit/limbo/protocol/registry/State.java +++ b/src/main/java/ru/nanit/limbo/protocol/registry/State.java @@ -86,7 +86,8 @@ public enum State { map(0x10, V1_16, V1_16_4), map(0x0F, V1_17, V1_18_2), map(0x11, V1_19, V1_19), - map(0x12, V1_19_1, V1_19_1) + map(0x12, V1_19_1, V1_19_1), + map(0x11, V1_19_3, V1_19_3) ); clientBound.register(PacketDeclareCommands::new, @@ -95,7 +96,8 @@ public enum State { map(0x11, V1_16, V1_16_1), map(0x10, V1_16_2, V1_16_4), map(0x12, V1_17, V1_18_2), - map(0x0F, V1_19, V1_19_1) + map(0x0F, V1_19, V1_19_1), + map(0x0E, V1_19_3, V1_19_3) ); clientBound.register(PacketJoinGame::new, map(0x01, V1_8, V1_8), @@ -106,7 +108,8 @@ public enum State { map(0x24, V1_16_2, V1_16_4), map(0x26, V1_17, V1_18_2), map(0x23, V1_19, V1_19), - map(0x25, V1_19_1, V1_19_1) + map(0x25, V1_19_1, V1_19_1), + map(0x24, V1_19_3, V1_19_3) ); clientBound.register(PacketPluginMessage::new, map(0x19, V1_13, V1_13_2), @@ -116,7 +119,8 @@ public enum State { map(0x17, V1_16_2, V1_16_4), map(0x18, V1_17, V1_18_2), map(0x15, V1_19, V1_19), - map(0x16, V1_19_1, V1_19_1) + map(0x16, V1_19_1, V1_19_1), + map(0x15, V1_19_3, V1_19_3) ); clientBound.register(PacketPlayerAbilities::new, map(0x39, V1_8, V1_8), @@ -129,7 +133,8 @@ public enum State { map(0x30, V1_16_2, V1_16_4), map(0x32, V1_17, V1_18_2), map(0x2F, V1_19, V1_19), - map(0x31, V1_19_1, V1_19_1) + map(0x31, V1_19_1, V1_19_1), + map(0x30, V1_19_3, V1_19_3) ); clientBound.register(PacketPlayerPositionAndLook::new, map(0x08, V1_8, V1_8), @@ -142,7 +147,8 @@ public enum State { map(0x34, V1_16_2, V1_16_4), map(0x38, V1_17, V1_18_2), map(0x36, V1_19, V1_19), - map(0x39, V1_19_1, V1_19_1) + map(0x39, V1_19_1, V1_19_1), + map(0x38, V1_19_3, V1_19_3) ); clientBound.register(PacketKeepAlive::new, map(0x00, V1_8, V1_8), @@ -154,7 +160,8 @@ public enum State { map(0x1F, V1_16_2, V1_16_4), map(0x21, V1_17, V1_18_2), map(0x1E, V1_19, V1_19), - map(0x20, V1_19_1, V1_19_1) + map(0x20, V1_19_1, V1_19_1), + map(0x1F, V1_19_3, V1_19_3) ); clientBound.register(PacketChatMessage::new, map(0x02, V1_8, V1_8), @@ -164,14 +171,15 @@ public enum State { map(0x0E, V1_16, V1_16_4), map(0x0F, V1_17, V1_18_2), map(0x5F, V1_19, V1_19), - map(0x62, V1_19_1, V1_19_1) + map(0x62, V1_19_1, V1_19_1), + map(0x60, V1_19_3, V1_19_3) ); clientBound.register(PacketBossBar::new, map(0x0C, V1_9, V1_14_4), map(0x0D, V1_15, V1_15_2), map(0x0C, V1_16, V1_16_4), map(0x0D, V1_17, V1_18_2), - map(0x0A, V1_19, V1_19_1) + map(0x0A, V1_19, V1_19_3) ); clientBound.register(PacketPlayerInfo::new, map(0x38, V1_8, V1_8), @@ -184,7 +192,8 @@ public enum State { map(0x32, V1_16_2, V1_16_4), map(0x36, V1_17, V1_18_2), map(0x34, V1_19, V1_19), - map(0x37, V1_19_1, V1_19_1) + map(0x37, V1_19_1, V1_19_1), + map(0x36, V1_19_3, V1_19_3) ); clientBound.register(PacketTitleLegacy::new, map(0x45, V1_8, V1_11_1), @@ -198,17 +207,20 @@ public enum State { clientBound.register(PacketTitleSetTitle::new, map(0x59, V1_17, V1_17_1), map(0x5A, V1_18, V1_19), - map(0x5D, V1_19_1, V1_19_1) + map(0x5D, V1_19_1, V1_19_1), + map(0x5B, V1_19_3, V1_19_3) ); clientBound.register(PacketTitleSetSubTitle::new, map(0x57, V1_17, V1_17_1), map(0x58, V1_18, V1_19), - map(0x5B, V1_19_1, V1_19_1) + map(0x5B, V1_19_1, V1_19_1), + map(0x59, V1_19_3, V1_19_3) ); clientBound.register(PacketTitleTimes::new, map(0x5A, V1_17, V1_17_1), map(0x5B, V1_18, V1_19), - map(0x5E, V1_19_1, V1_19_1) + map(0x5E, V1_19_1, V1_19_1), + map(0x5C, V1_19_3, V1_19_3) ); clientBound.register(PacketPlayerListHeader::new, map(0x47, V1_8, V1_8), @@ -223,7 +235,11 @@ public enum State { map(0x5E, V1_17, V1_17_1), map(0x5F, V1_18, V1_18_2), map(0x60, V1_19, V1_19), - map(0x63, V1_19_1, V1_19_1) + map(0x63, V1_19_1, V1_19_1), + map(0x61, V1_19_3, V1_19_3) + ); + clientBound.register(PacketSpawnPosition::new, + map(0x4C, V1_19_3, V1_19_3) ); } }; diff --git a/src/main/java/ru/nanit/limbo/protocol/registry/Version.java b/src/main/java/ru/nanit/limbo/protocol/registry/Version.java index 388ef51..580e3bd 100644 --- a/src/main/java/ru/nanit/limbo/protocol/registry/Version.java +++ b/src/main/java/ru/nanit/limbo/protocol/registry/Version.java @@ -60,7 +60,8 @@ public enum Version { // 1.18.1 has same protocol number V1_18_2(758), V1_19(759), - V1_19_1(760); + V1_19_1(760), + V1_19_3(761); private static final Map VERSION_MAP; private static final Version MAX;