From 4a07819c7d650d58ca5b95d307bab5c46ac706b5 Mon Sep 17 00:00:00 2001 From: Adrian Bergqvist Date: Sun, 18 Sep 2022 17:21:14 +0200 Subject: [PATCH] WIP: Backend handler --- .../org/adde0109/ambassador/Ambassador.java | 4 +- .../forge/ForgeFML2ClientConnectionPhase.java | 41 ++++++++++-------- ...Type.java => ForgeFML2ConnectionType.java} | 13 ++---- .../forge/ForgeHandshakeHandler.java | 9 ++-- .../ambassador/forge/ForgeHandshakeUtils.java | 8 +++- .../forge/ForgeServerSwitchHandler.java | 4 +- .../velocity/VelocityEventHandler.java | 30 ++++++++++++- .../VelocityForgeClientConnectionPhase.java | 6 ++- .../VelocityForgeHandshakeSessionHandler.java | 32 +++++++++----- .../VelocityHandshakeSessionHandler.java | 6 +-- ... => VelocityServerChannelInitializer.java} | 4 +- .../VelocityForgeBackendConnectionPhase.java | 14 ++++++ ...tyForgeBackendHandshakeSessionHandler.java | 43 +++++++++++++++++++ 13 files changed, 158 insertions(+), 56 deletions(-) rename src/main/java/org/adde0109/ambassador/forge/{ForgeConnectionType.java => ForgeFML2ConnectionType.java} (67%) rename src/main/java/org/adde0109/ambassador/velocity/{VelocityChannelInitializer.java => VelocityServerChannelInitializer.java} (89%) create mode 100644 src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java create mode 100644 src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeSessionHandler.java diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index 03624a4..b7d0c66 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -20,7 +20,7 @@ import org.adde0109.ambassador.forge.ForgeConnection; import org.adde0109.ambassador.forge.ForgeHandshakeHandler; import org.adde0109.ambassador.forge.ForgeHandshakeUtils; import org.adde0109.ambassador.forge.ForgeServerSwitchHandler; -import org.adde0109.ambassador.velocity.VelocityChannelInitializer; +import org.adde0109.ambassador.velocity.VelocityServerChannelInitializer; import org.adde0109.ambassador.velocity.VelocityEventHandler; import org.bstats.charts.SingleLineChart; import org.bstats.velocity.Metrics; @@ -73,7 +73,7 @@ public class Ambassador { Field cmField = VelocityServer.class.getDeclaredField("cm"); cmField.setAccessible(true); ChannelInitializer original = ((ConnectionManager) cmField.get(server)).serverChannelInitializer.get(); - ((ConnectionManager) cmField.get(server)).serverChannelInitializer.set(new VelocityChannelInitializer(original)); + ((ConnectionManager) cmField.get(server)).serverChannelInitializer.set(new VelocityServerChannelInitializer(original)); } @Subscribe diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java index 137eddb..d608877 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java @@ -12,50 +12,53 @@ import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.adde0109.ambassador.velocity.VelocityForgeHandshakeSessionHandler; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.Optional; public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnectionPhase { - - private final MinecraftConnection connection; private boolean isResettable; private Optional modListData = Optional.empty(); + + private final ArrayList listenerList = new ArrayList(); private Continuation whenComplete; - ForgeFML2ClientConnectionPhase(MinecraftConnection connection) { - this.connection = connection; - } @Override - public void handleLogin(ForgeHandshakeUtils.CachedServerHandshake handshake, Continuation continuation) { + public void handleLogin(ConnectedPlayer player,ForgeHandshakeUtils.CachedServerHandshake handshake, Continuation continuation) { this.whenComplete = continuation; - VelocityForgeHandshakeSessionHandler sessionHandler = new VelocityForgeHandshakeSessionHandler(this); + final MinecraftConnection connection = player.getConnection(); + VelocityForgeHandshakeSessionHandler sessionHandler = new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),player); if(handshake == null) { - this.connection.write(new LoginPluginMessage(98,"fml:loginwrapper", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateResetPacket()))); - sessionHandler.listen(98); + connection.delayedWrite(new LoginPluginMessage(98,"fml:loginwrapper", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateResetPacket()))); + listenerList.add(98); } else { - this.connection.delayedWrite(new LoginPluginMessage(1,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.modListPacket))); - sessionHandler.listen(1); + connection.delayedWrite(new LoginPluginMessage(1,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.modListPacket))); + listenerList.add(1); for (int i = 0;i id.equals(packet.getId()))) { + return false; + } if (packet.getId() == 98) { isResettable = packet.isSuccess(); } else if (packet.getId() == 1) { if (!packet.isSuccess()) { //TODO: Write disconnect message to end user - connection.close(); - return; + player.getConnection().close(); + return true; } modListData = Optional.of(packet.content().retain()); } - if (lastMessage) { + if (listenerList.isEmpty()) { whenComplete.resume(); } + return true; } } diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeConnectionType.java b/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ConnectionType.java similarity index 67% rename from src/main/java/org/adde0109/ambassador/forge/ForgeConnectionType.java rename to src/main/java/org/adde0109/ambassador/forge/ForgeFML2ConnectionType.java index 8ce8e9b..a1ae5d3 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeConnectionType.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ConnectionType.java @@ -6,23 +6,18 @@ import com.velocitypowered.proxy.connection.ConnectionType; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.backend.BackendConnectionPhase; import com.velocitypowered.proxy.connection.client.ClientConnectionPhase; -import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase; +import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendConnectionPhase; -public class ForgeConnectionType implements ConnectionType { - - private final MinecraftConnection connection; - public ForgeConnectionType(MinecraftConnection connection) { - this.connection = connection; - } +public class ForgeFML2ConnectionType implements ConnectionType { @Override public ClientConnectionPhase getInitialClientPhase() { - return new ForgeFML2ClientConnectionPhase(connection); + return new ForgeFML2ClientConnectionPhase(); } @Override public BackendConnectionPhase getInitialBackendPhase() { - return null; + return new VelocityForgeBackendConnectionPhase(); } @Override diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeHandler.java b/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeHandler.java index 8da119e..1019aee 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeHandler.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeHandler.java @@ -19,6 +19,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.format.NamedTextColor; import org.adde0109.ambassador.Ambassador; +import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; public class ForgeHandshakeHandler { @@ -37,12 +38,12 @@ public class ForgeHandshakeHandler { - public void handleLogin(ConnectedPlayer player, ForgeFML2ClientConnectionPhase phase, Continuation continuation) { + public void handleLogin(ConnectedPlayer player, Continuation continuation) { getInitialHandshake(player).whenCompleteAsync((msg,ex) -> { if (ex != null) { ambassador.logger.warn("Forge player, " + player.getUsername() + ", is entering vanilla-mode because of: " + ex.getMessage()); } - phase.handleLogin(msg,continuation); + ((VelocityForgeClientConnectionPhase) player.getPhase()).handleLogin(player,msg,continuation); }, player.getConnection().eventLoop()); } @@ -88,7 +89,7 @@ public class ForgeHandshakeHandler { forgeServerConnectionMap.remove(server); } - @Subscribe + //@Subscribe public void onServerLoginPluginMessageEvent(ServerLoginPluginMessageEvent event, Continuation continuation) { if (!event.getIdentifier().equals(LOGIN_WRAPPER_ID)) { continuation.resume(); @@ -110,7 +111,7 @@ public class ForgeHandshakeHandler { } } - @Subscribe + //@Subscribe public void onKickedFromServerEvent(KickedFromServerEvent event, Continuation continuation) { Optional forgeConnectionOptional = getForgeConnection(event.getPlayer()); if (forgeConnectionOptional.isPresent()) { diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeUtils.java b/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeUtils.java index 1500e75..66a167b 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeUtils.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeUtils.java @@ -65,7 +65,13 @@ public class ForgeHandshakeUtils { public static byte[] generateResetPacket() { ByteArrayDataOutput dataAndPacketIdStream = ByteStreams.newDataOutput(); writeVarInt(dataAndPacketIdStream,98); - return dataAndPacketIdStream.toByteArray(); + + ByteArrayDataOutput stream = ByteStreams.newDataOutput(); + byte[] dataAndPacketId = dataAndPacketIdStream.toByteArray(); + writeUtf(stream,"fml:handshake"); + writeVarInt(stream,dataAndPacketId.length); + stream.write(dataAndPacketId); + return stream.toByteArray(); } public static class HandshakeReceiver { diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeServerSwitchHandler.java b/src/main/java/org/adde0109/ambassador/forge/ForgeServerSwitchHandler.java index e699ebe..06c788a 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeServerSwitchHandler.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeServerSwitchHandler.java @@ -53,7 +53,7 @@ public class ForgeServerSwitchHandler { } - @Subscribe(order = PostOrder.LAST) + //@Subscribe(order = PostOrder.LAST) public void onServerPreConnectEvent(ServerPreConnectEvent event, Continuation continuation) { if (!event.getResult().isAllowed()) { continuation.resume(); @@ -111,7 +111,7 @@ public class ForgeServerSwitchHandler { reSyncMap.put(player.getUsername(),forgeServerConnection); } - @Subscribe + //@Subscribe public void onServerConnectedEvent(ServerConnectedEvent event, Continuation continuation) { ConnectedPlayer player = ((ConnectedPlayer) event.getPlayer()); Optional forgeConnection = ambassador.forgeHandshakeHandler.getForgeConnection(player); diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java index 33d5758..647e732 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java @@ -3,9 +3,19 @@ package org.adde0109.ambassador.velocity; import com.velocitypowered.api.event.Continuation; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.permission.PermissionsSetupEvent; +import com.velocitypowered.api.event.player.ServerLoginPluginMessageEvent; +import com.velocitypowered.proxy.connection.ConnectionTypes; +import com.velocitypowered.proxy.connection.MinecraftConnection; +import com.velocitypowered.proxy.connection.backend.BackendConnectionPhases; +import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import org.adde0109.ambassador.Ambassador; import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase; +import org.adde0109.ambassador.forge.ForgeFML2ConnectionType; +import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendConnectionPhase; +import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendHandshakeSessionHandler; + +import java.util.Objects; public class VelocityEventHandler { @@ -21,10 +31,26 @@ public class VelocityEventHandler { continuation.resume(); return; } - if (!(player.getPhase() instanceof ForgeFML2ClientConnectionPhase phase)) { + if (!(player.getPhase() instanceof VelocityForgeClientConnectionPhase phase)) { continuation.resume(); return; } - ambassador.forgeHandshakeHandler.handleLogin(player,phase,continuation); + ambassador.forgeHandshakeHandler.handleLogin(player,continuation); + } + + @Subscribe + public void onServerLoginPluginMessageEvent(ServerLoginPluginMessageEvent event, Continuation continuation) { + if (!Objects.equals(event.getIdentifier().getId(), "fml:loginwrapper")) { + continuation.resume(); + return; + } + final VelocityServerConnection serverCon = (VelocityServerConnection) event.getConnection(); + final MinecraftConnection connection = serverCon.getConnection(); + serverCon.setConnectionPhase(new VelocityForgeBackendConnectionPhase()); + if (connection != null) { + connection.setType(new ForgeFML2ConnectionType()); + connection.setSessionHandler(new VelocityForgeBackendHandshakeSessionHandler(connection.getSessionHandler(),serverCon,serverCon.getPlayer())); + } + continuation.resume(); } } diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java index 53cf8c5..8b06309 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java @@ -3,6 +3,7 @@ package org.adde0109.ambassador.velocity; import com.velocitypowered.api.event.Continuation; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.client.ClientConnectionPhase; +import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse; import org.adde0109.ambassador.forge.ForgeHandshakeUtils; @@ -11,8 +12,9 @@ import javax.annotation.Nullable; public interface VelocityForgeClientConnectionPhase extends ClientConnectionPhase { //TODO:Make class when PCF is done - default void handleLogin(@Nullable ForgeHandshakeUtils.CachedServerHandshake initialHandshake, Continuation continuation) { + default void handleLogin(ConnectedPlayer player, @Nullable ForgeHandshakeUtils.CachedServerHandshake initialHandshake, Continuation continuation) { } - default void handle(LoginPluginResponse packet, boolean lastMessage) { + default boolean handle(ConnectedPlayer player,LoginPluginResponse packet) { + return false; } } diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeHandshakeSessionHandler.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeHandshakeSessionHandler.java index 10191ee..6cb5242 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeHandshakeSessionHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeHandshakeSessionHandler.java @@ -1,28 +1,40 @@ package org.adde0109.ambassador.velocity; +import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.connection.client.LoginSessionHandler; +import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse; +import io.netty.buffer.ByteBuf; +import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase; import java.util.ArrayList; import java.util.List; public class VelocityForgeHandshakeSessionHandler implements MinecraftSessionHandler { - - private final ArrayList listenerList = new ArrayList(); - private final VelocityForgeClientConnectionPhase phase; - public VelocityForgeHandshakeSessionHandler(VelocityForgeClientConnectionPhase phase) { - this.phase = phase; + private final MinecraftSessionHandler original; + private final ConnectedPlayer player; + public VelocityForgeHandshakeSessionHandler(MinecraftSessionHandler original, ConnectedPlayer player) { + this.original = original; + this.player = player; } @Override public boolean handle(LoginPluginResponse packet) { - if (listenerList.removeIf(id -> id.equals(packet.getId()))) { - phase.handle(packet, listenerList.isEmpty()); + if (((VelocityForgeClientConnectionPhase) player.getPhase()).handle(player, packet)) { return true; + } else { + return original.handle(packet); } - return false; } - public void listen(int id) { - listenerList.add(id); + @Override + public void handleUnknown(ByteBuf buf) { + original.handleUnknown(buf); + } + + @Override + public void disconnected() { + original.disconnected(); } } diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityHandshakeSessionHandler.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityHandshakeSessionHandler.java index c262df0..5a73205 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityHandshakeSessionHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityHandshakeSessionHandler.java @@ -8,7 +8,7 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.packet.Handshake; import io.netty.buffer.ByteBuf; -import org.adde0109.ambassador.forge.ForgeConnectionType; +import org.adde0109.ambassador.forge.ForgeFML2ConnectionType; public class VelocityHandshakeSessionHandler implements MinecraftSessionHandler { private final HandshakeSessionHandler original; @@ -24,7 +24,7 @@ public class VelocityHandshakeSessionHandler implements MinecraftSessionHandler handshake.handle(original); if (connection.getType() == ConnectionTypes.VANILLA && connection.getState() == StateRegistry.LOGIN) { if (handshake.getServerAddress().split("\0")[1].equals("FML2")) { - connection.setType(new ForgeConnectionType(connection)); + connection.setType(new ForgeFML2ConnectionType()); } } return true; @@ -33,7 +33,7 @@ public class VelocityHandshakeSessionHandler implements MinecraftSessionHandler @Override public void handleGeneric(MinecraftPacket packet) { - packet.handle(original); + original.handleGeneric(packet); } @Override diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityChannelInitializer.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityServerChannelInitializer.java similarity index 89% rename from src/main/java/org/adde0109/ambassador/velocity/VelocityChannelInitializer.java rename to src/main/java/org/adde0109/ambassador/velocity/VelocityServerChannelInitializer.java index 05b5a3b..95699ac 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityChannelInitializer.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityServerChannelInitializer.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; import java.lang.reflect.Method; -public class VelocityChannelInitializer extends ChannelInitializer { +public class VelocityServerChannelInitializer extends ChannelInitializer { private static final Method INIT_CHANNEL; private final ChannelInitializer original; @@ -24,7 +24,7 @@ public class VelocityChannelInitializer extends ChannelInitializer { } } - public VelocityChannelInitializer(ChannelInitializer original) { + public VelocityServerChannelInitializer(ChannelInitializer original) { this.original = original; } diff --git a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java new file mode 100644 index 0000000..96b6937 --- /dev/null +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java @@ -0,0 +1,14 @@ +package org.adde0109.ambassador.velocity.backend; + +import com.velocitypowered.proxy.connection.backend.BackendConnectionPhase; +import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; +import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; +import com.velocitypowered.proxy.protocol.packet.PluginMessage; + +public class VelocityForgeBackendConnectionPhase implements BackendConnectionPhase { + + public boolean handle(VelocityServerConnection server, ConnectedPlayer player, LoginPluginMessage message) { + return true; + } +} diff --git a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeSessionHandler.java b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeSessionHandler.java new file mode 100644 index 0000000..019583f --- /dev/null +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeSessionHandler.java @@ -0,0 +1,43 @@ +package org.adde0109.ambassador.velocity.backend; + +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; +import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; +import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; +import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; + +public class VelocityForgeBackendHandshakeSessionHandler implements MinecraftSessionHandler { + private final MinecraftSessionHandler original; + private final VelocityServerConnection serverCon; + + public VelocityForgeBackendHandshakeSessionHandler(MinecraftSessionHandler original, VelocityServerConnection serverCon) { + this.original = original; + this.serverCon = serverCon; + } + + @Override + public void disconnected() { + original.disconnected(); + } + + @Override + public void exception(Throwable throwable) { + original.exception(throwable); + } + + @Override + public boolean handle(LoginPluginMessage packet) { + if (((VelocityForgeBackendConnectionPhase) serverCon.getPhase()).handle(serverCon, serverCon.getPlayer(), packet)) { + return true; + } else { + return original.handle(packet); + } + } + + @Override + public boolean handle(ServerLoginSuccess packet) { + + return original.handle(packet); + } +}