WIP: Restruct

This commit is contained in:
Adrian Bergqvist 2022-09-22 22:45:39 +02:00
parent d6dcb9a814
commit 2ab257ffe7
No known key found for this signature in database
GPG Key ID: FAE7D8EDE225E686
11 changed files with 138 additions and 160 deletions

View File

@ -72,6 +72,9 @@ public class Ambassador {
private void inject() throws ReflectiveOperationException {
Field cmField = VelocityServer.class.getDeclaredField("cm");
cmField.setAccessible(true);
Field endpointMap = ConnectionManager.class.getDeclaredField("endpoints");
endpointMap.setAccessible(true);
ChannelInitializer<?> original = ((ConnectionManager) cmField.get(server)).serverChannelInitializer.get();
((ConnectionManager) cmField.get(server)).serverChannelInitializer.set(new VelocityServerChannelInitializer(original));
}

View File

@ -0,0 +1,5 @@
package org.adde0109.ambassador.forge;
public class ForgeConstants {
public static final String HANDLER = "Modern Forge handler";
}

View File

@ -10,6 +10,7 @@ import com.velocitypowered.proxy.config.VelocityConfiguration;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.client.ClientConnectionPhase;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
@ -39,7 +40,7 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec
public byte[] modListData;
private final ArrayList<Integer> listenerList = new ArrayList();
public ArrayList<LoginPluginMessage> packagesToSendAfterReset = new ArrayList<>();
public ArrayList<MinecraftPacket> packagesToSendAfterReset = new ArrayList<>();
private Runnable whenComplete;
public boolean isReady = false;
@Override
@ -48,7 +49,7 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec
final MinecraftConnection connection = player.getConnection();
VelocityForgeHandshakeSessionHandler sessionHandler = new VelocityForgeHandshakeSessionHandler(connection.getSessionHandler(),player);
if(handshake == null) {
connection.delayedWrite(new LoginPluginMessage(0,"fml:loginwrapper", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateEmptyModlist())));
connection.delayedWrite(new LoginPluginMessage(0,"fml:loginwrapper", Unpooled.wrappedBuffer(ForgeHandshakeUtils.emptyModlist)));
listenerList.add(0);
} else {
connection.delayedWrite(new LoginPluginMessage(0,"fml:loginwrapper", Unpooled.wrappedBuffer(handshake.modListPacket)));
@ -69,7 +70,8 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec
return true;
}
if (packet.getId() == 98) {
for (LoginPluginMessage packet1 : packagesToSendAfterReset) {
isReady = true;
for (MinecraftPacket packet1 : packagesToSendAfterReset) {
player.getConnection().delayedWrite(packet1);
}
packagesToSendAfterReset = new ArrayList<>();
@ -88,7 +90,7 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec
}
return true;
}
public void reset(ConnectedPlayer player,MinecraftConnection connection, byte[] serverModlist) {
public void reset(ConnectedPlayer player,MinecraftConnection connection) {
isReady = false;
if (player.getConnectedServer() != null) {
player.getConnectedServer().disconnect();
@ -96,11 +98,23 @@ public class ForgeFML2ClientConnectionPhase implements VelocityForgeClientConnec
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);
}
public void send(ConnectedPlayer player, LoginPluginMessage message) {
public void complete(VelocityServer server, ConnectedPlayer player, MinecraftConnection connection) {
VelocityConfiguration configuration = (VelocityConfiguration) server.getConfiguration();
UUID playerUniqueId = player.getUniqueId();
if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.NONE) {
playerUniqueId = UuidUtils.generateOfflinePlayerUuid(player.getUsername());
}
ServerLoginSuccess success = new ServerLoginSuccess();
success.setUsername(player.getUsername());
success.setUuid(playerUniqueId);
send(player,success);
connection.setState(StateRegistry.PLAY);
connection.setSessionHandler(((VelocityForgeHandshakeSessionHandler) connection.getSessionHandler()).getOriginal());
}
public void send(ConnectedPlayer player, MinecraftPacket message) {
if (isReady) {
player.getConnection().write(message);
} else {

View File

@ -9,6 +9,8 @@ import com.velocitypowered.proxy.connection.backend.BackendConnectionPhases;
import com.velocitypowered.proxy.connection.client.ClientConnectionPhase;
import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendConnectionPhase;
import java.util.Collections;
public class ForgeFML2ConnectionType implements ConnectionType {
@Override
@ -23,6 +25,7 @@ public class ForgeFML2ConnectionType implements ConnectionType {
@Override
public GameProfile addGameProfileTokensIfRequired(GameProfile original, PlayerInfoForwarding forwardingType) {
original.addProperties(Collections.singleton(new GameProfile.Property("extraData", "\1FML2\1", "")));
return original;
}
}

View File

@ -88,7 +88,8 @@ public class ForgeHandshakeUtils {
return dataAndPacketIdStream.toByteArray();
}
public static byte[] generateEmptyModlist() {
public static final byte[] emptyModlist = generateEmptyModlist();
private static byte[] generateEmptyModlist() {
ByteArrayDataOutput dataAndPacketIdStream = ByteStreams.newDataOutput();
writeVarInt(dataAndPacketIdStream,1);
writeVarInt(dataAndPacketIdStream,0);
@ -103,20 +104,6 @@ public class ForgeHandshakeUtils {
return stream.toByteArray();
}
static public void complete(VelocityServer server, ConnectedPlayer player, MinecraftConnection connection) {
VelocityConfiguration configuration = (VelocityConfiguration) server.getConfiguration();
UUID playerUniqueId = player.getUniqueId();
if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.NONE) {
playerUniqueId = UuidUtils.generateOfflinePlayerUuid(player.getUsername());
}
ServerLoginSuccess success = new ServerLoginSuccess();
success.setUsername(player.getUsername());
success.setUuid(playerUniqueId);
connection.write(success);
connection.setState(StateRegistry.PLAY);
connection.setSessionHandler(((VelocityForgeHandshakeSessionHandler) connection.getSessionHandler()).getOriginal());
}
public static final byte[] ACKPacket = generateACKPacket();
private static byte[] generateACKPacket() {

View File

@ -0,0 +1,55 @@
package org.adde0109.ambassador.velocity;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import org.adde0109.ambassador.forge.ForgeConstants;
import org.adde0109.ambassador.forge.ForgeFML2ClientConnectionPhase;
import org.adde0109.ambassador.forge.ForgeFML2ConnectionType;
import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendHandshakeHandler;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
public class VelocityBackendChannelInitializer extends ChannelInitializer<Channel> {
private static final Method INIT_CHANNEL;
private final ChannelInitializer<?> original;
private final VelocityServer server;
static {
try {
INIT_CHANNEL = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
INIT_CHANNEL.setAccessible(true);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
public VelocityBackendChannelInitializer(ChannelInitializer<?> original, VelocityServer server) {
this.original = original;
this.server = server;
}
@Override
protected void initChannel(@NotNull Channel ch) throws Exception {
INIT_CHANNEL.invoke(original);
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.handler() instanceof MinecraftConnection connection) {
if (connection.getAssociation() instanceof VelocityServerConnection serverConnection) {
if (serverConnection.getPlayer().getPhase() instanceof ForgeFML2ClientConnectionPhase) {
connection.setType(new ForgeFML2ConnectionType());
ctx.pipeline().addBefore(ctx.name(), ForgeConstants.HANDLER, new VelocityForgeBackendHandshakeHandler(connection, serverConnection, server));
}
}
}
super.handlerAdded(ctx);
}
}

View File

@ -4,22 +4,17 @@ import com.velocitypowered.api.event.Continuation;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
import com.velocitypowered.api.event.player.ServerLoginPluginMessageEvent;
import com.velocitypowered.proxy.VelocityServer;
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 com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
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.ForgeFML2ConnectionType;
import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendConnectionPhase;
import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendHandshakeSessionHandler;
import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendHandshakeHandler;
import java.util.Objects;
@ -44,7 +39,7 @@ public class VelocityEventHandler {
ambassador.forgeHandshakeHandler.handleLogin(player,continuation);
}
@Subscribe
/*@Subscribe
public void onServerLoginPluginMessageEvent(ServerLoginPluginMessageEvent event, Continuation continuation) {
if (!Objects.equals(event.getIdentifier().getId(), "fml:loginwrapper") || !(((ConnectedPlayer)event.getConnection().getPlayer()).getPhase() instanceof VelocityForgeClientConnectionPhase)) {
continuation.resume();
@ -63,7 +58,7 @@ public class VelocityEventHandler {
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);
MinecraftSessionHandler sessionHandler = new VelocityForgeBackendHandshakeHandler(connection.getSessionHandler(),serverCon);
connection.setSessionHandler(sessionHandler);
((ForgeFML2ClientConnectionPhase) serverCon.getPlayer().getPhase()).reset(serverCon.getPlayer(), serverCon.getPlayer().getConnection(),event.getContents());
} else {
@ -71,5 +66,5 @@ public class VelocityEventHandler {
}
continuation.resume();
});
}
}*/
}

View File

@ -1,5 +1,6 @@
package org.adde0109.ambassador.velocity.backend;
import com.velocitypowered.proxy.Velocity;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.backend.BackendConnectionPhase;
@ -21,42 +22,26 @@ import java.util.List;
public class VelocityForgeBackendConnectionPhase implements BackendConnectionPhase {
private final Ambassador ambassador;
private final List<byte[]> handshakeMessages = new ArrayList<>();
private boolean vanilla = true;
public VelocityForgeBackendConnectionPhase(Ambassador ambassador) {
this.ambassador = ambassador;
}
public void handleSuccess(VelocityServerConnection serverCon) {
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) {
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;
return data;
default:
return ForgeHandshakeUtils.ACKPacket;
public void handleSuccess(VelocityServerConnection serverCon, VelocityServer server) {
ForgeFML2ClientConnectionPhase clientPhase = ((ForgeFML2ClientConnectionPhase) serverCon.getPlayer().getPhase());
if (vanilla) {
clientPhase.reset(serverCon.getPlayer(),serverCon.getPlayer().getConnection());
}
clientPhase.complete((VelocityServer) ambassador.server,serverCon.getPlayer(),serverCon.getPlayer().getConnection());
}
public boolean handle(VelocityServerConnection server, ConnectedPlayer player, LoginPluginMessage message) {
if (!message.getChannel().equals("fml:loginwrapper") || !(player.getPhase() instanceof VelocityForgeClientConnectionPhase)) {
return false;
}
vanilla = false;
message.retain();
((ForgeFML2ClientConnectionPhase) player.getPhase()).send(player,message);
return true;
}
}

View File

@ -0,0 +1,36 @@
package org.adde0109.ambassador.velocity.backend;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
public class VelocityForgeBackendHandshakeHandler extends ChannelInboundHandlerAdapter {
private final MinecraftConnection connection;
private final VelocityServerConnection serverConnection;
private final VelocityServer server;
public VelocityForgeBackendHandshakeHandler(MinecraftConnection connection, VelocityServerConnection serverConnection, VelocityServer server) {
this.connection = connection;
this.serverConnection = serverConnection;
this.server = server;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof LoginPluginMessage message && message.getChannel().equals("fml:loginwrapper")) {
((VelocityForgeBackendConnectionPhase) serverConnection.getPhase()).handle(serverConnection, serverConnection.getPlayer(), message);
ReferenceCountUtil.release(msg);
} else if (msg instanceof ServerLoginSuccess) {
((VelocityForgeBackendConnectionPhase) serverConnection.getPhase()).handleSuccess(serverConnection,server);
ReferenceCountUtil.release(msg);
} else {
ctx.fireChannelRead(msg);
}
}
}

View File

@ -1,51 +0,0 @@
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 LoginSessionHandler original;
private final VelocityServerConnection serverCon;
public VelocityForgeBackendHandshakeSessionHandler(MinecraftSessionHandler original, VelocityServerConnection serverCon) {
this.original = (LoginSessionHandler) original;
this.serverCon = serverCon;
}
@Override
public void disconnected() {
original.disconnected();
}
@Override
public void handleGeneric(MinecraftPacket packet) {
packet.handle(original);
}
@Override
public void exception(Throwable throwable) {
original.exception(throwable);
}
@Override
public boolean handle(LoginPluginMessage packet) {
if (((VelocityForgeBackendConnectionPhase) serverCon.getPhase()).handle(serverCon, serverCon.getPlayer(), packet)) {
return true;
} else {
return original.handle(packet);
}
}
@Override
public boolean handle(ServerLoginSuccess packet) {
((VelocityForgeBackendConnectionPhase) serverCon.getPhase()).handleSuccess(serverCon);
original.handle(packet);
return true;
}
}

View File

@ -1,54 +0,0 @@
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;
}
}