From b239a91388d0874108361a79313d8ef367322464 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Tue, 11 May 2021 03:21:08 -0400 Subject: [PATCH] Finish overhaul of packet state/registry system --- .../proxy/connection/MinecraftConnection.java | 13 +- .../backend/LoginSessionHandler.java | 5 +- .../backend/VelocityServerConnection.java | 6 +- .../client/ClientPlaySessionHandler.java | 5 +- .../connection/client/ConnectedPlayer.java | 4 +- .../client/HandshakeSessionHandler.java | 32 ++-- .../client/LoginSessionHandler.java | 4 +- .../ServerboundHandshakePacket.java | 2 + .../network/pipeline/MinecraftDecoder.java | 30 ++-- .../network/pipeline/MinecraftEncoder.java | 25 +-- .../packet/DensePacketRegistryMap.java | 32 +++- .../packet/EmptyPacketRegistryMap.java | 19 +- .../packet/PacketRegistryBuilder.java | 22 ++- .../registry/packet/PacketRegistryMap.java | 17 ++ .../packet/RegularPacketRegistryMap.java | 20 ++- .../registry/protocol/ProtocolRegistry.java | 17 ++ .../protocol/SimpleProtocolRegistry.java | 17 ++ .../VersionSpecificProtocolRegistry.java | 17 ++ .../registry/state/LoginPacketRegistry.java | 84 +++++++++ .../state/PlayPacketRegistry.java} | 166 ++++-------------- .../registry/state/ProtocolStates.java | 51 ++++-- .../registry/state/Version172To176.java | 39 ---- .../registry/version/GenericVersions.java | 5 - .../proxy/server/PingSessionHandler.java | 6 +- 24 files changed, 376 insertions(+), 262 deletions(-) create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/LoginPacketRegistry.java rename proxy/src/main/java/com/velocitypowered/proxy/network/{StateRegistry.java => registry/state/PlayPacketRegistry.java} (79%) delete mode 100644 proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/Version172To176.java delete mode 100644 proxy/src/main/java/com/velocitypowered/proxy/network/registry/version/GenericVersions.java diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java index f988f49e5..f18765248 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java @@ -36,7 +36,6 @@ import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler; import com.velocitypowered.proxy.connection.client.LoginSessionHandler; import com.velocitypowered.proxy.connection.client.StatusSessionHandler; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.Packet; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket; import com.velocitypowered.proxy.network.pipeline.MinecraftCipherDecoder; @@ -45,6 +44,8 @@ import com.velocitypowered.proxy.network.pipeline.MinecraftCompressDecoder; import com.velocitypowered.proxy.network.pipeline.MinecraftCompressorAndLengthEncoder; import com.velocitypowered.proxy.network.pipeline.MinecraftDecoder; import com.velocitypowered.proxy.network.pipeline.MinecraftEncoder; +import com.velocitypowered.proxy.network.registry.protocol.ProtocolRegistry; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import com.velocitypowered.proxy.util.except.QuietDecoderException; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; @@ -75,7 +76,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { private final Channel channel; private SocketAddress remoteAddress; - private StateRegistry state; + private ProtocolRegistry state; private @Nullable MinecraftSessionHandler sessionHandler; private ProtocolVersion protocolVersion; private @Nullable MinecraftConnectionAssociation association; @@ -92,7 +93,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { this.channel = channel; this.remoteAddress = channel.remoteAddress(); this.server = server; - this.state = StateRegistry.HANDSHAKE; + this.state = ProtocolStates.HANDSHAKE; } @Override @@ -247,7 +248,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { if (channel.isActive()) { boolean is17 = this.getProtocolVersion().lt(ProtocolVersion.MINECRAFT_1_8) && this.getProtocolVersion().gte(ProtocolVersion.MINECRAFT_1_7_2); - if (is17 && this.getState() != StateRegistry.STATUS) { + if (is17 && this.getState() != ProtocolStates.STATUS) { channel.eventLoop().execute(() -> { // 1.7.x versions have a race condition with switching protocol states, so just explicitly // close the connection after a short while. @@ -307,7 +308,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { return remoteAddress; } - public StateRegistry getState() { + public ProtocolRegistry getState() { return state; } @@ -341,7 +342,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { * Changes the state of the Minecraft connection. * @param state the new state */ - public void setState(StateRegistry state) { + public void setState(ProtocolRegistry state) { ensureInEventLoop(); this.state = state; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java index a06fa6600..5b5ad833f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java @@ -27,13 +27,13 @@ import com.velocitypowered.proxy.connection.VelocityConstants; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl; import com.velocitypowered.proxy.network.ProtocolUtils; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundLoginPluginMessagePacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundLoginPluginResponsePacket; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import com.velocitypowered.proxy.util.except.QuietRuntimeException; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -46,7 +46,6 @@ import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; public class LoginSessionHandler implements MinecraftSessionHandler { @@ -119,7 +118,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler { // Move into the PLAY phase. MinecraftConnection smc = serverConn.ensureConnected(); - smc.setState(StateRegistry.PLAY); + smc.setState(ProtocolStates.PLAY); // Switch to the transition handler. smc.setSessionHandler(new TransitionSessionHandler(server, serverConn, resultFuture)); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java index 23b3a4411..0de82d4b0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java @@ -38,11 +38,11 @@ import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.registry.DimensionRegistry; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundJoinGamePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -167,11 +167,11 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation, int port = destinationAddr instanceof InetSocketAddress ? ((InetSocketAddress) destinationAddr).getPort() : 0; ServerboundHandshakePacket handshake = new ServerboundHandshakePacket(protocolVersion, - address, port, StateRegistry.LOGIN_ID); + address, port, ServerboundHandshakePacket.LOGIN_ID); mc.delayedWrite(handshake); mc.setProtocolVersion(protocolVersion); - mc.setState(StateRegistry.LOGIN); + mc.setState(ProtocolStates.LOGIN); mc.delayedWrite(new ServerboundServerLoginPacket(proxyPlayer.username())); mc.flush(); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 3840f0b3c..950735cf2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -41,7 +41,6 @@ import com.velocitypowered.proxy.connection.backend.BackendConnectionPhases; import com.velocitypowered.proxy.connection.backend.BungeeCordMessageResponder; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.network.PluginMessageUtil; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket; import com.velocitypowered.proxy.network.packet.Packet; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundBossBarPacket; @@ -57,6 +56,7 @@ import com.velocitypowered.proxy.network.packet.serverbound.ServerboundKeepAlive import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundResourcePackResponsePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundTabCompleteRequestPacket; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; @@ -69,7 +69,6 @@ import java.util.Optional; import java.util.Queue; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import net.kyori.adventure.identity.Identity; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -210,7 +209,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { VelocityServerConnection serverConn = player.getConnectedServer(); MinecraftConnection backendConn = serverConn != null ? serverConn.getConnection() : null; if (serverConn != null && backendConn != null) { - if (backendConn.getState() != StateRegistry.PLAY) { + if (backendConn.getState() != ProtocolStates.PLAY) { logger.warn("A plugin message was received while the backend server was not " + "ready. Channel: {}. Packet discarded.", packet.getChannel()); } else if (PluginMessageUtil.isRegister(packet)) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 9abe2e542..f39f14520 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -58,7 +58,6 @@ import com.velocitypowered.proxy.connection.util.ConnectionMessages; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl; import com.velocitypowered.proxy.network.PluginMessageUtil; import com.velocitypowered.proxy.network.ProtocolUtils; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundChatPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket; @@ -68,6 +67,7 @@ import com.velocitypowered.proxy.network.packet.clientbound.ClientboundResourceP import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTitlePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundChatPacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundClientSettingsPacket; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.VelocityTabList; import com.velocitypowered.proxy.tablist.VelocityTabListLegacy; @@ -769,7 +769,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { * ID last sent by the server. */ public void sendKeepAlive() { - if (connection.getState() == StateRegistry.PLAY) { + if (connection.getState() == ProtocolStates.PLAY) { connection.write(new ClientboundKeepAlivePacket(ThreadLocalRandom.current().nextLong())); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java index c1f6b9b2b..31f3a9477 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java @@ -29,12 +29,13 @@ import com.velocitypowered.proxy.connection.ConnectionTypes; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.Packet; import com.velocitypowered.proxy.network.packet.legacy.LegacyDisconnectPacket; import com.velocitypowered.proxy.network.packet.legacy.LegacyHandshakePacket; import com.velocitypowered.proxy.network.packet.legacy.LegacyPingPacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket; +import com.velocitypowered.proxy.network.registry.protocol.ProtocolRegistry; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import io.netty.buffer.ByteBuf; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -81,7 +82,7 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler { public boolean handle(ServerboundHandshakePacket handshake) { InitialInboundConnection ic = new InitialInboundConnection(connection, cleanVhost(handshake.getServerAddress()), handshake); - StateRegistry nextState = getStateForProtocol(handshake.getNextStatus()); + ProtocolRegistry nextState = getStateForProtocol(handshake.getNextStatus()); if (nextState == null) { LOGGER.error("{} provided invalid protocol {}", ic, handshake.getNextStatus()); connection.close(true); @@ -90,28 +91,25 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler { connection.setProtocolVersion(handshake.getProtocolVersion()); connection.setAssociation(ic); - switch (nextState) { - case STATUS: - connection.setSessionHandler(new StatusSessionHandler(server, connection, ic)); - break; - case LOGIN: - this.handleLogin(handshake, ic); - break; - default: - // If you get this, it's a bug in Velocity. - throw new AssertionError("getStateForProtocol provided invalid state!"); + if (nextState == ProtocolStates.STATUS) { + connection.setSessionHandler(new StatusSessionHandler(server, connection, ic)); + } else if (nextState == ProtocolStates.LOGIN) { + this.handleLogin(handshake, ic); + } else { + // If you get this, it's a bug in Velocity. + throw new AssertionError("getStateForProtocol provided invalid state!"); } } return true; } - private static @Nullable StateRegistry getStateForProtocol(int status) { + private static @Nullable ProtocolRegistry getStateForProtocol(int status) { switch (status) { - case StateRegistry.STATUS_ID: - return StateRegistry.STATUS; - case StateRegistry.LOGIN_ID: - return StateRegistry.LOGIN; + case ServerboundHandshakePacket.STATUS_ID: + return ProtocolStates.STATUS; + case ServerboundHandshakePacket.LOGIN_ID: + return ProtocolStates.LOGIN; default: return null; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java index 085dec7ee..caaa37669 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java @@ -46,12 +46,12 @@ import com.velocitypowered.proxy.config.PlayerInfoForwarding; import com.velocitypowered.proxy.config.VelocityConfiguration; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundEncryptionResponsePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import io.netty.buffer.ByteBuf; import java.net.InetSocketAddress; import java.security.GeneralSecurityException; @@ -287,7 +287,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler { mcConnection.write(new ClientboundServerLoginSuccessPacket(playerUniqueId, player.username())); mcConnection.setAssociation(player); - mcConnection.setState(StateRegistry.PLAY); + mcConnection.setState(ProtocolStates.PLAY); server.eventManager().fire(new LoginEventImpl(player)) .thenAcceptAsync(event -> { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundHandshakePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundHandshakePacket.java index 17beb7a88..ee5539d72 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundHandshakePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundHandshakePacket.java @@ -41,6 +41,8 @@ public class ServerboundHandshakePacket implements Packet { out.writeShort(packet.port); ProtocolUtils.writeVarInt(out, packet.nextStatus); }; + public static final int STATUS_ID = 1; + public static final int LOGIN_ID = 2; private final ProtocolVersion protocolVersion; private final String serverAddress; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/MinecraftDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/MinecraftDecoder.java index 6ef4df737..68709a732 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/MinecraftDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/MinecraftDecoder.java @@ -20,9 +20,11 @@ package com.velocitypowered.proxy.network.pipeline; import com.google.common.base.Preconditions; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.Packet; import com.velocitypowered.proxy.network.packet.PacketDirection; +import com.velocitypowered.proxy.network.registry.packet.PacketRegistryMap; +import com.velocitypowered.proxy.network.registry.protocol.ProtocolRegistry; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import com.velocitypowered.proxy.util.except.QuietRuntimeException; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; @@ -37,8 +39,9 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { + "developer, launch Velocity with -Dvelocity.packet-decode-logging=true to see more."); private final PacketDirection direction; - private StateRegistry state; - private StateRegistry.PacketRegistry.ProtocolRegistry registry; + private ProtocolVersion version; + private ProtocolRegistry state; + private PacketRegistryMap registry; /** * Creates a new {@code MinecraftDecoder} decoding packets from the specified {@code direction}. @@ -47,9 +50,9 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { */ public MinecraftDecoder(PacketDirection direction) { this.direction = Preconditions.checkNotNull(direction, "direction"); - this.registry = StateRegistry.HANDSHAKE.getProtocolRegistry(direction, - ProtocolVersion.MINIMUM_VERSION); - this.state = StateRegistry.HANDSHAKE; + this.state = ProtocolStates.HANDSHAKE; + this.version = ProtocolVersion.MINIMUM_VERSION; + this.registry = this.state.lookup(direction, ProtocolVersion.MINIMUM_VERSION); } @Override @@ -72,7 +75,7 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { int packetId = ProtocolUtils.readVarInt(buf); Packet packet = null; try { - packet = this.registry.readPacket(packetId, buf, registry.version); + packet = this.registry.readPacket(packetId, buf, this.version); } catch (Exception e) { throw handleDecodeFailure(e, packet, packetId); // TODO: packet is always null } @@ -92,8 +95,8 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { } private void doLengthSanityChecks(ByteBuf buf, Packet packet) throws Exception { - int expectedMinLen = packet.expectedMinLength(buf, direction, registry.version); - int expectedMaxLen = packet.expectedMaxLength(buf, direction, registry.version); + int expectedMinLen = packet.expectedMinLength(buf, direction, version); + int expectedMaxLen = packet.expectedMaxLength(buf, direction, version); if (expectedMaxLen != -1 && buf.readableBytes() > expectedMaxLen) { throw handleOverflow(packet, expectedMaxLen, buf.readableBytes()); } @@ -130,16 +133,17 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { } private String getExtraConnectionDetail(int packetId) { - return "Direction " + direction + " Protocol " + registry.version + " State " + state + return "Direction " + direction + " Protocol " + version + " State " + state + " ID " + Integer.toHexString(packetId); } public void setProtocolVersion(ProtocolVersion protocolVersion) { - this.registry = state.getProtocolRegistry(direction, protocolVersion); + this.version = protocolVersion; + this.registry = state.lookup(direction, protocolVersion); } - public void setState(StateRegistry state) { + public void setState(ProtocolRegistry state) { this.state = state; - this.setProtocolVersion(registry.version); + this.setProtocolVersion(this.version); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/MinecraftEncoder.java b/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/MinecraftEncoder.java index 5931ef27f..ef861a841 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/MinecraftEncoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/MinecraftEncoder.java @@ -19,10 +19,11 @@ package com.velocitypowered.proxy.network.pipeline; import com.google.common.base.Preconditions; import com.velocitypowered.api.network.ProtocolVersion; -import com.velocitypowered.proxy.network.ProtocolUtils; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.Packet; import com.velocitypowered.proxy.network.packet.PacketDirection; +import com.velocitypowered.proxy.network.registry.packet.PacketRegistryMap; +import com.velocitypowered.proxy.network.registry.protocol.ProtocolRegistry; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; @@ -30,8 +31,9 @@ import io.netty.handler.codec.MessageToByteEncoder; public class MinecraftEncoder extends MessageToByteEncoder { private final PacketDirection direction; - private StateRegistry state; - private StateRegistry.PacketRegistry.ProtocolRegistry registry; + private ProtocolRegistry state; + private PacketRegistryMap registry; + private ProtocolVersion version; /** * Creates a new {@code MinecraftEncoder} encoding packets for the specified {@code direction}. @@ -40,22 +42,23 @@ public class MinecraftEncoder extends MessageToByteEncoder { */ public MinecraftEncoder(PacketDirection direction) { this.direction = Preconditions.checkNotNull(direction, "direction"); - this.registry = StateRegistry.HANDSHAKE - .getProtocolRegistry(direction, ProtocolVersion.MINIMUM_VERSION); - this.state = StateRegistry.HANDSHAKE; + this.state = ProtocolStates.HANDSHAKE; + this.version = ProtocolVersion.MINIMUM_VERSION; + this.registry = this.state.lookup(direction, ProtocolVersion.MINIMUM_VERSION); } @Override protected void encode(ChannelHandlerContext ctx, Packet msg, ByteBuf out) { - this.registry.writePacket(msg, out, registry.version); + this.registry.writePacket(msg, out, this.version); } public void setProtocolVersion(final ProtocolVersion protocolVersion) { - this.registry = state.getProtocolRegistry(direction, protocolVersion); + this.version = protocolVersion; + this.registry = this.state.lookup(direction, protocolVersion); } - public void setState(StateRegistry state) { + public void setState(ProtocolRegistry state) { this.state = state; - this.setProtocolVersion(registry.version); + this.setProtocolVersion(version); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/DensePacketRegistryMap.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/DensePacketRegistryMap.java index 4c8ecbe77..6ef0013f1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/DensePacketRegistryMap.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/DensePacketRegistryMap.java @@ -1,6 +1,24 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.packet; import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -19,6 +37,7 @@ public class DensePacketRegistryMap implements PacketRegistryMap { private final PacketReader[] readersById; private final PacketWriter[] writersByClass; private final Class[] classesById; + private final int[] idsByKey; public DensePacketRegistryMap(Int2ObjectMap> mappings) { int size = mappings.keySet().stream().mapToInt(x -> x).max().orElse(0) + 1; @@ -26,17 +45,19 @@ public class DensePacketRegistryMap implements PacketRegistryMap { this.readersById = new PacketReader[size]; this.writersByClass = new PacketWriter[size * 2]; this.classesById = new Class[size * 2]; + this.idsByKey = new int[size * 2]; for (PacketMapping value : mappings.values()) { this.readersById[value.id] = value.reader; - this.place(value.packetClass, value.writer); + this.place(value.id, value.packetClass, value.writer); } } - private void place(Class key, PacketWriter value) { + private void place(int packetId, Class key, PacketWriter value) { int bucket = findEmpty(key); this.writersByClass[bucket] = value; this.classesById[bucket] = key; + this.idsByKey[bucket] = packetId; } private int findEmpty(Class key) { @@ -86,9 +107,10 @@ public class DensePacketRegistryMap implements PacketRegistryMap { @Override public

void writePacket(P packet, ByteBuf buf, ProtocolVersion version) { - int id = this.index(packet.getClass()); - if (id != -1) { - this.writersByClass[id].write(buf, packet, version); + int bucket = this.index(packet.getClass()); + if (bucket != -1) { + ProtocolUtils.writeVarInt(buf, this.idsByKey[bucket]); + this.writersByClass[bucket].write(buf, packet, version); } else { throw new IllegalArgumentException(String.format( "Unable to find id for packet of type %s in protocol %s", diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/EmptyPacketRegistryMap.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/EmptyPacketRegistryMap.java index 35443f210..45b7ae61d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/EmptyPacketRegistryMap.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/EmptyPacketRegistryMap.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.packet; import com.velocitypowered.api.network.ProtocolVersion; @@ -21,7 +38,7 @@ public class EmptyPacketRegistryMap implements PacketRegistryMap { @Override public

void writePacket(P packet, ByteBuf buf, ProtocolVersion version) { throw new IllegalArgumentException(String.format( - "Unable to find id for packet of type %s in protocol %s", + "Unable to find id for packet of type %s for version %s", packet.getClass().getName(), version )); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/PacketRegistryBuilder.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/PacketRegistryBuilder.java index 5de1b3482..2f9f89fd0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/PacketRegistryBuilder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/PacketRegistryBuilder.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.packet; import com.velocitypowered.proxy.network.packet.Packet; @@ -16,8 +33,7 @@ public class PacketRegistryBuilder { this.mappings = new Int2ObjectOpenHashMap<>(); } - public PacketRegistryBuilder( - Int2ObjectMap> mappings, boolean dense) { + public PacketRegistryBuilder(Int2ObjectMap> mappings, boolean dense) { this.mappings = new Int2ObjectOpenHashMap<>(mappings); this.dense = dense; } @@ -29,7 +45,7 @@ public class PacketRegistryBuilder { } public

PacketRegistryBuilder register(int id, Class

packetClass, - PacketWriter

writer, PacketReader

reader) { + PacketReader

reader, PacketWriter

writer) { mappings.put(id, new PacketMapping(id, packetClass, writer, reader)); return this; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/PacketRegistryMap.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/PacketRegistryMap.java index d635abc09..bc1ed9e4c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/PacketRegistryMap.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/PacketRegistryMap.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.packet; import com.velocitypowered.api.network.ProtocolVersion; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/RegularPacketRegistryMap.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/RegularPacketRegistryMap.java index f62fb894d..0577620f7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/RegularPacketRegistryMap.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/RegularPacketRegistryMap.java @@ -1,6 +1,24 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.packet; import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -60,7 +78,7 @@ public class RegularPacketRegistryMap implements PacketRegistryMap { PacketWriter writer = this.writersById.get(packetId); assert writer != null; + ProtocolUtils.writeVarInt(buf, packetId); writer.write(buf, packet, version); - } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/ProtocolRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/ProtocolRegistry.java index 8ebe4886e..9f0852d33 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/ProtocolRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/ProtocolRegistry.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.protocol; import com.velocitypowered.api.network.ProtocolVersion; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/SimpleProtocolRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/SimpleProtocolRegistry.java index 83862361d..30636ca4f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/SimpleProtocolRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/SimpleProtocolRegistry.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.protocol; import com.velocitypowered.api.network.ProtocolVersion; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/VersionSpecificProtocolRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/VersionSpecificProtocolRegistry.java index 7497c7e7c..f8db927b3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/VersionSpecificProtocolRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/VersionSpecificProtocolRegistry.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.protocol; import com.velocitypowered.api.network.ProtocolVersion; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/LoginPacketRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/LoginPacketRegistry.java new file mode 100644 index 000000000..3742762e0 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/LoginPacketRegistry.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.network.registry.state; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket; +import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket; +import com.velocitypowered.proxy.network.packet.clientbound.ClientboundLoginPluginMessagePacket; +import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket; +import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket; +import com.velocitypowered.proxy.network.packet.serverbound.ServerboundEncryptionResponsePacket; +import com.velocitypowered.proxy.network.packet.serverbound.ServerboundLoginPluginResponsePacket; +import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket; +import com.velocitypowered.proxy.network.registry.packet.PacketRegistryBuilder; +import com.velocitypowered.proxy.network.registry.packet.PacketRegistryMap; + +public class LoginPacketRegistry { + private LoginPacketRegistry() { + throw new AssertionError(); + } + + public static final PacketRegistryMap SERVERBOUND_LOGIN_1_7 = baseProtocolServerbound().build(); + + public static final PacketRegistryMap CLIENTBOUND_LOGIN_1_7 = baseProtocolClientbound().build(); + + public static final PacketRegistryMap CLIENTBOUND_LOGIN_1_8 = baseProtocolClientbound() + .register(0x03, ClientboundSetCompressionPacket.class, + ClientboundSetCompressionPacket.DECODER, + ClientboundSetCompressionPacket.ENCODER) + .build(); + + public static final PacketRegistryMap CLIENTBOUND_LOGIN_1_13 = baseProtocolClientbound() + .register(0x03, ClientboundSetCompressionPacket.class, + ClientboundSetCompressionPacket.DECODER, + ClientboundSetCompressionPacket.ENCODER) + .register(0x04, ClientboundLoginPluginMessagePacket.class, + ClientboundLoginPluginMessagePacket.DECODER, + ClientboundLoginPluginMessagePacket.ENCODER) + .build(); + + public static final PacketRegistryMap SERVERBOUND_LOGIN_1_13 = baseProtocolServerbound() + .register(0x02, ServerboundLoginPluginResponsePacket.class, + ServerboundLoginPluginResponsePacket.DECODER, + ServerboundLoginPluginResponsePacket.ENCODER) + .build(); + + private static PacketRegistryBuilder baseProtocolServerbound() { + return new PacketRegistryBuilder() + .dense() + .register(0x00, ServerboundServerLoginPacket.class, ServerboundServerLoginPacket.DECODER, + ServerboundServerLoginPacket.ENCODER + ) + .register(0x01, ServerboundEncryptionResponsePacket.class, + ServerboundEncryptionResponsePacket.DECODER, + ServerboundEncryptionResponsePacket.ENCODER); + } + + private static PacketRegistryBuilder baseProtocolClientbound() { + return new PacketRegistryBuilder() + .dense() + .register(0x00, ClientboundDisconnectPacket.class, ClientboundDisconnectPacket.DECODER, + ClientboundDisconnectPacket.ENCODER) + .register(0x01, ClientboundEncryptionRequestPacket.class, + ClientboundEncryptionRequestPacket.DECODER, ClientboundEncryptionRequestPacket.ENCODER) + .register(0x02, ClientboundServerLoginSuccessPacket.class, + ClientboundServerLoginSuccessPacket.DECODER, + ClientboundServerLoginSuccessPacket.ENCODER); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/PlayPacketRegistry.java similarity index 79% rename from proxy/src/main/java/com/velocitypowered/proxy/network/StateRegistry.java rename to proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/PlayPacketRegistry.java index 2ba906f23..885534ff1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/PlayPacketRegistry.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.velocitypowered.proxy.network; +package com.velocitypowered.proxy.network.registry.state; import static com.google.common.collect.Iterables.getLast; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12; @@ -33,6 +33,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINIMUM_VERSION; import static com.velocitypowered.api.network.ProtocolVersion.SUPPORTED_VERSIONS; import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketReader; @@ -41,88 +42,44 @@ import com.velocitypowered.proxy.network.packet.clientbound.ClientboundAvailable import com.velocitypowered.proxy.network.packet.clientbound.ClientboundBossBarPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundChatPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket; -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundHeaderAndFooterPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundJoinGamePacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundKeepAlivePacket; -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundLoginPluginMessagePacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerListItemPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPluginMessagePacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundResourcePackRequestPacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundRespawnPacket; -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket; -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket; -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundStatusPingPacket; -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundStatusResponsePacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTabCompleteResponsePacket; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTitlePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundChatPacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundClientSettingsPacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundEncryptionResponsePacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundKeepAlivePacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundLoginPluginResponsePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundResourcePackResponsePacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusPingPacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusRequestPacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundTabCompleteRequestPacket; +import com.velocitypowered.proxy.network.registry.packet.PacketRegistryMap; +import com.velocitypowered.proxy.network.registry.protocol.ProtocolRegistry; import io.netty.buffer.ByteBuf; import io.netty.util.collection.IntObjectHashMap; import io.netty.util.collection.IntObjectMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import java.util.Collections; import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import org.checkerframework.checker.nullness.qual.Nullable; -public enum StateRegistry { +class PlayPacketRegistry implements ProtocolRegistry { - HANDSHAKE(true) { - { - serverbound.register( - ServerboundHandshakePacket.class, - ServerboundHandshakePacket.DECODER, - ServerboundHandshakePacket.ENCODER, - map(0x00, MINECRAFT_1_7_2, false) - ); - } - }, - STATUS(true) { - { - serverbound.register( - ServerboundStatusRequestPacket.class, - ServerboundStatusRequestPacket.DECODER, - ServerboundStatusRequestPacket.ENCODER, - map(0x00, MINECRAFT_1_7_2, false) - ); - serverbound.register( - ServerboundStatusPingPacket.class, - ServerboundStatusPingPacket.DECODER, - ServerboundStatusPingPacket.ENCODER, - map(0x01, MINECRAFT_1_7_2, false) - ); + static final ProtocolRegistry PLAY = new PlayPacketRegistry(); + + private PlayPacketRegistry() { + this.clientbound = new PacketRegistry(PacketDirection.CLIENTBOUND); + this.serverbound = new PacketRegistry(PacketDirection.SERVERBOUND); - clientbound.register( - ClientboundStatusResponsePacket.class, - ClientboundStatusResponsePacket.DECODER, - ClientboundStatusResponsePacket.ENCODER, - map(0x00, MINECRAFT_1_7_2, false) - ); - clientbound.register( - ClientboundStatusPingPacket.class, - ClientboundStatusPingPacket.DECODER, - ClientboundStatusPingPacket.ENCODER, - map(0x01, MINECRAFT_1_7_2, false) - ); - } - }, - PLAY(false) { { serverbound.register( ServerboundTabCompleteRequestPacket.class, @@ -346,73 +303,16 @@ public enum StateRegistry { map(0x32, MINECRAFT_1_16_2, false) ); } - }, - LOGIN(true) { - { - serverbound.register( - ServerboundServerLoginPacket.class, - ServerboundServerLoginPacket.DECODER, - ServerboundServerLoginPacket.ENCODER, - map(0x00, MINECRAFT_1_7_2, false) - ); - serverbound.register( - ServerboundEncryptionResponsePacket.class, - ServerboundEncryptionResponsePacket.DECODER, - ServerboundEncryptionResponsePacket.ENCODER, - map(0x01, MINECRAFT_1_7_2, false) - ); - serverbound.register( - ServerboundLoginPluginResponsePacket.class, - ServerboundLoginPluginResponsePacket.DECODER, - ServerboundLoginPluginResponsePacket.ENCODER, - map(0x02, MINECRAFT_1_13, false) - ); - clientbound.register( - ClientboundDisconnectPacket.class, - ClientboundDisconnectPacket.DECODER, - ClientboundDisconnectPacket.ENCODER, - map(0x00, MINECRAFT_1_7_2, false) - ); - clientbound.register( - ClientboundEncryptionRequestPacket.class, - ClientboundEncryptionRequestPacket.DECODER, - ClientboundEncryptionRequestPacket.ENCODER, - map(0x01, MINECRAFT_1_7_2, false) - ); - clientbound.register( - ClientboundServerLoginSuccessPacket.class, - ClientboundServerLoginSuccessPacket.DECODER, - ClientboundServerLoginSuccessPacket.ENCODER, - map(0x02, MINECRAFT_1_7_2, false) - ); - clientbound.register( - ClientboundSetCompressionPacket.class, - ClientboundSetCompressionPacket.DECODER, - ClientboundSetCompressionPacket.ENCODER, - map(0x03, MINECRAFT_1_8, false) - ); - clientbound.register( - ClientboundLoginPluginMessagePacket.class, - ClientboundLoginPluginMessagePacket.DECODER, - ClientboundLoginPluginMessagePacket.ENCODER, - map(0x04, MINECRAFT_1_13, false) - ); - } - }; + serverbound.compact(); + clientbound.compact(); + } - public static final int STATUS_ID = 1; - public static final int LOGIN_ID = 2; public final PacketRegistry clientbound; public final PacketRegistry serverbound; - StateRegistry(boolean useMinimumIfVersionNotFound) { - this.clientbound = new PacketRegistry(PacketDirection.CLIENTBOUND, useMinimumIfVersionNotFound); - this.serverbound = new PacketRegistry(PacketDirection.SERVERBOUND, useMinimumIfVersionNotFound); - } - - public PacketRegistry.ProtocolRegistry getProtocolRegistry(PacketDirection direction, - ProtocolVersion version) { + public PacketRegistryMap lookup(PacketDirection direction, + ProtocolVersion version) { return (direction == PacketDirection.SERVERBOUND ? this.serverbound : this.clientbound) .getProtocolRegistry(version); } @@ -421,15 +321,9 @@ public enum StateRegistry { private final PacketDirection direction; private final Map versions; - private final boolean useMinimumIfVersionNotFound; PacketRegistry(PacketDirection direction) { - this(direction, true); - } - - PacketRegistry(PacketDirection direction, boolean useMinimumIfVersionNotFound) { this.direction = direction; - this.useMinimumIfVersionNotFound = useMinimumIfVersionNotFound; Map mutableVersions = new EnumMap<>(ProtocolVersion.class); for (ProtocolVersion version : ProtocolVersion.values()) { @@ -438,15 +332,12 @@ public enum StateRegistry { } } - this.versions = Collections.unmodifiableMap(mutableVersions); + this.versions = mutableVersions; } ProtocolRegistry getProtocolRegistry(final ProtocolVersion version) { ProtocolRegistry registry = versions.get(version); if (registry == null) { - if (useMinimumIfVersionNotFound) { - return getProtocolRegistry(MINIMUM_VERSION); - } throw new IllegalArgumentException("Could not find data for protocol version " + version); } return registry; @@ -499,9 +390,26 @@ public enum StateRegistry { } } - public class ProtocolRegistry { + public void compact() { + ProtocolRegistry last = this.versions.get(MINIMUM_VERSION); + for (Entry entry : this.versions + .entrySet()) { + if (entry.getValue() == last) { + continue; + } - public final ProtocolVersion version; + if (entry.getValue().packetClassToId.equals(last.packetClassToId) + && entry.getValue().packetClassToWriter.equals(last.packetClassToWriter)) { + entry.setValue(last); + } else { + last = entry.getValue(); + } + } + } + + public class ProtocolRegistry implements PacketRegistryMap { + + private final ProtocolVersion version; final IntObjectMap> packetIdToReader = new IntObjectHashMap<>(16, 0.5f); final Object2IntMap> packetClassToId = @@ -519,7 +427,6 @@ public enum StateRegistry { * * @param id the packet ID * @param buf the bytebuf - * @param version the protocol version * @return the packet instance, or {@code null} if the ID is not registered */ public @Nullable Packet readPacket(final int id, ByteBuf buf, ProtocolVersion version) { @@ -535,7 +442,6 @@ public enum StateRegistry { * * @param packet the packet * @param buf the bytebuf - * @param version the protocol version */ public

void writePacket(P packet, ByteBuf buf, ProtocolVersion version) { final int id = this.packetClassToId.getInt(packet.getClass()); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/ProtocolStates.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/ProtocolStates.java index 1a9a5b813..24d3ba8be 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/ProtocolStates.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/ProtocolStates.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package com.velocitypowered.proxy.network.registry.state; import com.velocitypowered.api.network.ProtocolVersion; @@ -16,39 +33,43 @@ public class ProtocolStates { public static final ProtocolRegistry HANDSHAKE; public static final ProtocolRegistry STATUS; public static final ProtocolRegistry LOGIN; + public static final ProtocolRegistry PLAY; static { HANDSHAKE = new SimpleProtocolRegistry( new PacketRegistryBuilder() - .dense() - .register(0x00, ServerboundHandshakePacket.class, ServerboundHandshakePacket.ENCODER, - ServerboundHandshakePacket.DECODER) + .register(0x00, ServerboundHandshakePacket.class, ServerboundHandshakePacket.DECODER, + ServerboundHandshakePacket.ENCODER) .build(), EmptyPacketRegistryMap.INSTANCE); STATUS = new SimpleProtocolRegistry( new PacketRegistryBuilder() - .dense() .register(0x00, ServerboundStatusRequestPacket.class, - ServerboundStatusRequestPacket.ENCODER, - ServerboundStatusRequestPacket.DECODER) + ServerboundStatusRequestPacket.DECODER, ServerboundStatusRequestPacket.ENCODER + ) .register(0x01, ServerboundStatusPingPacket.class, - ServerboundStatusPingPacket.ENCODER, - ServerboundStatusPingPacket.DECODER) + ServerboundStatusPingPacket.DECODER, ServerboundStatusPingPacket.ENCODER + ) .build(), new PacketRegistryBuilder() - .dense() .register(0x00, ClientboundStatusResponsePacket.class, - ClientboundStatusResponsePacket.ENCODER, - ClientboundStatusResponsePacket.DECODER) + ClientboundStatusResponsePacket.DECODER, ClientboundStatusResponsePacket.ENCODER + ) .register(0x01, ClientboundStatusPingPacket.class, - ClientboundStatusPingPacket.ENCODER, - ClientboundStatusPingPacket.DECODER) + ClientboundStatusPingPacket.DECODER, ClientboundStatusPingPacket.ENCODER + ) .build()); LOGIN = new VersionSpecificProtocolRegistry() - .register(ProtocolVersion.MINECRAFT_1_7_2, ProtocolVersion.MINECRAFT_1_8, - Version172To176.SERVERBOUND_LOGIN, Version172To176.CLIENTBOUND_LOGIN); + .register(ProtocolVersion.MINECRAFT_1_7_2, ProtocolVersion.MINECRAFT_1_7_6, + LoginPacketRegistry.SERVERBOUND_LOGIN_1_7, LoginPacketRegistry.CLIENTBOUND_LOGIN_1_7) + .register(ProtocolVersion.MINECRAFT_1_8, ProtocolVersion.MINECRAFT_1_12_2, + LoginPacketRegistry.SERVERBOUND_LOGIN_1_7, LoginPacketRegistry.CLIENTBOUND_LOGIN_1_8) + .register(ProtocolVersion.MINECRAFT_1_13, ProtocolVersion.MAXIMUM_VERSION, + LoginPacketRegistry.SERVERBOUND_LOGIN_1_13, LoginPacketRegistry.CLIENTBOUND_LOGIN_1_13); + + PLAY = PlayPacketRegistry.PLAY; } private ProtocolStates() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/Version172To176.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/Version172To176.java deleted file mode 100644 index bfe95825f..000000000 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/Version172To176.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.velocitypowered.proxy.network.registry.state; - -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket; -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket; -import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundEncryptionResponsePacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket; -import com.velocitypowered.proxy.network.packet.serverbound.ServerboundTabCompleteRequestPacket; -import com.velocitypowered.proxy.network.registry.packet.PacketRegistryBuilder; -import com.velocitypowered.proxy.network.registry.packet.PacketRegistryMap; - -public class Version172To176 { - private Version172To176() { - throw new AssertionError(); - } - - public static final PacketRegistryMap SERVERBOUND_LOGIN = new PacketRegistryBuilder() - .dense() - .register(0x00, ServerboundServerLoginPacket.class, ServerboundServerLoginPacket.ENCODER, - ServerboundServerLoginPacket.DECODER) - .register(0x01, ServerboundEncryptionResponsePacket.class, - ServerboundEncryptionResponsePacket.ENCODER, ServerboundEncryptionResponsePacket.DECODER) - .build(); - - public static final PacketRegistryMap CLIENTBOUND_LOGIN = new PacketRegistryBuilder() - .dense() - .register(0x00, ClientboundDisconnectPacket.class, ClientboundDisconnectPacket.ENCODER, - ClientboundDisconnectPacket.DECODER) - .register(0x01, ClientboundEncryptionRequestPacket.class, - ClientboundEncryptionRequestPacket.ENCODER, ClientboundEncryptionRequestPacket.DECODER) - .register(0x02, ClientboundServerLoginSuccessPacket.class, - ClientboundServerLoginSuccessPacket.ENCODER, ClientboundServerLoginSuccessPacket.DECODER) - .build(); - - public static final PacketRegistryMap SERVERBOUND_PLAY = new PacketRegistryBuilder() - .register(0x14, ServerboundTabCompleteRequestPacket.class, - ServerboundTabCompleteRequestPacket.ENCODER, ServerboundTabCompleteRequestPacket.DECODER) - .build(); -} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/version/GenericVersions.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/version/GenericVersions.java deleted file mode 100644 index 9069f39a1..000000000 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/version/GenericVersions.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.velocitypowered.proxy.network.registry.version; - -public class GenericVersions { - -} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/server/PingSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/server/PingSessionHandler.java index 63e2447d2..7a2b3daca 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/server/PingSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/server/PingSessionHandler.java @@ -23,10 +23,10 @@ import com.velocitypowered.api.proxy.server.ServerPing; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; -import com.velocitypowered.proxy.network.StateRegistry; import com.velocitypowered.proxy.network.packet.clientbound.ClientboundStatusResponsePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket; import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusRequestPacket; +import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; @@ -67,10 +67,10 @@ public class PingSessionHandler implements MinecraftSessionHandler { version, hostname, port, - StateRegistry.STATUS_ID + ServerboundHandshakePacket.STATUS_ID )); - connection.setState(StateRegistry.STATUS); + connection.setState(ProtocolStates.STATUS); connection.delayedWrite(ServerboundStatusRequestPacket.INSTANCE); connection.flush();