diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java index d608877..81333b1 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeFML2ClientConnectionPhase.java @@ -7,6 +7,7 @@ import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.adde0109.ambassador.velocity.VelocityForgeHandshakeSessionHandler; @@ -17,7 +18,9 @@ import java.util.Optional; public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnectionPhase { private boolean isResettable; - private Optional modListData = Optional.empty(); + + //TODO: Use modData inside ConnectedPlayer instead + public byte[] modListData; private final ArrayList listenerList = new ArrayList(); private Continuation whenComplete; @@ -54,7 +57,7 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec player.getConnection().close(); return true; } - modListData = Optional.of(packet.content().retain()); + modListData = ByteBufUtil.getBytes(packet.content()); } if (listenerList.isEmpty()) { whenComplete.resume(); diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeUtils.java b/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeUtils.java index 66a167b..ede6eee 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeUtils.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeHandshakeUtils.java @@ -74,6 +74,19 @@ public class ForgeHandshakeUtils { return stream.toByteArray(); } + public static final byte[] ACKPacket = generateACKPacket(); + private static byte[] generateACKPacket() { + ByteArrayDataOutput dataAndPacketIdStream = ByteStreams.newDataOutput(); + writeVarInt(dataAndPacketIdStream,4); + + 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 { private int partLength; diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java index 647e732..1082c92 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java @@ -6,9 +6,12 @@ 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.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.backend.BackendConnectionPhases; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; +import io.netty.buffer.Unpooled; import org.adde0109.ambassador.Ambassador; import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase; import org.adde0109.ambassador.forge.ForgeFML2ConnectionType; @@ -40,17 +43,22 @@ public class VelocityEventHandler { @Subscribe public void onServerLoginPluginMessageEvent(ServerLoginPluginMessageEvent event, Continuation continuation) { - if (!Objects.equals(event.getIdentifier().getId(), "fml:loginwrapper")) { + if (!Objects.equals(event.getIdentifier().getId(), "fml:loginwrapper") || !(((ConnectedPlayer)event.getConnection().getPlayer()).getPhase() instanceof VelocityForgeClientConnectionPhase)) { 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())); + if (connection == null) { + //This should never happen. + continuation.resumeWithException(new NullPointerException()); + return; } + serverCon.setConnectionPhase(new VelocityForgeBackendConnectionPhase()); + connection.setType(new ForgeFML2ConnectionType()); + MinecraftSessionHandler sessionHandler = new VelocityForgeBackendHandshakeSessionHandler(connection.getSessionHandler(),serverCon); + connection.setSessionHandler(sessionHandler); + sessionHandler.handle(new LoginPluginMessage(event.getSequenceId(),event.getIdentifier().getId(), Unpooled.wrappedBuffer(event.getContents()))); continuation.resume(); } } 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 96b6937..8961511 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendConnectionPhase.java @@ -1,14 +1,51 @@ package org.adde0109.ambassador.velocity.backend; +import com.google.common.io.ByteArrayDataInput; +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.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.Unpooled; +import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase; +import org.adde0109.ambassador.forge.ForgeHandshakeUtils; +import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; + +import java.io.EOFException; public class VelocityForgeBackendConnectionPhase implements BackendConnectionPhase { public boolean handle(VelocityServerConnection server, ConnectedPlayer player, LoginPluginMessage message) { + if (!message.getChannel().equals("fml:loginwrapper") || !(player.getPhase() instanceof VelocityForgeClientConnectionPhase)) { + return false; + } + MinecraftConnection connection = server.getConnection(); + if (connection == null) { + throw new NullPointerException(); + } + + ByteBuf content = message.content(); + content.readBytes(14); //Channel Identifier + ProtocolUtils.readVarInt(content); //Length + int packetID = ProtocolUtils.readVarInt(content); + + + switch (packetID) { + + case 1: + final byte[] data = ((ForgeFML2ClientConnectionPhase) player.getPhase()).modListData; + connection.write(new LoginPluginResponse(message.getId(),true, Unpooled.wrappedBuffer(data))); + break; + + default: + connection.write(new LoginPluginResponse(message.getId(),true,Unpooled.wrappedBuffer(ForgeHandshakeUtils.ACKPacket))); + break; + } + 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 019583f..7e46568 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeSessionHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeSessionHandler.java @@ -37,7 +37,6 @@ public class VelocityForgeBackendHandshakeSessionHandler implements MinecraftSes @Override public boolean handle(ServerLoginSuccess packet) { - return original.handle(packet); } }