diff --git a/build.gradle b/build.gradle index 12eecf7..8496662 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'org.adde0109' -version '0.4.0-reset' +version '1.0.0-alpha' repositories { maven { diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index b7d0c66..6bb9ac5 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -28,7 +28,7 @@ import org.slf4j.Logger; import java.nio.file.Path; -@Plugin(id = "ambassador", name = "Ambassador", version = "0.4.0-reset", authors = {"adde0109"}) +@Plugin(id = "ambassador", name = "Ambassador", version = "1.0.0-alpha", authors = {"adde0109"}) public class Ambassador { public ProxyServer server; diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java index df7ff8a..97c94d3 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java @@ -1,6 +1,7 @@ package org.adde0109.ambassador.forge; import com.velocitypowered.api.event.Continuation; +import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.util.UuidUtils; import com.velocitypowered.proxy.Velocity; import com.velocitypowered.proxy.VelocityServer; @@ -19,6 +20,8 @@ import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.adde0109.ambassador.velocity.VelocityForgeHandshakeSessionHandler; +import org.checkerframework.checker.units.qual.A; +import org.checkerframework.checker.units.qual.C; import javax.annotation.Nullable; import java.util.ArrayList; @@ -36,21 +39,23 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec public byte[] modListData; private final ArrayList listenerList = new ArrayList(); + public ArrayList packagesToSendAfterReset = new ArrayList<>(); private Runnable whenComplete; + public boolean isReady = false; @Override public void handleLogin(ConnectedPlayer player,ForgeHandshakeUtils.CachedServerHandshake handshake, Continuation continuation) { this.whenComplete = continuation::resume; final MinecraftConnection connection = player.getConnection(); VelocityForgeHandshakeSessionHandler sessionHandler = new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),player); if(handshake == null) { - connection.delayedWrite(new LoginPluginMessage(1,"fml:loginwrapper", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateEmptyModlist()))); - listenerList.add(1); + connection.delayedWrite(new LoginPluginMessage(0,"fml:loginwrapper", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateEmptyModlist()))); + listenerList.add(0); } else { - connection.delayedWrite(new LoginPluginMessage(1,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.modListPacket))); - listenerList.add(1); + connection.delayedWrite(new LoginPluginMessage(0,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.modListPacket))); + listenerList.add(0); for (int i = 0;i id.equals(packet.getId()))) { - return false; + player.getConnectionInFlight().getConnection().write(packet.retain()); + return true; } if (packet.getId() == 98) { - isResettable = packet.isSuccess(); - } else if (packet.getId() == 1) { + for (LoginPluginMessage packet1 : packagesToSendAfterReset) { + player.getConnection().delayedWrite(packet1); + } + packagesToSendAfterReset = new ArrayList<>(); + player.getConnection().flush(); + } else if (packet.getId() == 0) { if (!packet.isSuccess()) { //TODO: Write disconnect message to end user player.getConnection().close(); @@ -78,16 +88,23 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec } return true; } - public void reset(ConnectedPlayer player,MinecraftConnection connection, List messages, Runnable whenComplete) { - this.whenComplete = whenComplete; + public void reset(ConnectedPlayer player,MinecraftConnection connection, byte[] serverModlist) { + isReady = false; + if (player.getConnectedServer() != null) { + player.getConnectedServer().disconnect(); + } connection.setSessionHandler(new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),player)); connection.write(new PluginMessage("fml:handshake",Unpooled.wrappedBuffer(ForgeHandshakeUtils.generatePluginResetPacket()))); listenerList.add(98); + send(player,new LoginPluginMessage(0,"fml:loginwrapper",Unpooled.wrappedBuffer(serverModlist))); + listenerList.add(0); connection.setState(StateRegistry.LOGIN); - for (int i = 0;i { - connection.setType(new ForgeFML2ConnectionType()); - serverCon.setConnectionPhase(new VelocityForgeBackendConnectionPhase(ambassador)); - byte[] response = ((VelocityForgeBackendConnectionPhase)serverCon.getPhase()).generateResponse(serverCon.getPlayer(), Unpooled.wrappedBuffer(event.getContents())); - event.setResult(ServerLoginPluginMessageEvent.ResponseResult.reply(response)); + if (event.getSequenceId() == 0) { + connection.setType(new ForgeFML2ConnectionType()); + serverCon.setConnectionPhase(new VelocityForgeBackendConnectionPhase(ambassador)); + byte[] response = ((VelocityForgeBackendConnectionPhase)serverCon.getPhase()).generateResponse(serverCon.getPlayer(), Unpooled.wrappedBuffer(event.getContents())); + event.setResult(ServerLoginPluginMessageEvent.ResponseResult.reply(response)); + MinecraftSessionHandler sessionHandler = new VelocityForgeBackendHandshakeSessionHandler(connection.getSessionHandler(),serverCon); + connection.setSessionHandler(sessionHandler); + ((ForgeFML2ClientConnectionPhase) serverCon.getPlayer().getPhase()).reset(serverCon.getPlayer(), serverCon.getPlayer().getConnection(),event.getContents()); + } else { + ((ForgeFML2ClientConnectionPhase) serverCon.getPlayer().getPhase()).send(serverCon.getPlayer(), new LoginPluginMessage(event.getSequenceId(),event.getIdentifier().getId(),Unpooled.wrappedBuffer(event.getContents()))); + } continuation.resume(); - MinecraftSessionHandler sessionHandler = new VelocityForgeBackendHandshakeSessionHandler(connection.getSessionHandler(),serverCon); - connection.setSessionHandler(sessionHandler); }); } } 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 f379d44..8aac65a 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java @@ -1,25 +1,20 @@ package org.adde0109.ambassador.velocity.backend; -import com.google.common.io.ByteArrayDataInput; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftConnection; 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.ProtocolUtils; -import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse; -import com.velocitypowered.proxy.protocol.packet.PluginMessage; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import org.adde0109.ambassador.Ambassador; import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase; import org.adde0109.ambassador.forge.ForgeHandshakeUtils; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; -import java.io.EOFException; import java.util.ArrayList; import java.util.List; @@ -33,8 +28,9 @@ public class VelocityForgeBackendConnectionPhase implements BackendConnectionPha } public void handleSuccess(VelocityServerConnection serverCon) { - ((ForgeFML2ClientConnectionPhase) serverCon.getPlayer().getPhase()).reset(serverCon.getPlayer(),serverCon.getPlayer().getConnection(), handshakeMessages, - () -> ForgeHandshakeUtils.complete((VelocityServer) ambassador.server,serverCon.getPlayer(),serverCon.getPlayer().getConnection())); + ForgeHandshakeUtils.complete((VelocityServer) ambassador.server,serverCon.getPlayer(),serverCon.getPlayer().getConnection()); + //((ForgeFML2ClientConnectionPhase) serverCon.getPlayer().getPhase()).reset(serverCon.getPlayer(),serverCon.getPlayer().getConnection(), handshakeMessages, + // () -> ForgeHandshakeUtils.complete((VelocityServer) ambassador.server,serverCon.getPlayer(),serverCon.getPlayer().getConnection())); } public byte[] generateResponse(ConnectedPlayer player, ByteBuf content) { @@ -58,11 +54,8 @@ public class VelocityForgeBackendConnectionPhase implements BackendConnectionPha if (!message.getChannel().equals("fml:loginwrapper") || !(player.getPhase() instanceof VelocityForgeClientConnectionPhase)) { return false; } - MinecraftConnection connection = server.getConnection(); - if (connection == null) { - throw new NullPointerException(); - } - connection.write(new LoginPluginResponse(message.getId(),true, Unpooled.wrappedBuffer(generateResponse(player,message.content())))); + message.retain(); + ((ForgeFML2ClientConnectionPhase) player.getPhase()).send(player,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 index da5700e..8d39fd6 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeSessionHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeSessionHandler.java @@ -1,18 +1,20 @@ package org.adde0109.ambassador.velocity.backend; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.connection.backend.LoginSessionHandler; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.protocol.MinecraftPacket; 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 LoginSessionHandler original; private final VelocityServerConnection serverCon; public VelocityForgeBackendHandshakeSessionHandler(MinecraftSessionHandler original, VelocityServerConnection serverCon) { - this.original = original; + this.original = (LoginSessionHandler) original; this.serverCon = serverCon; } @@ -21,6 +23,11 @@ public class VelocityForgeBackendHandshakeSessionHandler implements MinecraftSes original.disconnected(); } + @Override + public void handleGeneric(MinecraftPacket packet) { + packet.handle(original); + } + @Override public void exception(Throwable throwable) { original.exception(throwable); @@ -37,8 +44,8 @@ public class VelocityForgeBackendHandshakeSessionHandler implements MinecraftSes @Override public boolean handle(ServerLoginSuccess packet) { - original.handle(packet); ((VelocityForgeBackendConnectionPhase) serverCon.getPhase()).handleSuccess(serverCon); + original.handle(packet); return true; } } diff --git a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendTransitionSessionHandler.java b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendTransitionSessionHandler.java new file mode 100644 index 0000000..91236e1 --- /dev/null +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendTransitionSessionHandler.java @@ -0,0 +1,54 @@ +package org.adde0109.ambassador.velocity.backend; + +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.connection.backend.TransitionSessionHandler; +import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import com.velocitypowered.proxy.protocol.StateRegistry; +import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; +import com.velocitypowered.proxy.protocol.packet.PluginMessage; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +public class VelocityForgeBackendTransitionSessionHandler implements MinecraftSessionHandler { + private final TransitionSessionHandler original; + private final VelocityServerConnection serverCon; + + public VelocityForgeBackendTransitionSessionHandler(MinecraftSessionHandler original, VelocityServerConnection serverCon) { + this.original = (TransitionSessionHandler) original; + this.serverCon = serverCon; + } + + @Override + public boolean beforeHandle() { + return original.beforeHandle(); + } + + @Override + public void disconnected() { + original.disconnected(); + } + + @Override + public void handleGeneric(MinecraftPacket packet) { + packet.handle(original); + } + + @Override + public boolean handle(PluginMessage packet) { + if (serverCon.getPlayer().getConnection().getState() == StateRegistry.LOGIN) { + //So it can't send when the client is in LOGIN state. + //We can instead use forge's LoginWrapper + ByteBuf wrapped = Unpooled.buffer(); + ProtocolUtils.writeString(wrapped,"minecraft:register"); + ProtocolUtils.writeVarInt(wrapped, packet.content().readableBytes()); + wrapped.writeBytes(packet.content()); + serverCon.getPlayer().getConnection().write(new LoginPluginMessage(97,"fml:loginwrapper",wrapped)); + } else { + original.handle(packet); + } + return true; + } + +}