WIP: Works but NEEDS CLEANUP

This commit is contained in:
Adrian Bergqvist 2022-09-20 22:34:05 +02:00
parent fea9082dd7
commit d6dcb9a814
No known key found for this signature in database
GPG Key ID: FAE7D8EDE225E686
7 changed files with 115 additions and 38 deletions

View File

@ -4,7 +4,7 @@ plugins {
} }
group 'org.adde0109' group 'org.adde0109'
version '0.4.0-reset' version '1.0.0-alpha'
repositories { repositories {
maven { maven {

View File

@ -28,7 +28,7 @@ import org.slf4j.Logger;
import java.nio.file.Path; 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 class Ambassador {
public ProxyServer server; public ProxyServer server;

View File

@ -1,6 +1,7 @@
package org.adde0109.ambassador.forge; package org.adde0109.ambassador.forge;
import com.velocitypowered.api.event.Continuation; import com.velocitypowered.api.event.Continuation;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.util.UuidUtils; import com.velocitypowered.api.util.UuidUtils;
import com.velocitypowered.proxy.Velocity; import com.velocitypowered.proxy.Velocity;
import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.VelocityServer;
@ -19,6 +20,8 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase;
import org.adde0109.ambassador.velocity.VelocityForgeHandshakeSessionHandler; 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 javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
@ -36,21 +39,23 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec
public byte[] modListData; public byte[] modListData;
private final ArrayList<Integer> listenerList = new ArrayList(); private final ArrayList<Integer> listenerList = new ArrayList();
public ArrayList<LoginPluginMessage> packagesToSendAfterReset = new ArrayList<>();
private Runnable whenComplete; private Runnable whenComplete;
public boolean isReady = false;
@Override @Override
public void handleLogin(ConnectedPlayer player,ForgeHandshakeUtils.CachedServerHandshake handshake, Continuation continuation) { public void handleLogin(ConnectedPlayer player,ForgeHandshakeUtils.CachedServerHandshake handshake, Continuation continuation) {
this.whenComplete = continuation::resume; this.whenComplete = continuation::resume;
final MinecraftConnection connection = player.getConnection(); final MinecraftConnection connection = player.getConnection();
VelocityForgeHandshakeSessionHandler sessionHandler = new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),player); VelocityForgeHandshakeSessionHandler sessionHandler = new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),player);
if(handshake == null) { if(handshake == null) {
connection.delayedWrite(new LoginPluginMessage(1,"fml:loginwrapper", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateEmptyModlist()))); connection.delayedWrite(new LoginPluginMessage(0,"fml:loginwrapper", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateEmptyModlist())));
listenerList.add(1); listenerList.add(0);
} else { } else {
connection.delayedWrite(new LoginPluginMessage(1,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.modListPacket))); connection.delayedWrite(new LoginPluginMessage(0,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.modListPacket)));
listenerList.add(1); listenerList.add(0);
for (int i = 0;i<handshake.otherPackets.size();i++) { for (int i = 0;i<handshake.otherPackets.size();i++) {
connection.delayedWrite(new LoginPluginMessage(i+2,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.otherPackets.get(i)))); connection.delayedWrite(new LoginPluginMessage(i+1,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.otherPackets.get(i))));
listenerList.add(i+2); listenerList.add(i+1);
} }
} }
connection.setSessionHandler(sessionHandler); connection.setSessionHandler(sessionHandler);
@ -60,11 +65,16 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec
@Override @Override
public boolean handle(ConnectedPlayer player, LoginPluginResponse packet) { public boolean handle(ConnectedPlayer player, LoginPluginResponse packet) {
if (!listenerList.removeIf(id -> id.equals(packet.getId()))) { if (!listenerList.removeIf(id -> id.equals(packet.getId()))) {
return false; player.getConnectionInFlight().getConnection().write(packet.retain());
return true;
} }
if (packet.getId() == 98) { if (packet.getId() == 98) {
isResettable = packet.isSuccess(); for (LoginPluginMessage packet1 : packagesToSendAfterReset) {
} else if (packet.getId() == 1) { player.getConnection().delayedWrite(packet1);
}
packagesToSendAfterReset = new ArrayList<>();
player.getConnection().flush();
} else if (packet.getId() == 0) {
if (!packet.isSuccess()) { if (!packet.isSuccess()) {
//TODO: Write disconnect message to end user //TODO: Write disconnect message to end user
player.getConnection().close(); player.getConnection().close();
@ -78,16 +88,23 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec
} }
return true; return true;
} }
public void reset(ConnectedPlayer player,MinecraftConnection connection, List<byte[]> messages, Runnable whenComplete) { public void reset(ConnectedPlayer player,MinecraftConnection connection, byte[] serverModlist) {
this.whenComplete = whenComplete; isReady = false;
if (player.getConnectedServer() != null) {
player.getConnectedServer().disconnect();
}
connection.setSessionHandler(new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),player)); connection.setSessionHandler(new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),player));
connection.write(new PluginMessage("fml:handshake",Unpooled.wrappedBuffer(ForgeHandshakeUtils.generatePluginResetPacket()))); connection.write(new PluginMessage("fml:handshake",Unpooled.wrappedBuffer(ForgeHandshakeUtils.generatePluginResetPacket())));
listenerList.add(98); listenerList.add(98);
send(player,new LoginPluginMessage(0,"fml:loginwrapper",Unpooled.wrappedBuffer(serverModlist)));
listenerList.add(0);
connection.setState(StateRegistry.LOGIN); connection.setState(StateRegistry.LOGIN);
for (int i = 0;i<messages.size();i++) { }
connection.delayedWrite(new LoginPluginMessage(i+2,"fml:loginwrapper", Unpooled.wrappedBuffer(messages.get(i)))); public void send(ConnectedPlayer player, LoginPluginMessage message) {
listenerList.add(i+2); if (isReady) {
player.getConnection().write(message);
} else {
packagesToSendAfterReset.add(message);
} }
connection.flush();
} }
} }

