From cd952139bcc7a32872c5ddaa11698e82d94fbf3c Mon Sep 17 00:00:00 2001 From: Adrian Bergqvist Date: Wed, 24 Aug 2022 22:37:25 +0200 Subject: [PATCH] refined reset packet handler --- .../ambassador/forge/ForgeConnection.java | 20 +++++++- .../forge/ForgeHandshakeHandler.java | 1 - .../forge/ForgeServerSwitchHandler.java | 51 +++++++++++-------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeConnection.java b/src/main/java/org/adde0109/ambassador/forge/ForgeConnection.java index 6f2836d..c0af214 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeConnection.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeConnection.java @@ -6,9 +6,13 @@ import com.velocitypowered.api.event.player.ServerLoginPluginMessageEvent; import com.velocitypowered.api.proxy.LoginPhaseConnection; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import com.velocitypowered.api.proxy.server.RegisteredServer; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import org.slf4j.Logger; import java.io.EOFException; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -26,6 +30,7 @@ public class ForgeConnection { private boolean forced = false; private Optional syncedTo = Optional.empty(); + private boolean resettable; public ForgeConnection(LoginPhaseConnection connection, Logger logger) { this.connection = connection; @@ -59,7 +64,16 @@ public class ForgeConnection { if (!ignoreSyncExepction && response == null) { logger.warn("Sync Exception: Client responded with an empty body."); } - recivedClientModlist = Optional.ofNullable(response); + if (response != null) { + recivedClientModlist = Optional.of(response); + //If the client is resettable. + ByteBuf clientModListPacket = Unpooled.wrappedBuffer(response); + clientModListPacket.readBytes(14); //Channel Identifier + ProtocolUtils.readVarInt(clientModListPacket); //Length + int packetID = ProtocolUtils.readVarInt(clientModListPacket); + String[] mods = ProtocolUtils.readStringArray(clientModListPacket); + resettable = Arrays.stream(mods).anyMatch((s) -> s.equals("clientresetpacket")); + } }); //This gets also sent to vanilla sendOther(msg.otherPackets).thenAccept((response) -> { @@ -126,6 +140,10 @@ public class ForgeConnection { return connection; } + public boolean isResettable() { + return resettable; + } + public Optional getTransmittedHandshake() { return transmittedHandshake; } diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeHandler.java b/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeHandler.java index 6e2b94e..18eddc4 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeHandler.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeHandler.java @@ -19,7 +19,6 @@ 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.bstats.velocity.Metrics; public class ForgeHandshakeHandler { diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeServerSwitchHandler.java b/src/main/java/org/adde0109/ambassador/forge/ForgeServerSwitchHandler.java index 417ccb4..5f19677 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeServerSwitchHandler.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeServerSwitchHandler.java @@ -31,6 +31,7 @@ import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse; import com.velocitypowered.proxy.protocol.packet.PluginMessage; import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; +import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.EventLoop; @@ -59,10 +60,10 @@ public class ForgeServerSwitchHandler { return; } Optional forgeServerConnectionOptional = ambassador.forgeHandshakeHandler.getForgeServerConnection(event.getOriginalServer()); - Optional forgeConnection = ambassador.forgeHandshakeHandler.getForgeConnection(event.getPlayer()); - if (forgeConnection.isPresent()) { - //TODO: If the client can resync without kick, we don't need to check the server. - if (true) { + Optional forgeConnectionOptional = ambassador.forgeHandshakeHandler.getForgeConnection(event.getPlayer()); + if (forgeConnectionOptional.isPresent()) { + ForgeConnection forgeConnection = forgeConnectionOptional.get(); + if (forgeConnection.isResettable()) { continuation.resume(); return; } @@ -86,7 +87,7 @@ public class ForgeServerSwitchHandler { event.getPlayer().setGameProfileProperties(properties); if (ambassador.config.reSyncOptionForge() != AmbassadorConfig.reSyncOption.NEVER) { - if (forgeConnection.get().getTransmittedHandshake().isEmpty() || !msg.equals(forgeConnection.get().getTransmittedHandshake().get())) { + if (forgeConnection.getTransmittedHandshake().isEmpty() || !msg.equals(forgeConnection.getTransmittedHandshake().get())) { event.setResult(ServerPreConnectEvent.ServerResult.denied()); kickReSync(event.getPlayer(), forgeServerConnection); } @@ -113,9 +114,14 @@ public class ForgeServerSwitchHandler { @Subscribe public void onServerConnectedEvent(ServerConnectedEvent event, Continuation continuation) { ConnectedPlayer player = ((ConnectedPlayer) event.getPlayer()); - Optional forgeServerConnection = ambassador.forgeHandshakeHandler.getForgeServerConnection(event.getServer()); Optional forgeConnection = ambassador.forgeHandshakeHandler.getForgeConnection(player); - if (forgeConnection.isPresent() && forgeServerConnection.isPresent() && event.getPreviousServer().isPresent()) { + if (forgeConnection.isEmpty() || !forgeConnection.get().isResettable()) { + //Don't bother unless the client can be reset. + continuation.resume(); + return; + } + Optional forgeServerConnection = ambassador.forgeHandshakeHandler.getForgeServerConnection(event.getServer()); + if (forgeServerConnection.isPresent() && event.getPreviousServer().isPresent()) { Future handshakeFuture = forgeServerConnection.get().getHandshake(); player.getConnection().eventLoop().submit(() -> { reSync(player,handshakeFuture,continuation); @@ -140,7 +146,8 @@ public class ForgeServerSwitchHandler { private final Future handshakeFuture; private final MinecraftSessionHandler originalHandler; private final Continuation continuation; - private int sent = 0; + + private List inTransit = new ArrayList<>(); ReSyncHandler(ConnectedPlayer player, Future handshakeFuture, Continuation continuation) { this.player = player; @@ -152,32 +159,34 @@ public class ForgeServerSwitchHandler { @Override public boolean handle(LoginPluginResponse packet) { - if (sent == 0) { - ForgeHandshakeUtils.CachedServerHandshake handshake; - try { - handshake = handshakeFuture.get(); - } catch (Exception e) { + if (!inTransit.removeIf((s) -> s==packet.getId())) { + if (packet.getId() == 98) { + ForgeHandshakeUtils.CachedServerHandshake handshake; + try { + handshake = handshakeFuture.get(); + } catch (Exception e) { + return true; + } + sendHandshake(connection, handshake); return true; } - sent = sendHandshake(connection, handshake); - } else { - if (sent == 1) { - complete(); - } - sent--; + return false; + } else if (inTransit.isEmpty()) { + complete(); } return true; } - private int sendHandshake(MinecraftConnection connection, ForgeHandshakeUtils.CachedServerHandshake handshake) { + private void sendHandshake(MinecraftConnection connection, ForgeHandshakeUtils.CachedServerHandshake handshake) { int transactionId = 1; connection.delayedWrite(new LoginPluginMessage(transactionId, "fml:loginwrapper", Unpooled.wrappedBuffer(handshake.modListPacket))); + inTransit.add(transactionId); for (byte[] data : handshake.otherPackets) { transactionId++; connection.delayedWrite(new LoginPluginMessage(transactionId, "fml:loginwrapper", Unpooled.wrappedBuffer(data))); + inTransit.add(transactionId); } connection.flush(); - return transactionId; } private void complete() { VelocityConfiguration configuration = (VelocityConfiguration) ambassador.server.getConfiguration();