From f6fa70420a463c8ed71ca22308d887dca6240d85 Mon Sep 17 00:00:00 2001 From: Adrian Bergqvist Date: Mon, 28 Nov 2022 20:56:08 +0100 Subject: [PATCH] Removed some handlers (simplified the mechanism) --- build.gradle | 2 +- .../org/adde0109/ambassador/Ambassador.java | 8 ++- .../forge/FML2CRPMClientConnectionPhase.java | 18 +++--- .../forge/FML2CRPMOutboundCatcher.java | 56 ----------------- .../forge/FML2ClientConnectionPhase.java | 6 +- .../velocity/VelocityEventHandler.java | 6 +- .../VelocityForgeClientConnectionPhase.java | 2 +- .../backend/ForgeHandshakeSessionHandler.java | 28 +++++++-- .../VelocityForgeBackendConnectionPhase.java | 41 +++++-------- .../VelocityForgeBackendHandshakeHandler.java | 60 +++---------------- 10 files changed, 70 insertions(+), 157 deletions(-) delete mode 100644 src/main/java/org/adde0109/ambassador/forge/FML2CRPMOutboundCatcher.java diff --git a/build.gradle b/build.gradle index 848296e..b762dfd 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'org.adde0109' -version '1.1.4-alpha' +version '1.1.5-alpha' repositories { maven { diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index 68f478e..d5e98d2 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -25,7 +25,7 @@ import org.slf4j.Logger; import java.nio.file.Path; -@Plugin(id = "ambassador", name = "Ambassador", version = "1.1.4-alpha", authors = {"adde0109"}) +@Plugin(id = "ambassador", name = "Ambassador", version = "1.1.5-alpha", authors = {"adde0109"}) public class Ambassador { public ProxyServer server; @@ -33,7 +33,10 @@ public class Ambassador { private final Metrics.Factory metricsFactory; private final Path dataDirectory; - + private static Ambassador instance; + public static Ambassador getInstance() { + return instance; + } @Inject @@ -42,6 +45,7 @@ public class Ambassador { this.logger = logger; this.dataDirectory = dataDirectory; this.metricsFactory = metricsFactory; + Ambassador.instance = this; } @Subscribe(order = PostOrder.LAST) diff --git a/src/main/java/org/adde0109/ambassador/forge/FML2CRPMClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/FML2CRPMClientConnectionPhase.java index 18a33f4..433201a 100644 --- a/src/main/java/org/adde0109/ambassador/forge/FML2CRPMClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/FML2CRPMClientConnectionPhase.java @@ -14,6 +14,7 @@ import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.packet.PluginMessage; import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; import io.netty.buffer.Unpooled; +import org.adde0109.ambassador.Ambassador; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.adde0109.ambassador.velocity.VelocityForgeHandshakeSessionHandler; import org.adde0109.ambassador.velocity.VelocityLoginPayloadManager; @@ -32,10 +33,8 @@ public class FML2CRPMClientConnectionPhase extends VelocityForgeClientConnection public FML2CRPMClientConnectionPhase(VelocityForgeClientConnectionPhase.ClientPhase clientPhase, VelocityLoginPayloadManager payloadManager) { super(clientPhase,payloadManager); } - public FML2CRPMClientConnectionPhase() { - } - public CompletableFuture reset(VelocityServerConnection serverConnection, ConnectedPlayer player) { + public CompletableFuture reset(RegisteredServer server, ConnectedPlayer player) { CompletableFuture future = new CompletableFuture<>(); if (player.getConnectedServer() != null) { backupServer = player.getConnectedServer().getServer(); @@ -46,26 +45,23 @@ public class FML2CRPMClientConnectionPhase extends VelocityForgeClientConnection MinecraftConnection connection = player.getConnection(); connection.setSessionHandler(new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),this)); - serverConnection.getConnection().getChannel().config().setAutoRead(false); + ((VelocityServer) Ambassador.getInstance().server).unregisterConnection(player); + this.clientPhase = null; ScheduledFuture scheduledFuture = connection.eventLoop().schedule(()-> { - connection.getChannel().pipeline().remove(ForgeConstants.OUTBOUND_CATCHER_NAME); - + connection.getChannel().pipeline().remove(ForgeConstants.RESET_LISTENER); future.complete(false); },5, TimeUnit.SECONDS); - connection.getChannel().pipeline().addBefore(Connections.MINECRAFT_DECODER,ForgeConstants.RESET_LISTENER,new FML2CRPMResetCompleteDecoder()); + connection.getChannel().pipeline().addBefore(Connections.MINECRAFT_DECODER, ForgeConstants.RESET_LISTENER,new FML2CRPMResetCompleteDecoder()); getPayloadManager().listenFor(98).thenAccept(ignore -> { if (scheduledFuture.cancel(false)) { connection.getChannel().pipeline().remove(ForgeConstants.RESET_LISTENER); connection.setState(StateRegistry.LOGIN); this.clientPhase = ClientPhase.HANDSHAKE; - serverConnection.getConnection().getChannel().config().setAutoRead(true); future.complete(true); } }); connection.write(new PluginMessage("fml:handshake",Unpooled.wrappedBuffer(ForgeHandshakeUtils.generatePluginResetPacket()))); - this.clientPhase = null; - connection.getChannel().pipeline().addBefore(Connections.HANDLER,ForgeConstants.OUTBOUND_CATCHER_NAME,new FML2CRPMOutboundCatcher(connection)); return future; } public void complete(VelocityServer server, ConnectedPlayer player, MinecraftConnection connection) { @@ -82,6 +78,8 @@ public class FML2CRPMClientConnectionPhase extends VelocityForgeClientConnection this.clientPhase = this.clientPhase == ClientPhase.MODLIST ? ClientPhase.MODDED : ClientPhase.VANILLA; connection.setSessionHandler(((VelocityForgeHandshakeSessionHandler) connection.getSessionHandler()).getOriginal()); + connection.setState(StateRegistry.PLAY); + ((VelocityServer) Ambassador.getInstance().server).registerConnection(player); backupServer = null; } diff --git a/src/main/java/org/adde0109/ambassador/forge/FML2CRPMOutboundCatcher.java b/src/main/java/org/adde0109/ambassador/forge/FML2CRPMOutboundCatcher.java deleted file mode 100644 index 4101e98..0000000 --- a/src/main/java/org/adde0109/ambassador/forge/FML2CRPMOutboundCatcher.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.adde0109.ambassador.forge; - -import com.velocitypowered.proxy.connection.MinecraftConnection; -import com.velocitypowered.proxy.protocol.StateRegistry; -import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; -import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundHandlerAdapter; -import io.netty.channel.ChannelPromise; -import io.netty.util.ReferenceCountUtil; - -import java.util.*; - -public class FML2CRPMOutboundCatcher extends ChannelOutboundHandlerAdapter { - - private final MinecraftConnection connection; - - private final Map catchedPackets = Collections.synchronizedMap(new LinkedHashMap<>()); - - public FML2CRPMOutboundCatcher(MinecraftConnection connection) { - this.connection = connection; - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - final Set> s = catchedPackets.entrySet(); - Iterator> i = s.iterator(); - if (!ctx.channel().isActive()) { - while (catchedPackets.entrySet().iterator().hasNext()) { - final Map.Entry entry = i.next(); - ReferenceCountUtil.release(entry.getValue()); - i.remove(); - } - } else { - while (catchedPackets.entrySet().iterator().hasNext()) { - final Map.Entry entry = i.next(); - ctx.write(entry.getValue(),entry.getKey()); - i.remove(); - } - ctx.flush(); - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - if (msg instanceof LoginPluginMessage) { - ctx.write(msg, promise); - } else if (msg instanceof ServerLoginSuccess) { - ctx.write(msg,promise); - connection.setState(StateRegistry.PLAY); - ctx.pipeline().remove(this); - } else { - catchedPackets.put(promise,msg); - } - } -} diff --git a/src/main/java/org/adde0109/ambassador/forge/FML2ClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/FML2ClientConnectionPhase.java index dea432a..ae297a7 100644 --- a/src/main/java/org/adde0109/ambassador/forge/FML2ClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/FML2ClientConnectionPhase.java @@ -69,13 +69,13 @@ public class FML2ClientConnectionPhase extends VelocityForgeClientConnectionPhas } @Override - public CompletableFuture reset(VelocityServerConnection serverConnection, ConnectedPlayer player) { + public CompletableFuture reset(RegisteredServer server, ConnectedPlayer player) { FML2CRPMClientConnectionPhase newPhase = new FML2CRPMClientConnectionPhase(clientPhase,getPayloadManager()); player.setPhase(newPhase); - CompletableFuture future = newPhase.reset(serverConnection,player); + CompletableFuture future = newPhase.reset(server,player); future.thenAccept(success -> { if (!success) { - TEMPORARY_FORCED.put(player.getUsername(),serverConnection.getServer()); + TEMPORARY_FORCED.put(player.getUsername(),server); player.disconnect(Component.text("Please reconnect")); } }); diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java index 9956318..fd9cfc4 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java @@ -57,8 +57,12 @@ public class VelocityEventHandler { event.setResult(ServerPreConnectEvent.ServerResult.denied()); player.setConnectedServer((VelocityServerConnection) phase.internalServerConnection); phase.internalServerConnection = null; + } else if (phase.clientPhase == VelocityForgeClientConnectionPhase.ClientPhase.MODDED) { + player.getConnection().eventLoop().submit(() -> phase.reset(event.getOriginalServer(), (ConnectedPlayer) event.getPlayer()) + .thenAccept((ignored) -> continuation.resume())); + } else { + continuation.resume(); } - continuation.resume(); } @Subscribe(order = PostOrder.LAST) diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java index 88ba422..a7046cd 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java @@ -33,7 +33,7 @@ public abstract class VelocityForgeClientConnectionPhase implements ClientConnec public void handleLogin(ConnectedPlayer player, VelocityServer server, Continuation continuation) { } - public CompletableFuture reset(VelocityServerConnection serverConnection, ConnectedPlayer player) { + public CompletableFuture reset(RegisteredServer server, ConnectedPlayer player) { return CompletableFuture.completedFuture(false); } diff --git a/src/main/java/org/adde0109/ambassador/velocity/backend/ForgeHandshakeSessionHandler.java b/src/main/java/org/adde0109/ambassador/velocity/backend/ForgeHandshakeSessionHandler.java index bd24422..8009ea4 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/ForgeHandshakeSessionHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/ForgeHandshakeSessionHandler.java @@ -4,36 +4,52 @@ import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.backend.LoginSessionHandler; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; +import com.velocitypowered.proxy.protocol.packet.Disconnect; import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; import io.netty.buffer.ByteBuf; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import org.adde0109.ambassador.forge.ForgeConstants; +import org.adde0109.ambassador.forge.ForgeFMLConnectionType; +import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; public class ForgeHandshakeSessionHandler implements MinecraftSessionHandler { private final LoginSessionHandler original; private final VelocityServerConnection serverConnection; - private final VelocityForgeBackendConnectionPhase phase; private final VelocityServer server; public ForgeHandshakeSessionHandler(LoginSessionHandler original, VelocityServerConnection serverConnection, VelocityServer server) { this.original = original; this.serverConnection = serverConnection; - this.phase = (VelocityForgeBackendConnectionPhase) serverConnection.getPhase(); this.server = server; } @Override public boolean handle(LoginPluginMessage packet) { - if (phase.handle(serverConnection,serverConnection.getPlayer(),packet)) { + if (packet.getChannel().equals("fml:loginwrapper")) { + if (!(serverConnection.getConnection().getType() instanceof ForgeFMLConnectionType)) { + if (!(serverConnection.getPlayer().getConnection().getType() instanceof ForgeFMLConnectionType clientType)) { + final String reason = "This server has mods that require Forge to be installed on the client. Contact your server admin for more details."; + original.handle(new Disconnect(reason)); + return true; + } + serverConnection.getConnection().setType(clientType); + serverConnection.setConnectionPhase(clientType.getInitialBackendPhase()); + } + ((VelocityForgeBackendConnectionPhase) serverConnection.getPhase()).handle(serverConnection,serverConnection.getPlayer(),packet); return true; - } else { - return original.handle(packet); } + return original.handle(packet); } @Override public boolean handle(ServerLoginSuccess packet) { - phase.handleSuccess(serverConnection,server); + if ((serverConnection.getPlayer().getPhase() instanceof VelocityForgeClientConnectionPhase phase)) { + phase.complete(server,serverConnection.getPlayer(),serverConnection.getPlayer().getConnection()); + } return original.handle(packet); } diff --git a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java index 6f539fb..939f474 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java @@ -18,33 +18,24 @@ public class VelocityForgeBackendConnectionPhase implements BackendConnectionPha public VelocityForgeBackendConnectionPhase() { } - public void handleSuccess(VelocityServerConnection serverCon, VelocityServer server) { - VelocityForgeClientConnectionPhase clientPhase = ((VelocityForgeClientConnectionPhase) serverCon.getPlayer().getPhase()); - if (clientPhase.clientPhase == VelocityForgeClientConnectionPhase.ClientPhase.HANDSHAKE - || clientPhase.clientPhase == VelocityForgeClientConnectionPhase.ClientPhase.MODLIST) - clientPhase.complete((VelocityServer) server,serverCon.getPlayer(),serverCon.getPlayer().getConnection()); - } + public void handle(VelocityServerConnection server, ConnectedPlayer player, LoginPluginMessage message) { + VelocityForgeClientConnectionPhase clientPhase = ((VelocityForgeClientConnectionPhase) player.getPhase()); + if (clientPhase.clientPhase == VelocityForgeClientConnectionPhase.ClientPhase.VANILLA) { + final LoginPluginMessage msg = message; - public boolean handle(VelocityServerConnection server, ConnectedPlayer player, LoginPluginMessage message) { - if (message.getChannel().equals("fml:loginwrapper")) { - VelocityForgeClientConnectionPhase clientPhase = ((VelocityForgeClientConnectionPhase) player.getPhase()); - if (clientPhase.clientPhase == VelocityForgeClientConnectionPhase.ClientPhase.VANILLA) { - message.retain(); - clientPhase.reset(server,player).thenAccept((success) -> { - if (success) { - clientPhase.forwardPayload(server,message); - } else { - message.release(); - } - }); - } else { - clientPhase.forwardPayload(server, (LoginPluginMessage) message.retain()); - } - return true; + msg.content().retain().discardSomeReadBytes(); + + server.getConnection().getChannel().config().setAutoRead(false); + clientPhase.reset(server.getServer(),player).thenAccept((success) -> { + if (success) { + clientPhase.forwardPayload(server,msg); + server.getConnection().getChannel().config().setAutoRead(true); + } else { + msg.release(); + } + }); } else { - return false; + clientPhase.forwardPayload(server, (LoginPluginMessage) message.retain()); } } - - } diff --git a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java index 0219a6f..06328bd 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java @@ -16,68 +16,24 @@ import org.adde0109.ambassador.forge.ForgeFMLConnectionType; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.jetbrains.annotations.NotNull; -public class VelocityForgeBackendHandshakeHandler extends ChannelDuplexHandler { +public class VelocityForgeBackendHandshakeHandler extends ChannelInboundHandlerAdapter { - private VelocityServerConnection serverConnection; private final VelocityServer server; public VelocityForgeBackendHandshakeHandler(VelocityServer server) { this.server = server; } - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - if (serverConnection == null) { - return; - } - VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) serverConnection.getPlayer().getPhase(); - if (clientPhase.clientPhase == VelocityForgeClientConnectionPhase.ClientPhase.MODDED) { - clientPhase.reset(serverConnection ,serverConnection.getPlayer()).thenAccept(ignored -> ctx.flush()); - } else { - ctx.flush(); - } - } - @Override public void channelActive(@NotNull ChannelHandlerContext ctx) throws Exception { - this.serverConnection.getConnection().setSessionHandler(new ForgeHandshakeSessionHandler((LoginSessionHandler) this.serverConnection.getConnection().getSessionHandler(),serverConnection,server)); + MinecraftConnection connection = (MinecraftConnection) ctx.pipeline().get(Connections.HANDLER); + VelocityServerConnection serverConnection = (VelocityServerConnection) connection.getAssociation(); + + if (serverConnection.getPlayer().getConnection().getType() instanceof ForgeFMLConnectionType) { + connection.setSessionHandler(new ForgeHandshakeSessionHandler((LoginSessionHandler) connection.getSessionHandler(),serverConnection,server)); + } + ctx.pipeline().remove(this); ctx.pipeline().fireChannelActive(); } - - private void initBackend(MinecraftConnection connection, VelocityServerConnection serverConnection, ForgeFMLConnectionType type) { - this.serverConnection = serverConnection; - connection.setType(type); - serverConnection.setConnectionPhase(connection.getType().getInitialBackendPhase()); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - if (!(msg instanceof Handshake handshake)){ - ctx.write(msg, promise); - return; - } - ChannelHandler handler = ctx.pipeline().get(Connections.HANDLER); - if (handler instanceof MinecraftConnection connection) { - if (connection.getAssociation() instanceof VelocityServerConnection serverConnection) { - if (serverConnection.getPlayer().getConnection().getType() instanceof ForgeFMLConnectionType type) { - initBackend(connection,serverConnection,type); - if (server.getConfiguration().getPlayerInfoForwardingMode() != PlayerInfoForwarding.LEGACY) { - if (type == ForgeConstants.ForgeFML2) { - handshake.setServerAddress(handshake.getServerAddress() + ForgeConstants.FML2Marker); - } else if (type == ForgeConstants.ForgeFML3) { - handshake.setServerAddress(handshake.getServerAddress() + ForgeConstants.FML3Marker); - } - } - } else { - ctx.pipeline().remove(this); - } - } else { - throw new Exception("Connection not associated with a server connection"); - } - } else { - throw new Exception("Default minecraft packet handler not found"); - } - ctx.write(msg,promise); - } }