View File

@ -12,6 +12,7 @@ import com.velocitypowered.proxy.connection.backend.BackendConnectionPhases;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.adde0109.ambassador.Ambassador; import org.adde0109.ambassador.Ambassador;
@ -57,13 +58,18 @@ public class VelocityEventHandler {
return; return;
} }
connection.eventLoop().submit(() -> { connection.eventLoop().submit(() -> {
connection.setType(new ForgeFML2ConnectionType()); if (event.getSequenceId() == 0) {
serverCon.setConnectionPhase(new VelocityForgeBackendConnectionPhase(ambassador)); connection.setType(new ForgeFML2ConnectionType());
byte[] response = ((VelocityForgeBackendConnectionPhase)serverCon.getPhase()).generateResponse(serverCon.getPlayer(), Unpooled.wrappedBuffer(event.getContents())); serverCon.setConnectionPhase(new VelocityForgeBackendConnectionPhase(ambassador));
event.setResult(ServerLoginPluginMessageEvent.ResponseResult.reply(response)); 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(); continuation.resume();
MinecraftSessionHandler sessionHandler = new VelocityForgeBackendHandshakeSessionHandler(connection.getSessionHandler(),serverCon);
connection.setSessionHandler(sessionHandler);
}); });
} }
} }

View File

@ -1,25 +1,20 @@
package org.adde0109.ambassador.velocity.backend; package org.adde0109.ambassador.velocity.backend;
import com.google.common.io.ByteArrayDataInput;
import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.backend.BackendConnectionPhase; import com.velocitypowered.proxy.connection.backend.BackendConnectionPhase;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.ProtocolUtils; 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.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse; import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.adde0109.ambassador.Ambassador; import org.adde0109.ambassador.Ambassador;
import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase; import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase;
import org.adde0109.ambassador.forge.ForgeHandshakeUtils; import org.adde0109.ambassador.forge.ForgeHandshakeUtils;
import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase;
import java.io.EOFException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -33,8 +28,9 @@ public class VelocityForgeBackendConnectionPhase implements BackendConnectionPha
} }
public void handleSuccess(VelocityServerConnection serverCon) { 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) { 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)) { if (!message.getChannel().equals("fml:loginwrapper") || !(player.getPhase() instanceof VelocityForgeClientConnectionPhase)) {
return false; return false;
} }
MinecraftConnection connection = server.getConnection(); message.retain();
if (connection == null) { ((ForgeFML2ClientConnectionPhase) player.getPhase()).send(player,message);
throw new NullPointerException();
}
connection.write(new LoginPluginResponse(message.getId(),true, Unpooled.wrappedBuffer(generateResponse(player,message.content()))));
return true; return true;
} }

View File

@ -1,18 +1,20 @@
package org.adde0109.ambassador.velocity.backend; package org.adde0109.ambassador.velocity.backend;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler; 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.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; 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.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess;
import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase;
public class VelocityForgeBackendHandshakeSessionHandler implements MinecraftSessionHandler { public class VelocityForgeBackendHandshakeSessionHandler implements MinecraftSessionHandler {
private final MinecraftSessionHandler original; private final LoginSessionHandler original;
private final VelocityServerConnection serverCon; private final VelocityServerConnection serverCon;
public VelocityForgeBackendHandshakeSessionHandler(MinecraftSessionHandler original, VelocityServerConnection serverCon) { public VelocityForgeBackendHandshakeSessionHandler(MinecraftSessionHandler original, VelocityServerConnection serverCon) {
this.original = original; this.original = (LoginSessionHandler) original;
this.serverCon = serverCon; this.serverCon = serverCon;
} }
@ -21,6 +23,11 @@ public class VelocityForgeBackendHandshakeSessionHandler implements MinecraftSes
original.disconnected(); original.disconnected();
} }
@Override
public void handleGeneric(MinecraftPacket packet) {
packet.handle(original);
}
@Override @Override
public void exception(Throwable throwable) { public void exception(Throwable throwable) {
original.exception(throwable); original.exception(throwable);
@ -37,8 +44,8 @@ public class VelocityForgeBackendHandshakeSessionHandler implements MinecraftSes
@Override @Override
public boolean handle(ServerLoginSuccess packet) { public boolean handle(ServerLoginSuccess packet) {
original.handle(packet);
((VelocityForgeBackendConnectionPhase) serverCon.getPhase()).handleSuccess(serverCon); ((VelocityForgeBackendConnectionPhase) serverCon.getPhase()).handleSuccess(serverCon);
original.handle(packet);
return true; return true;
} }
} }

View File

@ -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;
}
}