diff --git a/build.gradle b/build.gradle index 77e1dbc..4b0d2e7 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'org.adde0109' -version '1.0.7-alpha' +version '1.0.9-alpha' repositories { maven { diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index 3a506b0..b4111e7 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -22,7 +22,7 @@ import org.slf4j.Logger; import java.nio.file.Path; -@Plugin(id = "ambassador", name = "Ambassador", version = "1.0.7-alpha", authors = {"adde0109"}) +@Plugin(id = "ambassador", name = "Ambassador", version = "1.0.9-alpha", authors = {"adde0109"}) public class Ambassador { public ProxyServer server; diff --git a/src/main/java/org/adde0109/ambassador/forge/FML2CRPMClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/FML2CRPMClientConnectionPhase.java index 1548b87..4f24937 100644 --- a/src/main/java/org/adde0109/ambassador/forge/FML2CRPMClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/FML2CRPMClientConnectionPhase.java @@ -20,6 +20,7 @@ import org.adde0109.ambassador.velocity.VelocityLoginPayloadManager; import java.util.NoSuchElementException; import java.util.UUID; +import java.util.concurrent.CompletableFuture; public class FML2CRPMClientConnectionPhase extends VelocityForgeClientConnectionPhase { private static String OUTBOUND_CATCHER_NAME = "ambassador-catcher"; @@ -34,7 +35,8 @@ public class FML2CRPMClientConnectionPhase extends VelocityForgeClientConnection public FML2CRPMClientConnectionPhase() { } - public void reset(VelocityServerConnection serverConnection, ConnectedPlayer player, Runnable whenComplete) { + public CompletableFuture reset(VelocityServerConnection serverConnection, ConnectedPlayer player) { + CompletableFuture future = new CompletableFuture<>(); if (player.getConnectedServer() != null) { backupServer = player.getConnectedServer().getServer(); player.getConnectedServer().disconnect(); @@ -53,16 +55,15 @@ public class FML2CRPMClientConnectionPhase extends VelocityForgeClientConnection } getPayloadManager().listenFor(98).thenAccept((response) -> { this.clientPhase = ClientPhase.HANDSHAKE; - whenComplete.run(); + future.complete(true); }); this.clientPhase = null; connection.getChannel().pipeline().addBefore(Connections.HANDLER,OUTBOUND_CATCHER_NAME,new FML2CRPMConnectionHandler(() -> { - connection.setState(StateRegistry.PLAY); - final FML2ClientConnectionPhase newPhase = new FML2ClientConnectionPhase(ClientPhase.HANDSHAKE,getPayloadManager()); - player.setPhase(newPhase); - newPhase.reset(serverConnection,player,whenComplete); + player.getConnection().setState(StateRegistry.PLAY); + future.complete(false); })); + return future; } public void complete(VelocityServer server, ConnectedPlayer player, MinecraftConnection connection) { VelocityConfiguration configuration = (VelocityConfiguration) server.getConfiguration(); diff --git a/src/main/java/org/adde0109/ambassador/forge/FML2CRPMConnectionHandler.java b/src/main/java/org/adde0109/ambassador/forge/FML2CRPMConnectionHandler.java index 8b7729c..96e7913 100644 --- a/src/main/java/org/adde0109/ambassador/forge/FML2CRPMConnectionHandler.java +++ b/src/main/java/org/adde0109/ambassador/forge/FML2CRPMConnectionHandler.java @@ -6,6 +6,7 @@ import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.util.ReferenceCountUtil; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -23,12 +24,20 @@ public class FML2CRPMConnectionHandler extends ChannelDuplexHandler { public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { final Set> s = catchedPackets.entrySet(); Iterator> i = s.iterator(); - while (catchedPackets.entrySet().iterator().hasNext()) { - final Map.Entry entry = i.next(); - ctx.write(entry.getValue(),entry.getKey()); - i.remove(); + 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(); } - ctx.flush(); } @Override diff --git a/src/main/java/org/adde0109/ambassador/forge/FML2ClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/FML2ClientConnectionPhase.java index e71c3ac..cd940f4 100644 --- a/src/main/java/org/adde0109/ambassador/forge/FML2ClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/FML2ClientConnectionPhase.java @@ -11,6 +11,7 @@ import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; import io.netty.buffer.ByteBuf; +import io.netty.util.ReferenceCountUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; @@ -19,6 +20,7 @@ import org.apache.commons.collections4.map.PassiveExpiringMap; import java.util.Arrays; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class FML2ClientConnectionPhase extends VelocityForgeClientConnectionPhase { @@ -31,13 +33,6 @@ public class FML2ClientConnectionPhase extends VelocityForgeClientConnectionPhas private RegisteredServer triedServer; private Continuation continuation; - public FML2ClientConnectionPhase(VelocityForgeClientConnectionPhase.ClientPhase clientPhase, VelocityLoginPayloadManager payloadManager) { - super(clientPhase,payloadManager); - } - public FML2ClientConnectionPhase(){ - super(); - } - @Override public void handleLogin(ConnectedPlayer player, VelocityServer server, Continuation continuation) { @@ -60,9 +55,17 @@ public class FML2ClientConnectionPhase extends VelocityForgeClientConnectionPhas } @Override - public void reset(VelocityServerConnection serverConnection, ConnectedPlayer player, Runnable whenComplete) { - TEMPORARY_FORCED.put(player.getUsername(),serverConnection.getServer()); - player.disconnect(Component.text("Please reconnect")); + public CompletableFuture reset(VelocityServerConnection serverConnection, ConnectedPlayer player) { + FML2CRPMClientConnectionPhase newPhase = new FML2CRPMClientConnectionPhase(clientPhase,getPayloadManager()); + player.setPhase(newPhase); + CompletableFuture future = newPhase.reset(serverConnection,player); + future.thenAccept(success -> { + if (!success) { + TEMPORARY_FORCED.put(player.getUsername(),serverConnection.getServer()); + player.disconnect(Component.text("Please reconnect")); + } + }); + return future; } @Override @@ -70,9 +73,7 @@ public class FML2ClientConnectionPhase extends VelocityForgeClientConnectionPhas if (triedServer != null) player.sendMessage(Component.translatable("velocity.error.connecting-server-error", Component.text(triedServer.getServerInfo().getName()))); - if (clientPhase == ClientPhase.VANILLA) { - player.setPhase(new FML2CRPMClientConnectionPhase(ClientPhase.VANILLA,getPayloadManager())); - } else if (clientPhase == ClientPhase.MODLIST) { + if (clientPhase == ClientPhase.MODLIST) { clientPhase = ClientPhase.MODDED; internalServerConnection = player.getConnectionInFlight(); player.resetInFlightConnection(); @@ -99,21 +100,28 @@ public class FML2ClientConnectionPhase extends VelocityForgeClientConnectionPhas @Override - public void forwardPayload(VelocityServerConnection serverConnection, LoginPluginMessage payload) { + public void handleForward(VelocityServerConnection serverConnection, LoginPluginMessage payload) { ByteBuf buf = payload.content().copy(); - String channel = ProtocolUtils.readString(buf); - int length = ProtocolUtils.readVarInt(buf); - int id = ProtocolUtils.readVarInt(buf); - if (id == 1) { - String[] mods = ProtocolUtils.readStringArray(buf); - - if (Arrays.stream(mods).anyMatch(s -> s.equals("clientresetpacket"))) { - serverConnection.getPlayer().setPhase(new FML2CRPMClientConnectionPhase(ClientPhase.VANILLA,getPayloadManager())); - } + ProtocolUtils.readString(buf); //Channel + ProtocolUtils.readVarInt(buf); //Length + if (ProtocolUtils.readVarInt(buf) == 1) { + getPayloadManager().listenFor(payload.getId()).thenAccept(rawResponse -> { + ByteBuf response = rawResponse.copy(); + ProtocolUtils.readString(response); //Channel + ProtocolUtils.readVarInt(response); //Length + if (ProtocolUtils.readVarInt(response) == 2) { + String[] mods = ProtocolUtils.readStringArray(response); + if (Arrays.stream(mods).anyMatch(s -> s.equals("clientresetpacket"))) { + serverConnection.getPlayer().setPhase(new FML2CRPMClientConnectionPhase(clientPhase,getPayloadManager())); + } + } + ReferenceCountUtil.release(response); + }); + ReferenceCountUtil.release(buf); } - super.forwardPayload(serverConnection, payload); } + private void handlePingResponse(ConnectedPlayer player, RegisteredServer server, ServerPing ping) { if (ping.getModinfo().isEmpty()) { clientPhase = ClientPhase.VANILLA; diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java index 1057567..6220181 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityForgeClientConnectionPhase.java @@ -12,6 +12,8 @@ import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse; import org.adde0109.ambassador.forge.FML2CRPMClientConnectionPhase; +import java.util.concurrent.CompletableFuture; + public abstract class VelocityForgeClientConnectionPhase implements ClientConnectionPhase { //TODO:Make class when PCF is done @@ -27,13 +29,13 @@ public abstract class VelocityForgeClientConnectionPhase implements ClientConnec this.payloadManager = payloadManager; } protected VelocityForgeClientConnectionPhase() { - } public void handleLogin(ConnectedPlayer player, VelocityServer server, Continuation continuation) { } - public void reset(VelocityServerConnection serverConnection,ConnectedPlayer player, Runnable whenComplete) { + public CompletableFuture reset(VelocityServerConnection serverConnection, ConnectedPlayer player) { + return CompletableFuture.completedFuture(false); } public void complete(VelocityServer server, ConnectedPlayer player, MinecraftConnection connection) { @@ -48,7 +50,11 @@ public abstract class VelocityForgeClientConnectionPhase implements ClientConnec player.getConnection().setSessionHandler(sessionHandler); } - public void forwardPayload(VelocityServerConnection serverConnection, LoginPluginMessage payload) { + public void handleForward(VelocityServerConnection serverConnection, LoginPluginMessage payload) { + } + + final public void forwardPayload(VelocityServerConnection serverConnection, LoginPluginMessage payload) { + handleForward(serverConnection,payload); if (payloadManager == null) { return; } diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityLoginPayloadManager.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityLoginPayloadManager.java index 54d22eb..2fe0461 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityLoginPayloadManager.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityLoginPayloadManager.java @@ -20,10 +20,9 @@ public class VelocityLoginPayloadManager { public CompletableFuture sendPayload(String channel, ByteBuf data) { connection.write(new LoginPluginMessage(counter,channel,data)); - final CompletableFuture callback = new CompletableFuture<>(); - listenerList.put(counter, callback); + CompletableFuture future = listenFor(counter); counter++; - return callback; + return future; } public CompletableFuture sendPayloads(String channel, List dataList) { @@ -37,13 +36,14 @@ public class VelocityLoginPayloadManager { return callback; } - public CompletableFuture listenFor(int id) throws RuntimeException{ - if (!listenerList.containsValue(id)) { + public CompletableFuture listenFor(int id) { + CompletableFuture value = listenerList.get(id); + if (value == null) { CompletableFuture callback = new CompletableFuture<>(); listenerList.put(id,callback); return callback; } else { - throw new RuntimeException("Already listening for:" + id); + return value; } } 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 fa8d1e3..6e7b7ab 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java @@ -5,6 +5,7 @@ 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 io.netty.util.ReferenceCountUtil; import org.adde0109.ambassador.forge.FML2CRPMClientConnectionPhase; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; @@ -27,11 +28,17 @@ public class VelocityForgeBackendConnectionPhase implements BackendConnectionPha VelocityForgeClientConnectionPhase clientPhase = ((VelocityForgeClientConnectionPhase) player.getPhase()); message.retain(); if (clientPhase.clientPhase == VelocityForgeClientConnectionPhase.ClientPhase.VANILLA) { - clientPhase.reset(server,player, () -> { - for (LoginPluginMessage msg: queuedHandshakePackets) { - clientPhase.forwardPayload(server,msg); + clientPhase.reset(server,player).thenAccept((success) -> { + if (success) { + for (LoginPluginMessage msg: queuedHandshakePackets) { + ((VelocityForgeClientConnectionPhase) player.getPhase()).forwardPayload(server,msg); + } + player.getConnection().flush(); + } else { + for (LoginPluginMessage msg: queuedHandshakePackets) { + ReferenceCountUtil.release(msg); + } } - player.getConnection().flush(); queuedHandshakePackets = null; }); queuedHandshakePackets = new ArrayList<>(); 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 c6b978b..1dd2fc9 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java @@ -34,9 +34,7 @@ public class VelocityForgeBackendHandshakeHandler extends ChannelDuplexHandler { if (serverConnection.getPlayer().getPhase() instanceof VelocityForgeClientConnectionPhase phase) { init(connection,serverConnection); if (phase.clientPhase == VelocityForgeClientConnectionPhase.ClientPhase.MODDED) { - phase.reset(serverConnection ,serverConnection.getPlayer(), () -> { - ctx.flush(); - }); + phase.reset(serverConnection ,serverConnection.getPlayer()).thenAccept(ignored -> ctx.flush()); } else { ctx.flush(); }