diff --git a/README.md b/README.md index 46ce909..0dd19b1 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Symbol `X` means all minor versions. - [x] 1.17.X - [x] 1.18.X - [x] 1.19.X -- [x] 1.20-1.20.4 +- [x] 1.20-1.20.6 The server **doesn't** support snapshots. diff --git a/src/main/java/ua/nanit/limbo/connection/ClientConnection.java b/src/main/java/ua/nanit/limbo/connection/ClientConnection.java index a11f46b..1d98847 100644 --- a/src/main/java/ua/nanit/limbo/connection/ClientConnection.java +++ b/src/main/java/ua/nanit/limbo/connection/ClientConnection.java @@ -115,7 +115,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { public void handlePacket(Object packet) { if (packet instanceof Packet) { - ((Packet)packet).handle(this, server); + ((Packet) packet).handle(this, server); } } @@ -199,7 +199,14 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { if (PacketSnapshots.PACKET_PLUGIN_MESSAGE != null) writePacket(PacketSnapshots.PACKET_PLUGIN_MESSAGE); - writePacket(PacketSnapshots.PACKET_REGISTRY_DATA); + + if (clientVersion.moreOrEqual(Version.V1_20_5)) { + for (PacketSnapshot packet : PacketSnapshots.PACKETS_REGISTRY_DATA) { + writePacket(packet); + } + } else { + writePacket(PacketSnapshots.PACKET_REGISTRY_DATA); + } sendPacket(PacketSnapshots.PACKET_FINISH_CONFIGURATION); } @@ -272,7 +279,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { } public void setAddress(String host) { - this.address = new InetSocketAddress(host, ((InetSocketAddress)this.address).getPort()); + this.address = new InetSocketAddress(host, ((InetSocketAddress) this.address).getPort()); } boolean checkBungeeGuardHandshake(String handshake) { @@ -333,7 +340,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { byte[] mySignature = mac.doFinal(data); if (!MessageDigest.isEqual(signature, mySignature)) return false; - } catch (InvalidKeyException |java.security.NoSuchAlgorithmException e) { + } catch (InvalidKeyException | java.security.NoSuchAlgorithmException e) { throw new AssertionError(e); } int version = buf.readVarInt(); diff --git a/src/main/java/ua/nanit/limbo/connection/PacketSnapshots.java b/src/main/java/ua/nanit/limbo/connection/PacketSnapshots.java index 0c82723..f5f5797 100644 --- a/src/main/java/ua/nanit/limbo/connection/PacketSnapshots.java +++ b/src/main/java/ua/nanit/limbo/connection/PacketSnapshots.java @@ -17,6 +17,9 @@ package ua.nanit.limbo.connection; +import net.kyori.adventure.nbt.BinaryTag; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.nbt.ListBinaryTag; import ua.nanit.limbo.LimboConstants; import ua.nanit.limbo.protocol.PacketSnapshot; import ua.nanit.limbo.protocol.packets.configuration.PacketFinishConfiguration; @@ -27,6 +30,7 @@ import ua.nanit.limbo.server.LimboServer; import ua.nanit.limbo.server.data.Title; import ua.nanit.limbo.util.NbtMessageUtil; import ua.nanit.limbo.util.UuidUtil; +import ua.nanit.limbo.world.Dimension; import java.util.ArrayList; import java.util.Collections; @@ -60,6 +64,7 @@ public final class PacketSnapshots { public static PacketSnapshot PACKET_TITLE_LEGACY_TIMES; public static PacketSnapshot PACKET_REGISTRY_DATA; + public static List PACKETS_REGISTRY_DATA; public static PacketSnapshot PACKET_FINISH_CONFIGURATION; public static List PACKETS_EMPTY_CHUNKS; @@ -193,6 +198,38 @@ public final class PacketSnapshots { packetRegistryData.setDimensionRegistry(server.getDimensionRegistry()); PACKET_REGISTRY_DATA = PacketSnapshot.of(packetRegistryData); + + Dimension dimension1_20_5 = server.getDimensionRegistry().getDimension_1_20_5(); + List packetRegistries = new ArrayList<>(); + CompoundBinaryTag dimensionTag = dimension1_20_5.getData(); + for (String registryType : dimensionTag.keySet()) { + CompoundBinaryTag compundRegistryType = dimensionTag.getCompound(registryType); + + PacketRegistryData registryData = new PacketRegistryData(); + registryData.setDimensionRegistry(server.getDimensionRegistry()); + + ListBinaryTag values = compundRegistryType.getList("value"); + registryData.setMetadataWriter((message, version) -> { + message.writeString(registryType); + + message.writeVarInt(values.size()); + for (BinaryTag entry : values) { + CompoundBinaryTag entryTag = (CompoundBinaryTag) entry; + + String name = entryTag.getString("name"); + CompoundBinaryTag element = entryTag.getCompound("element"); + + message.writeString(name); + message.writeBoolean(true); + message.writeNamelessCompoundTag(element); + } + }); + + packetRegistries.add(PacketSnapshot.of(registryData)); + } + + PACKETS_REGISTRY_DATA = packetRegistries; + PACKET_FINISH_CONFIGURATION = PacketSnapshot.of(new PacketFinishConfiguration()); PacketGameEvent packetGameEvent = new PacketGameEvent(); diff --git a/src/main/java/ua/nanit/limbo/protocol/MetadataWriter.java b/src/main/java/ua/nanit/limbo/protocol/MetadataWriter.java new file mode 100644 index 0000000..54a46f5 --- /dev/null +++ b/src/main/java/ua/nanit/limbo/protocol/MetadataWriter.java @@ -0,0 +1,10 @@ +package ua.nanit.limbo.protocol; + +import ua.nanit.limbo.protocol.registry.Version; + +@FunctionalInterface +public interface MetadataWriter { + + void writeData(ByteMessage message, Version version); + +} diff --git a/src/main/java/ua/nanit/limbo/protocol/packets/configuration/PacketRegistryData.java b/src/main/java/ua/nanit/limbo/protocol/packets/configuration/PacketRegistryData.java index 3f3a6e9..7b284ae 100644 --- a/src/main/java/ua/nanit/limbo/protocol/packets/configuration/PacketRegistryData.java +++ b/src/main/java/ua/nanit/limbo/protocol/packets/configuration/PacketRegistryData.java @@ -1,6 +1,7 @@ package ua.nanit.limbo.protocol.packets.configuration; import ua.nanit.limbo.protocol.ByteMessage; +import ua.nanit.limbo.protocol.MetadataWriter; import ua.nanit.limbo.protocol.PacketOut; import ua.nanit.limbo.protocol.registry.Version; import ua.nanit.limbo.world.DimensionRegistry; @@ -8,13 +9,24 @@ import ua.nanit.limbo.world.DimensionRegistry; public class PacketRegistryData implements PacketOut { private DimensionRegistry dimensionRegistry; + private MetadataWriter metadataWriter; public void setDimensionRegistry(DimensionRegistry dimensionRegistry) { this.dimensionRegistry = dimensionRegistry; } + public void setMetadataWriter(MetadataWriter metadataWriter) { + this.metadataWriter = metadataWriter; + } + @Override public void encode(ByteMessage msg, Version version) { + if (metadataWriter != null) { + if (version.moreOrEqual(Version.V1_20_5)) { + metadataWriter.writeData(msg, version); + return; + } + } msg.writeNamelessCompoundTag(dimensionRegistry.getCodec_1_20()); } } diff --git a/src/main/java/ua/nanit/limbo/protocol/packets/login/PacketLoginSuccess.java b/src/main/java/ua/nanit/limbo/protocol/packets/login/PacketLoginSuccess.java index a07dd2a..309fb3e 100644 --- a/src/main/java/ua/nanit/limbo/protocol/packets/login/PacketLoginSuccess.java +++ b/src/main/java/ua/nanit/limbo/protocol/packets/login/PacketLoginSuccess.java @@ -49,6 +49,9 @@ public class PacketLoginSuccess implements PacketOut { if (version.moreOrEqual(Version.V1_19)) { msg.writeVarInt(0); } + if (version.moreOrEqual(Version.V1_20_5)) { + msg.writeBoolean(true); + } } @Override diff --git a/src/main/java/ua/nanit/limbo/protocol/packets/play/PacketJoinGame.java b/src/main/java/ua/nanit/limbo/protocol/packets/play/PacketJoinGame.java index fbb190f..ffefa2b 100644 --- a/src/main/java/ua/nanit/limbo/protocol/packets/play/PacketJoinGame.java +++ b/src/main/java/ua/nanit/limbo/protocol/packets/play/PacketJoinGame.java @@ -39,6 +39,7 @@ public class PacketJoinGame implements PacketOut { private boolean isDebug; private boolean isFlat; private boolean limitedCrafting; + private boolean secureProfile; public void setEntityId(int entityId) { this.entityId = entityId; @@ -100,6 +101,10 @@ public class PacketJoinGame implements PacketOut { this.limitedCrafting = limitedCrafting; } + public void setSecureProfile(boolean secureProfile) { + this.secureProfile = secureProfile; + } + @Override public void encode(ByteMessage msg, Version version) { msg.writeInt(entityId); @@ -255,7 +260,7 @@ public class PacketJoinGame implements PacketOut { msg.writeVarInt(0); } - if (version.moreOrEqual(Version.V1_20_2)) { + if (version.fromTo(Version.V1_20_2, Version.V1_20_3)) { msg.writeBoolean(isHardcore); msg.writeStringsArray(worldNames); msg.writeVarInt(maxPlayers); @@ -274,6 +279,27 @@ public class PacketJoinGame implements PacketOut { msg.writeBoolean(false); msg.writeVarInt(0); } + + if (version.moreOrEqual(Version.V1_20_5)) { + msg.writeBoolean(isHardcore); + msg.writeStringsArray(worldNames); + msg.writeVarInt(maxPlayers); + msg.writeVarInt(viewDistance); + msg.writeVarInt(viewDistance); // Simulation Distance + msg.writeBoolean(reducedDebugInfo); + msg.writeBoolean(enableRespawnScreen); + msg.writeBoolean(limitedCrafting); + msg.writeVarInt(dimensionRegistry.getDimension_1_20_5().getId()); + msg.writeString(worldName); + msg.writeLong(hashedSeed); + msg.writeByte(gameMode); + msg.writeByte(previousGameMode); + msg.writeBoolean(isDebug); + msg.writeBoolean(isFlat); + msg.writeBoolean(false); + msg.writeVarInt(0); + msg.writeBoolean(secureProfile); + } } } diff --git a/src/main/java/ua/nanit/limbo/protocol/registry/State.java b/src/main/java/ua/nanit/limbo/protocol/registry/State.java index f8564f7..f52488b 100644 --- a/src/main/java/ua/nanit/limbo/protocol/registry/State.java +++ b/src/main/java/ua/nanit/limbo/protocol/registry/State.java @@ -66,7 +66,7 @@ public enum State { ); serverBound.register( PacketLoginAcknowledged::new, - map(0x03, V1_20_2, V1_20_3) + map(0x03, V1_20_2, V1_20_5) ); clientBound.register(PacketDisconnect::new, map(0x00, Version.getMin(), Version.getMax()) @@ -83,36 +83,44 @@ public enum State { { clientBound.register( PacketPluginMessage::new, - map(0x00, V1_20_2, V1_20_3) + map(0x00, V1_20_2, V1_20_3), + map(0x01, V1_20_5, V1_20_5) ); clientBound.register( PacketDisconnect::new, - map(0x01, V1_20_2, V1_20_3) + map(0x01, V1_20_2, V1_20_3), + map(0x02, V1_20_5, V1_20_5) ); clientBound.register( PacketFinishConfiguration::new, - map(0x02, V1_20_2, V1_20_3) + map(0x02, V1_20_2, V1_20_3), + map(0x03, V1_20_5, V1_20_5) ); clientBound.register( PacketKeepAlive::new, - map(0x03, V1_20_2, V1_20_3) + map(0x03, V1_20_2, V1_20_3), + map(0x04, V1_20_5, V1_20_5) ); clientBound.register( PacketRegistryData::new, - map(0x05, V1_20_2, V1_20_3) + map(0x05, V1_20_2, V1_20_3), + map(0x07, V1_20_5, V1_20_5) ); serverBound.register( PacketPluginMessage::new, - map(0x01, V1_20_2, V1_20_3) + map(0x01, V1_20_2, V1_20_3), + map(0x02, V1_20_2, V1_20_5) ); serverBound.register( PacketFinishConfiguration::new, - map(0x02, V1_20_2, V1_20_3) + map(0x02, V1_20_2, V1_20_3), + map(0x03, V1_20_5, V1_20_5) ); serverBound.register( PacketKeepAlive::new, - map(0x03, V1_20_2, V1_20_3) + map(0x03, V1_20_2, V1_20_3), + map(0x04, V1_20_5, V1_20_5) ); } }, @@ -132,7 +140,8 @@ public enum State { map(0x11, V1_19_3, V1_19_3), map(0x12, V1_19_4, V1_20), map(0x14, V1_20_2, V1_20_2), - map(0x15, V1_20_3, V1_20_3) + map(0x15, V1_20_3, V1_20_3), + map(0x18, V1_20_5, V1_20_5) ); clientBound.register(PacketDeclareCommands::new, @@ -144,7 +153,7 @@ public enum State { map(0x0F, V1_19, V1_19_1), map(0x0E, V1_19_3, V1_19_3), map(0x10, V1_19_4, V1_20), - map(0x11, V1_20_2, V1_20_3) + map(0x11, V1_20_2, V1_20_5) ); clientBound.register(PacketJoinGame::new, map(0x01, V1_7_2, V1_8), @@ -158,7 +167,8 @@ public enum State { map(0x25, V1_19_1, V1_19_1), map(0x24, V1_19_3, V1_19_3), map(0x28, V1_19_4, V1_20), - map(0x29, V1_20_2, V1_20_3) + map(0x29, V1_20_2, V1_20_3), + map(0x2B, V1_20_5, V1_20_5) ); clientBound.register(PacketPluginMessage::new, map(0x19, V1_13, V1_13_2), @@ -171,7 +181,8 @@ public enum State { map(0x16, V1_19_1, V1_19_1), map(0x15, V1_19_3, V1_19_3), map(0x17, V1_19_4, V1_20), - map(0x18, V1_20_2, V1_20_3) + map(0x18, V1_20_2, V1_20_3), + map(0x19, V1_20_5, V1_20_5) ); clientBound.register(PacketPlayerAbilities::new, map(0x39, V1_7_2, V1_8), @@ -187,7 +198,8 @@ public enum State { map(0x31, V1_19_1, V1_19_1), map(0x30, V1_19_3, V1_19_3), map(0x34, V1_19_4, V1_20), - map(0x36, V1_20_2, V1_20_3) + map(0x36, V1_20_2, V1_20_3), + map(0x38, V1_20_5, V1_20_5) ); clientBound.register(PacketPlayerPositionAndLook::new, map(0x08, V1_7_2, V1_8), @@ -203,7 +215,8 @@ public enum State { map(0x39, V1_19_1, V1_19_1), map(0x38, V1_19_3, V1_19_3), map(0x3C, V1_19_4, V1_20), - map(0x3E, V1_20_2, V1_20_3) + map(0x3E, V1_20_2, V1_20_3), + map(0x40, V1_20_5, V1_20_5) ); clientBound.register(PacketKeepAlive::new, map(0x00, V1_7_2, V1_8), @@ -218,7 +231,8 @@ public enum State { map(0x20, V1_19_1, V1_19_1), map(0x1F, V1_19_3, V1_19_3), map(0x23, V1_19_4, V1_20), - map(0x24, V1_20_2, V1_20_3) + map(0x24, V1_20_2, V1_20_3), + map(0x26, V1_20_5, V1_20_5) ); clientBound.register(PacketChatMessage::new, map(0x02, V1_7_2, V1_8), @@ -232,7 +246,8 @@ public enum State { map(0x60, V1_19_3, V1_19_3), map(0x64, V1_19_4, V1_20), map(0x67, V1_20_2, V1_20_2), - map(0x69, V1_20_3, V1_20_3) + map(0x69, V1_20_3, V1_20_3), + map(0x6C, V1_20_5, V1_20_5) ); clientBound.register(PacketBossBar::new, map(0x0C, V1_9, V1_14_4), @@ -241,7 +256,7 @@ public enum State { map(0x0D, V1_17, V1_18_2), map(0x0A, V1_19, V1_19_3), map(0x0B, V1_19_4, V1_20), - map(0x0A, V1_20_2, V1_20_3) + map(0x0A, V1_20_2, V1_20_5) ); clientBound.register(PacketPlayerInfo::new, map(0x38, V1_7_2, V1_8), @@ -257,7 +272,8 @@ public enum State { map(0x37, V1_19_1, V1_19_1), map(0x36, V1_19_3, V1_19_3), map(0x3A, V1_19_4, V1_20), - map(0x3C, V1_20_2, V1_20_3) + map(0x3C, V1_20_2, V1_20_3), + map(0x3E, V1_20_5, V1_20_5) ); clientBound.register(PacketTitleLegacy::new, map(0x45, V1_8, V1_11_1), @@ -275,7 +291,8 @@ public enum State { map(0x5B, V1_19_3, V1_19_3), map(0x5F, V1_19_4, V1_20), map(0x61, V1_20_2, V1_20_2), - map(0x63, V1_20_3, V1_20_3) + map(0x63, V1_20_3, V1_20_3), + map(0x65, V1_20_5, V1_20_5) ); clientBound.register(PacketTitleSetSubTitle::new, map(0x57, V1_17, V1_17_1), @@ -284,7 +301,8 @@ public enum State { map(0x59, V1_19_3, V1_19_3), map(0x5D, V1_19_4, V1_20), map(0x5F, V1_20_2, V1_20_2), - map(0x61, V1_20_3, V1_20_3) + map(0x61, V1_20_3, V1_20_3), + map(0x63, V1_20_5, V1_20_5) ); clientBound.register(PacketTitleTimes::new, map(0x5A, V1_17, V1_17_1), @@ -293,7 +311,8 @@ public enum State { map(0x5C, V1_19_3, V1_19_3), map(0x60, V1_19_4, V1_20), map(0x62, V1_20_2, V1_20_2), - map(0x64, V1_20_3, V1_20_3) + map(0x64, V1_20_3, V1_20_3), + map(0x66, V1_20_5, V1_20_5) ); clientBound.register(PacketPlayerListHeader::new, map(0x47, V1_8, V1_8), @@ -312,19 +331,23 @@ public enum State { map(0x61, V1_19_3, V1_19_3), map(0x65, V1_19_4, V1_20), map(0x68, V1_20_2, V1_20_2), - map(0x6A, V1_20_3, V1_20_3) + map(0x6A, V1_20_3, V1_20_3), + map(0x6D, V1_20_5, V1_20_5) ); clientBound.register(PacketSpawnPosition::new, map(0x4C, V1_19_3, V1_19_3), map(0x50, V1_19_4, V1_20), map(0x52, V1_20_2, V1_20_2), - map(0x54, V1_20_3, V1_20_3) + map(0x54, V1_20_3, V1_20_3), + map(0x56, V1_20_5, V1_20_5) ); clientBound.register(PacketGameEvent::new, - map(0x20, V1_20_3, V1_20_3) + map(0x20, V1_20_3, V1_20_3), + map(0x22, V1_20_5, V1_20_5) ); clientBound.register(PacketEmptyChunk::new, - map(0x25, V1_20_3, V1_20_3) + map(0x25, V1_20_3, V1_20_3), + map(0x27, V1_20_5, V1_20_5) ); } }; diff --git a/src/main/java/ua/nanit/limbo/protocol/registry/Version.java b/src/main/java/ua/nanit/limbo/protocol/registry/Version.java index 3418c4b..81b9155 100644 --- a/src/main/java/ua/nanit/limbo/protocol/registry/Version.java +++ b/src/main/java/ua/nanit/limbo/protocol/registry/Version.java @@ -71,7 +71,8 @@ public enum Version { V1_20(763), // 1.20.1 has same protocol number V1_20_2(764), - V1_20_3(765); + V1_20_3(765), + V1_20_5(766); private static final Map VERSION_MAP; private static final Version MAX; diff --git a/src/main/java/ua/nanit/limbo/world/DimensionRegistry.java b/src/main/java/ua/nanit/limbo/world/DimensionRegistry.java index d90f8c9..49954b6 100644 --- a/src/main/java/ua/nanit/limbo/world/DimensionRegistry.java +++ b/src/main/java/ua/nanit/limbo/world/DimensionRegistry.java @@ -33,6 +33,7 @@ public final class DimensionRegistry { private Dimension defaultDimension_1_16; private Dimension defaultDimension_1_18_2; + private Dimension dimension_1_20_5; private CompoundBinaryTag codec_1_16; private CompoundBinaryTag codec_1_18_2; @@ -82,6 +83,10 @@ public final class DimensionRegistry { return defaultDimension_1_18_2; } + public Dimension getDimension_1_20_5() { + return dimension_1_20_5; + } + public void load(String def) throws IOException { codec_1_16 = readCodecFile("/dimension/codec_1_16.snbt"); codec_1_18_2 = readCodecFile("/dimension/codec_1_18_2.snbt"); @@ -94,6 +99,8 @@ public final class DimensionRegistry { defaultDimension_1_16 = getDefaultDimension(def, codec_1_16); defaultDimension_1_18_2 = getDefaultDimension(def, codec_1_18_2); + + dimension_1_20_5 = getModernDimension(def, codec_1_20); } private Dimension getDefaultDimension(String def, CompoundBinaryTag tag) { @@ -116,24 +123,35 @@ public final class DimensionRegistry { } } + private Dimension getModernDimension(String def, CompoundBinaryTag tag) { + switch (def.toLowerCase()) { + case "overworld": + return new Dimension(0, "minecraft:overworld", tag); + case "the_nether": + return new Dimension(2, "minecraft:nether", tag); + case "the_end": + return new Dimension(3, "minecraft:the_end", tag); + default: + Logger.warning("Undefined dimension type: '%s'. Using THE_END as default", def); + return new Dimension(3, "minecraft:the_end", tag); + } + } + private CompoundBinaryTag readCodecFile(String resPath) throws IOException { InputStream in = server.getClass().getResourceAsStream(resPath); - if(in == null) + if (in == null) throw new FileNotFoundException("Cannot find dimension registry file"); return TagStringIO.get().asCompound(streamToString(in)); } private String streamToString(InputStream in) throws IOException { - InputStreamReader isReader = new InputStreamReader(in, StandardCharsets.UTF_8); - BufferedReader bufReader = new BufferedReader(isReader); - String content = bufReader.lines() - .collect(Collectors.joining("\n")); + try (BufferedReader bufReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { + String content = bufReader.lines() + .collect(Collectors.joining("\n")); - isReader.close(); - bufReader.close(); - - return content; + return content; + } } }