From f490e008885162d3b4dfe24398bbdebc8ed2fb0b Mon Sep 17 00:00:00 2001 From: Nanit Date: Fri, 29 Oct 2021 13:12:43 +0300 Subject: [PATCH] Modify state registry for multimple versions support --- .../connection/pipeline/PacketDecoder.java | 4 +- .../connection/pipeline/PacketEncoder.java | 4 +- .../nanit/limbo/protocol/registry/State.java | 206 ++++++++++++++++-- .../limbo/protocol/registry/Version.java | 31 ++- .../ru/nanit/limbo/server/LimboServer.java | 1 + 5 files changed, 209 insertions(+), 37 deletions(-) diff --git a/src/main/java/ru/nanit/limbo/connection/pipeline/PacketDecoder.java b/src/main/java/ru/nanit/limbo/connection/pipeline/PacketDecoder.java index 37f471f..1359dc2 100644 --- a/src/main/java/ru/nanit/limbo/connection/pipeline/PacketDecoder.java +++ b/src/main/java/ru/nanit/limbo/connection/pipeline/PacketDecoder.java @@ -16,7 +16,7 @@ public class PacketDecoder extends MessageToMessageDecoder { private Version version; public PacketDecoder() { - updateVersion(Version.getMinimal()); + updateVersion(Version.getMin()); updateState(State.HANDSHAKING); } @@ -46,6 +46,6 @@ public class PacketDecoder extends MessageToMessageDecoder { } public void updateState(State state) { - this.mappings = state.serverBound; + this.mappings = state.serverBound.getRegistry(version); } } diff --git a/src/main/java/ru/nanit/limbo/connection/pipeline/PacketEncoder.java b/src/main/java/ru/nanit/limbo/connection/pipeline/PacketEncoder.java index 9b45594..efcf9ee 100644 --- a/src/main/java/ru/nanit/limbo/connection/pipeline/PacketEncoder.java +++ b/src/main/java/ru/nanit/limbo/connection/pipeline/PacketEncoder.java @@ -16,7 +16,7 @@ public class PacketEncoder extends MessageToByteEncoder { private Version version; public PacketEncoder() { - updateVersion(Version.getMinimal()); + updateVersion(Version.getMin()); updateState(State.HANDSHAKING); } @@ -52,7 +52,7 @@ public class PacketEncoder extends MessageToByteEncoder { } public void updateState(State state) { - this.registry = state.clientBound; + this.registry = state.clientBound.getRegistry(version); } } 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 7b3c339..0ed7086 100644 --- a/src/main/java/ru/nanit/limbo/protocol/registry/State.java +++ b/src/main/java/ru/nanit/limbo/protocol/registry/State.java @@ -8,45 +8,134 @@ import ru.nanit.limbo.protocol.packets.status.PacketStatusPing; import ru.nanit.limbo.protocol.packets.status.PacketStatusRequest; import ru.nanit.limbo.protocol.packets.status.PacketStatusResponse; -import java.util.HashMap; -import java.util.Map; +import static ru.nanit.limbo.protocol.registry.Version.*; + +import java.util.*; import java.util.function.Supplier; public enum State { HANDSHAKING(0) { { - serverBound.register(0x00, PacketHandshake::new); + serverBound.register(PacketHandshake::new, + map(0x00, Version.getMin(), Version.getMax()) + ); } }, STATUS(1) { { - serverBound.register(0x01, PacketStatusPing::new); - serverBound.register(0x00, PacketStatusRequest::new); - clientBound.register(0x00, PacketStatusResponse::new); - clientBound.register(0x01, PacketStatusPing::new); + serverBound.register(PacketStatusRequest::new, + map(0x00, Version.getMin(), Version.getMax()) + ); + serverBound.register(PacketStatusPing::new, + map(0x01, Version.getMin(), Version.getMax()) + ); + clientBound.register(PacketStatusResponse::new, + map(0x00, Version.getMin(), Version.getMax()) + ); + clientBound.register(PacketStatusPing::new, + map(0x01, Version.getMin(), Version.getMax()) + ); } }, LOGIN(2) { { - serverBound.register(0x00, PacketLoginStart::new); - serverBound.register(0x02, PacketLoginPluginResponse::new); - clientBound.register(0x00, PacketDisconnect::new); - clientBound.register(0x02, PacketLoginSuccess::new); - clientBound.register(0x04, PacketLoginPluginRequest::new); + serverBound.register(PacketLoginStart::new, + map(0x00, Version.getMin(), Version.getMax()) + ); + serverBound.register(PacketLoginPluginResponse::new, + map(0x02, Version.getMin(), Version.getMax()) + ); + clientBound.register(PacketDisconnect::new, + map(0x00, Version.getMin(), Version.getMax()) + ); + clientBound.register(PacketLoginSuccess::new, + map(0x02, Version.getMin(), Version.getMax()) + ); + clientBound.register(PacketLoginPluginRequest::new, + map(0x04, Version.getMin(), Version.getMax()) + ); } }, PLAY(3) { { - serverBound.register(0x10, PacketKeepAlive::new); - clientBound.register(0x10, PacketDeclareCommands::new); - clientBound.register(0x24, PacketJoinGame::new); - clientBound.register(0x30, PacketPlayerAbilities::new); - clientBound.register(0x34, PacketPlayerPositionAndLook::new); - clientBound.register(0x1F, PacketKeepAlive::new); - clientBound.register(0x0E, PacketChatMessage::new); - clientBound.register(0x0C, PacketBossBar::new); - clientBound.register(0x32, PacketPlayerInfo::new); + serverBound.register(PacketKeepAlive::new, + map(0x0B, V1_9, V1_11_1), + map(0x0C, V1_12, V1_12), + map(0x0B, V1_12_1, V1_12_2), + map(0x0E, V1_13, V1_13_2), + map(0x0F, V1_14, V1_15_2), + map(0x10, V1_16, V1_16_4), + map(0x0F, V1_17, V1_17_1) + ); + clientBound.register(PacketDeclareCommands::new, + map(0x11, V1_13, V1_14_4), + map(0x12, V1_15, V1_15_2), + map(0x11, V1_16, V1_16_1), + map(0x10, V1_16_2, V1_16_4), + map(0x12, V1_17, V1_17_1) + ); + clientBound.register(PacketJoinGame::new, + map(0x23, V1_9, V1_12_2), + map(0x25, V1_13, V1_13_2), + map(0x25, V1_14, V1_14_4), + map(0x26, V1_15, V1_15_2), + map(0x25, V1_16, V1_16_1), + map(0x24, V1_16_2, V1_16_4), + map(0x26, V1_17, V1_17_1) + ); + clientBound.register(PacketPlayerAbilities::new, + map(0x2B, V1_9, V1_12), + map(0x2C, V1_12_1, V1_12_2), + map(0x2E, V1_13, V1_13_2), + map(0x31, V1_14, V1_14_4), + map(0x32, V1_15, V1_15_2), + map(0x31, V1_16, V1_16_1), + map(0x30, V1_16_2, V1_16_4), + map(0x32, V1_17, V1_17_1) + ); + clientBound.register(PacketPlayerPositionAndLook::new, + map(0x2E, V1_9, V1_12), + map(0x2F, V1_12_1, V1_12_2), + map(0x32, V1_13, V1_13_2), + map(0x35, V1_14, V1_14_4), + map(0x36, V1_15, V1_15_2), + map(0x35, V1_16, V1_16_1), + map(0x34, V1_16_2, V1_16_4), + map(0x38, V1_17, V1_17_1) + ); + clientBound.register(PacketKeepAlive::new, + map(0x1F, V1_9, V1_12_2), + map(0x21, V1_13, V1_13_2), + map(0x20, V1_14, V1_14_4), + map(0x21, V1_15, V1_15_2), + map(0x20, V1_16, V1_16_1), + map(0x1F, V1_16_2, V1_16_4), + map(0x21, V1_17, V1_17_1) + ); + clientBound.register(PacketChatMessage::new, + map(0x0F, V1_9, V1_12_2), + map(0x0E, V1_13, V1_14_4), + map(0x0F, V1_15, V1_15_2), + map(0x0E, V1_16, V1_16_4), + map(0x0F, V1_17, V1_17_1) + ); + 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_17_1) + ); + clientBound.register(PacketPlayerInfo::new, + map(0x2D, V1_9, V1_12), + map(0x2E, V1_12_1, V1_12_2), + map(0x30, V1_13, V1_13_2), + map(0x33, V1_14, V1_14_4), + map(0x34, V1_15, V1_15_2), + map(0x33, V1_16, V1_16_1), + map(0x32, V1_16_2, V1_16_4), + map(0x36, V1_17, V1_17_1) + ); } }; @@ -59,8 +148,8 @@ public enum State { } private final int stateId; - public final PacketRegistry serverBound = new PacketRegistry(); - public final PacketRegistry clientBound = new PacketRegistry(); + public final ProtocolMappings serverBound = new ProtocolMappings(); + public final ProtocolMappings clientBound = new ProtocolMappings(); State(int stateId) { this.stateId = stateId; @@ -70,11 +159,58 @@ public enum State { return STATE_BY_ID.get(stateId); } + public static class ProtocolMappings { + + private final Map registry = new HashMap<>(); + + public PacketRegistry getRegistry(Version version) { + return registry.get(version); + } + + public void register(Supplier packet, Mapping... mappings) { + for (Mapping mapping : mappings) { + for (Version ver : getRange(mapping)) { + PacketRegistry reg = registry.computeIfAbsent(ver, PacketRegistry::new); + reg.register(mapping.packetId, packet); + } + } + } + + private Collection getRange(Mapping mapping) { + Version from = mapping.from; + Version curr = mapping.to; + + if (curr == from) + return Collections.singletonList(from); + + List versions = new LinkedList<>(); + + while (curr != from) { + versions.add(curr); + curr = curr.getPrev(); + } + + versions.add(from); + + return versions; + } + + } + public static class PacketRegistry { + private final Version version; private final Map> packetsById = new HashMap<>(); private final Map, Integer> packetIdByClass = new HashMap<>(); + public PacketRegistry(Version version) { + this.version = version; + } + + public Version getVersion() { + return version; + } + public Packet getPacket(int packetId) { Supplier supplier = packetsById.get(packetId); return supplier == null ? null : (Packet) supplier.get(); @@ -91,4 +227,28 @@ public enum State { } + private static class Mapping { + + private final int packetId; + private final Version from; + private final Version to; + + public Mapping(int packetId, Version from, Version to) { + this.from = from; + this.to = to; + this.packetId = packetId; + } + } + + /** + * Map packet id to version range + * @param packetId Packet id + * @param from Minimal version (include) + * @param to Last version (include) + * @return Created mapping + */ + private static Mapping map(int packetId, Version from, Version to) { + return new Mapping(packetId, from, to); + } + } 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 b39bcda..f205417 100644 --- a/src/main/java/ru/nanit/limbo/protocol/registry/Version.java +++ b/src/main/java/ru/nanit/limbo/protocol/registry/Version.java @@ -13,6 +13,7 @@ public enum Version { V1_10(210), V1_11(315), V1_11_1(316), + // 1.11.2 has same protocol number V1_12(335), V1_12_1(338), V1_12_2(340), @@ -36,25 +37,20 @@ public enum Version { V1_17(755), V1_17_1(756); - public static final Map VERSION_MAP; + private static final Map VERSION_MAP; static { VERSION_MAP = new HashMap<>(); - + Version last = null; for (Version version : values()) { + version.prev = last; + last = version; VERSION_MAP.put(version.getProtocolNumber(), version); } } - public static Version getMinimal() { - return V1_9; - } - - public static Version of(int protocolNumber) { - return VERSION_MAP.getOrDefault(protocolNumber, UNDEFINED); - } - private final int protocolNumber; + private Version prev; Version(int protocolNumber) { this.protocolNumber = protocolNumber; @@ -64,4 +60,19 @@ public enum Version { return this.protocolNumber; } + public Version getPrev() { + return prev; + } + + public static Version getMin() { + return V1_9; + } + + public static Version getMax() { + return V1_17_1; + } + + public static Version of(int protocolNumber) { + return VERSION_MAP.getOrDefault(protocolNumber, UNDEFINED); + } } diff --git a/src/main/java/ru/nanit/limbo/server/LimboServer.java b/src/main/java/ru/nanit/limbo/server/LimboServer.java index 28df9a3..11120ec 100644 --- a/src/main/java/ru/nanit/limbo/server/LimboServer.java +++ b/src/main/java/ru/nanit/limbo/server/LimboServer.java @@ -13,6 +13,7 @@ import io.netty.util.ResourceLeakDetector; import ru.nanit.limbo.configuration.LimboConfig; import ru.nanit.limbo.connection.ClientChannelInitializer; import ru.nanit.limbo.connection.ClientConnection; +import ru.nanit.limbo.protocol.registry.State; import ru.nanit.limbo.util.Logger; import ru.nanit.limbo.world.DimensionRegistry;