From bc57512ca2d0261c5c67d20fbaf6e35daeb87ea3 Mon Sep 17 00:00:00 2001 From: EnZaXD Date: Wed, 21 Aug 2024 14:35:19 +0200 Subject: [PATCH] Allow for multiple base protocols per version (#4106) --- .../api/protocol/ProtocolManager.java | 6 +- .../protocol/ProtocolManagerImpl.java | 19 +-- .../protocols/base/BaseProtocol1_16.java | 30 ----- ...Protocol.java => InitialBaseProtocol.java} | 24 ++-- .../ClientboundBaseProtocol1_7.java} | 111 ++++++++---------- .../base/v1_7/ServerboundBaseProtocol1_7.java | 83 +++++++++++++ 6 files changed, 157 insertions(+), 116 deletions(-) delete mode 100644 common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol1_16.java rename common/src/main/java/com/viaversion/viaversion/protocols/base/{BaseProtocol.java => InitialBaseProtocol.java} (90%) rename common/src/main/java/com/viaversion/viaversion/protocols/base/{BaseProtocol1_7.java => v1_7/ClientboundBaseProtocol1_7.java} (70%) create mode 100644 common/src/main/java/com/viaversion/viaversion/protocols/base/v1_7/ServerboundBaseProtocol1_7.java diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java index 468d32bcd..51a6c68c3 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java @@ -73,13 +73,13 @@ public interface ProtocolManager { Protocol getBaseProtocol(); /** - * Returns the base protocol for a specific server protocol version. + * Returns the base protocols for a specific server protocol version. * The standard base protocols deal with status and login packets for userconnection initialization. * * @param serverVersion server protocol version - * @return base protocol for the given server protocol version if present, else null + * @return base protocols for the given server protocol version if present, else null */ - @Nullable Protocol getBaseProtocol(ProtocolVersion serverVersion); + List getBaseProtocols(ProtocolVersion serverVersion); /** * Returns an immutable collection of registered protocols. diff --git a/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java b/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java index a9eef13b3..f9aa1ba95 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java +++ b/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java @@ -38,9 +38,9 @@ import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion; import com.viaversion.viaversion.api.protocol.version.VersionType; import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl; import com.viaversion.viaversion.protocol.packet.VersionedPacketTransformerImpl; -import com.viaversion.viaversion.protocols.base.BaseProtocol; -import com.viaversion.viaversion.protocols.base.BaseProtocol1_16; -import com.viaversion.viaversion.protocols.base.BaseProtocol1_7; +import com.viaversion.viaversion.protocols.base.InitialBaseProtocol; +import com.viaversion.viaversion.protocols.base.v1_7.ClientboundBaseProtocol1_7; +import com.viaversion.viaversion.protocols.base.v1_7.ServerboundBaseProtocol1_7; import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21; import com.viaversion.viaversion.protocols.v1_10to1_11.Protocol1_10To1_11; import com.viaversion.viaversion.protocols.v1_11_1to1_12.Protocol1_11_1To1_12; @@ -109,7 +109,7 @@ import java.util.logging.Level; import org.checkerframework.checker.nullness.qual.Nullable; public class ProtocolManagerImpl implements ProtocolManager { - private static final Protocol BASE_PROTOCOL = new BaseProtocol(); + private static final Protocol BASE_PROTOCOL = new InitialBaseProtocol(); // Input Version -> Output Version & Protocol (Allows fast lookup) private final Object2ObjectMap> registryMap = new Object2ObjectOpenHashMap<>(32); @@ -137,8 +137,8 @@ public class ProtocolManagerImpl implements ProtocolManager { // Base Protocol BASE_PROTOCOL.initialize(); BASE_PROTOCOL.register(Via.getManager().getProviders()); - registerBaseProtocol(new BaseProtocol1_7(), Range.closedOpen(ProtocolVersion.v1_7_2, ProtocolVersion.v1_16)); - registerBaseProtocol(new BaseProtocol1_16(), Range.atLeast(ProtocolVersion.v1_16)); + registerBaseProtocol(new ClientboundBaseProtocol1_7(), Range.atLeast(ProtocolVersion.v1_7_2)); + registerBaseProtocol(new ServerboundBaseProtocol1_7(), Range.atLeast(ProtocolVersion.v1_7_2)); registerProtocol(new Protocol1_8To1_9(), ProtocolVersion.v1_9, ProtocolVersion.v1_8); registerProtocol(new Protocol1_9To1_9_1(), Arrays.asList(ProtocolVersion.v1_9_1, ProtocolVersion.v1_9_2), ProtocolVersion.v1_9); @@ -365,13 +365,14 @@ public class ProtocolManagerImpl implements ProtocolManager { } @Override - public @Nullable Protocol getBaseProtocol(ProtocolVersion serverVersion) { + public List getBaseProtocols(ProtocolVersion serverVersion) { + final List list = new ArrayList<>(); for (Pair, Protocol> rangeProtocol : Lists.reverse(baseProtocols)) { if (rangeProtocol.key().contains(serverVersion)) { - return rangeProtocol.value(); + list.add(rangeProtocol.value()); } } - return null; + return list; } @Override diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol1_16.java b/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol1_16.java deleted file mode 100644 index 6997b774b..000000000 --- a/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol1_16.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion - * Copyright (C) 2016-2024 ViaVersion and 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.viaversion.viaversion.protocols.base; - -import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; -import com.viaversion.viaversion.api.type.Types; -import java.util.UUID; - -public class BaseProtocol1_16 extends BaseProtocol1_7 { - - @Override - protected UUID passthroughLoginUUID(final PacketWrapper wrapper) { - return wrapper.passthrough(Types.UUID); - } -} diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol.java b/common/src/main/java/com/viaversion/viaversion/protocols/base/InitialBaseProtocol.java similarity index 90% rename from common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol.java rename to common/src/main/java/com/viaversion/viaversion/protocols/base/InitialBaseProtocol.java index bacc45eb1..d14daeeb0 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/base/InitialBaseProtocol.java @@ -39,22 +39,28 @@ import com.viaversion.viaversion.protocol.version.BaseVersionProvider; import com.viaversion.viaversion.protocols.base.packet.BaseClientboundPacket; import com.viaversion.viaversion.protocols.base.packet.BasePacketTypesProvider; import com.viaversion.viaversion.protocols.base.packet.BaseServerboundPacket; + import java.util.ArrayList; import java.util.List; -public class BaseProtocol extends AbstractProtocol { +/** + * Initial base protocol which is kept always in the pipeline. + *

+ * State tracking for configuration state is done via {@link AbstractProtocol#registerConfigurationChangeHandlers()} + */ +public class InitialBaseProtocol extends AbstractProtocol { private static final int STATUS_INTENT = 1; private static final int LOGIN_INTENT = 2; private static final int TRANSFER_INTENT = 3; - public BaseProtocol() { + public InitialBaseProtocol() { super(BaseClientboundPacket.class, BaseClientboundPacket.class, BaseServerboundPacket.class, BaseServerboundPacket.class); } @Override protected void registerPackets() { - // Handshake Packet + // Setup protocol pipeline + track initial state registerServerbound(ServerboundHandshakePackets.CLIENT_INTENTION, wrapper -> { int protocolVersion = wrapper.passthrough(Types.VAR_INT); wrapper.passthrough(Types.STRING); // Server Address @@ -92,12 +98,11 @@ public class BaseProtocol extends AbstractProtocol createPacketTypesProvider() { return BasePacketTypesProvider.INSTANCE; } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol1_7.java b/common/src/main/java/com/viaversion/viaversion/protocols/base/v1_7/ClientboundBaseProtocol1_7.java similarity index 70% rename from common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol1_7.java rename to common/src/main/java/com/viaversion/viaversion/protocols/base/v1_7/ClientboundBaseProtocol1_7.java index 74bb193a1..dffe0bfbd 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol1_7.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/base/v1_7/ClientboundBaseProtocol1_7.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.viaversion.viaversion.protocols.base; +package com.viaversion.viaversion.protocols.base.v1_7; import com.google.common.base.Joiner; import com.google.gson.JsonElement; @@ -26,7 +26,6 @@ import com.viaversion.viaversion.api.connection.ProtocolInfo; import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.protocol.AbstractProtocol; import com.viaversion.viaversion.api.protocol.ProtocolPathEntry; -import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.packet.State; import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider; import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers; @@ -35,25 +34,25 @@ import com.viaversion.viaversion.api.protocol.version.VersionProvider; import com.viaversion.viaversion.api.type.Types; import com.viaversion.viaversion.protocol.ProtocolManagerImpl; import com.viaversion.viaversion.protocol.ServerProtocolVersionSingleton; +import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets; +import com.viaversion.viaversion.protocols.base.ClientboundStatusPackets; import com.viaversion.viaversion.protocols.base.packet.BaseClientboundPacket; import com.viaversion.viaversion.protocols.base.packet.BasePacketTypesProvider; import com.viaversion.viaversion.protocols.base.packet.BaseServerboundPacket; -import com.viaversion.viaversion.util.ChatColorUtil; -import com.viaversion.viaversion.util.ComponentUtil; import com.viaversion.viaversion.util.GsonUtil; -import io.netty.channel.ChannelFuture; import java.util.List; import java.util.UUID; import java.util.logging.Level; -public class BaseProtocol1_7 extends AbstractProtocol { +public class ClientboundBaseProtocol1_7 extends AbstractProtocol { - public BaseProtocol1_7() { + public ClientboundBaseProtocol1_7() { super(BaseClientboundPacket.class, BaseClientboundPacket.class, BaseServerboundPacket.class, BaseServerboundPacket.class); } @Override protected void registerPackets() { + // Handle server pinging sent by the client registerClientbound(ClientboundStatusPackets.STATUS_RESPONSE, new PacketHandlers() { @Override public void register() { @@ -128,60 +127,27 @@ public class BaseProtocol1_7 extends AbstractProtocol { - ProtocolInfo info = wrapper.user().getProtocolInfo(); - if (info.protocolVersion().olderThan(ProtocolVersion.v1_20_2)) { // On 1.20.2+, wait for the login ack - info.setState(State.PLAY); - } - - UUID uuid = passthroughLoginUUID(wrapper); - info.setUuid(uuid); - - String username = wrapper.passthrough(Types.STRING); - info.setUsername(username); - // Add to ported clients - Via.getManager().getConnectionManager().onLoginSuccess(wrapper.user()); - - if (!info.getPipeline().hasNonBaseProtocols()) { // Only base protocol - wrapper.user().setActive(false); - } - - if (Via.getManager().isDebug()) { - // Print out the route to console - Via.getPlatform().getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}", - new Object[]{ - username, - info.protocolVersion().getName(), - Joiner.on(", ").join(info.getPipeline().pipes(), ", ") - }); - } - }); - - // Login Start Packet - registerServerbound(ServerboundLoginPackets.HELLO, wrapper -> { - final UserConnection user = wrapper.user(); - final ProtocolVersion protocol = user.getProtocolInfo().protocolVersion(); - if (Via.getConfig().blockedProtocolVersions().contains(protocol)) { - if (!user.getChannel().isOpen() || !user.shouldApplyBlockProtocol()) { - return; - } - - wrapper.cancel(); // cancel current - - final String disconnectMessage = ChatColorUtil.translateAlternateColorCodes(Via.getConfig().getBlockedDisconnectMsg()); - final PacketWrapper disconnectPacket = PacketWrapper.create(ClientboundLoginPackets.LOGIN_DISCONNECT, user); - disconnectPacket.write(Types.COMPONENT, ComponentUtil.plainToJson(disconnectMessage)); - - // Send and close - final ChannelFuture future = disconnectPacket.sendFuture(null); - future.addListener(f -> user.getChannel().close()); - } - }); - - registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> { final ProtocolInfo info = wrapper.user().getProtocolInfo(); - info.setState(State.CONFIGURATION); + + if (info.serverProtocolVersion().olderThan(ProtocolVersion.v1_16)) { + String uuidString = wrapper.passthrough(Types.STRING); + if (uuidString.length() == 32) { // Trimmed UUIDs are 32 characters + // Trimmed + uuidString = addDashes(uuidString); + } + info.setUuid(UUID.fromString(uuidString)); + } else { + final UUID uuid = wrapper.passthrough(Types.UUID); + info.setUuid(uuid); + } + + final String username = wrapper.passthrough(Types.STRING); + info.setUsername(username); + + // Setup connection + onLoginSuccess(wrapper.user()); }); } @@ -199,13 +165,28 @@ public class BaseProtocol1_7 extends AbstractProtocol. + */ +package com.viaversion.viaversion.protocols.base.v1_7; + +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.connection.ProtocolInfo; +import com.viaversion.viaversion.api.connection.UserConnection; +import com.viaversion.viaversion.api.protocol.AbstractProtocol; +import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; +import com.viaversion.viaversion.api.protocol.packet.State; +import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import com.viaversion.viaversion.api.type.Types; +import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets; +import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets; +import com.viaversion.viaversion.protocols.base.packet.BaseClientboundPacket; +import com.viaversion.viaversion.protocols.base.packet.BasePacketTypesProvider; +import com.viaversion.viaversion.protocols.base.packet.BaseServerboundPacket; +import com.viaversion.viaversion.util.ChatColorUtil; +import com.viaversion.viaversion.util.ComponentUtil; +import io.netty.channel.ChannelFuture; + +public class ServerboundBaseProtocol1_7 extends AbstractProtocol { + + public ServerboundBaseProtocol1_7() { + super(BaseClientboundPacket.class, BaseClientboundPacket.class, BaseServerboundPacket.class, BaseServerboundPacket.class); + } + + @Override + protected void registerPackets() { + // State tracking + registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> { + final ProtocolInfo info = wrapper.user().getProtocolInfo(); + info.setState(State.CONFIGURATION); + }); + + // Handle blocked version disconnect + registerServerbound(ServerboundLoginPackets.HELLO, wrapper -> { + final UserConnection user = wrapper.user(); + final ProtocolVersion protocol = user.getProtocolInfo().protocolVersion(); + if (Via.getConfig().blockedProtocolVersions().contains(protocol)) { + if (!user.getChannel().isOpen() || !user.shouldApplyBlockProtocol()) { + return; + } + + wrapper.cancel(); // cancel current + + final String disconnectMessage = ChatColorUtil.translateAlternateColorCodes(Via.getConfig().getBlockedDisconnectMsg()); + final PacketWrapper disconnectPacket = PacketWrapper.create(ClientboundLoginPackets.LOGIN_DISCONNECT, user); + disconnectPacket.write(Types.COMPONENT, ComponentUtil.plainToJson(disconnectMessage)); + + // Send and close + final ChannelFuture future = disconnectPacket.sendFuture(null); + future.addListener(f -> user.getChannel().close()); + } + }); + } + + @Override + public boolean isBaseProtocol() { + return true; + } + + @Override + protected PacketTypesProvider createPacketTypesProvider() { + return BasePacketTypesProvider.INSTANCE; + } +}