WIP: new handling structure

This commit is contained in:
Adrian Bergqvist 2022-09-11 17:08:31 +02:00
parent ff934dc106
commit 26e320f034
No known key found for this signature in database
GPG Key ID: FAE7D8EDE225E686
9 changed files with 168 additions and 88 deletions

View File

@ -10,18 +10,23 @@ import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import java.lang.reflect.Field;
import java.util.concurrent.Callable;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.network.ConnectionManager;
import io.netty.channel.ChannelInitializer;
import org.adde0109.ambassador.forge.ForgeConnection;
import org.adde0109.ambassador.forge.ForgeHandshakeHandler;
import org.adde0109.ambassador.forge.ForgeHandshakeUtils;
import org.adde0109.ambassador.forge.ForgeServerSwitchHandler;
import org.bstats.MetricsBase;
import org.adde0109.ambassador.velocity.VelocityChannelInitializer;
import org.adde0109.ambassador.velocity.VelocityEventHandler;
import org.bstats.charts.SingleLineChart;
import org.bstats.velocity.Metrics;
import org.slf4j.Logger;
import java.nio.file.Path;
import java.util.*;
@Plugin(id = "ambassador", name = "Ambassador", version = "0.4.0-reset", authors = {"adde0109"})
public class Ambassador {
@ -46,14 +51,14 @@ public class Ambassador {
}
@Subscribe
public void onProxyInitialization(ProxyInitializeEvent event) {
public void onProxyInitialization(ProxyInitializeEvent event) throws ReflectiveOperationException {
initMetrics();
config = AmbassadorConfig.readOrCreateConfig(dataDirectory,server,logger);
if(config != null) {
forgeHandshakeHandler = new ForgeHandshakeHandler(this);
forgeServerSwitchHandler = new ForgeServerSwitchHandler(this);
server.getEventManager().register(this, forgeHandshakeHandler);
server.getEventManager().register(this, new VelocityEventHandler(this));
server.getEventManager().register(this,forgeServerSwitchHandler);
}
else {
@ -61,6 +66,14 @@ public class Ambassador {
}
ForgeHandshakeUtils.HandshakeReceiver.logger = logger;
inject();
}
private void inject() throws ReflectiveOperationException {
Field cmField = VelocityServer.class.getDeclaredField("cm");
cmField.setAccessible(true);
ChannelInitializer<?> original = ((ConnectionManager) cmField.get(server)).serverChannelInitializer.get();
((ConnectionManager) cmField.get(server)).serverChannelInitializer.set(new VelocityChannelInitializer(original));
}
@Subscribe

View File

@ -1,14 +1,10 @@
package org.adde0109.ambassador.forge;
import com.velocitypowered.api.event.Continuation;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PreLoginEvent;
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
import com.velocitypowered.api.event.player.KickedFromServerEvent;
import com.velocitypowered.api.event.player.ServerLoginPluginMessageEvent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.LoginPhaseConnection;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
@ -17,18 +13,15 @@ import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import com.velocitypowered.proxy.connection.ConnectionType;
import com.velocitypowered.proxy.connection.ConnectionTypes;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import org.adde0109.ambassador.Ambassador;
import org.checkerframework.checker.units.qual.A;
import org.adde0109.ambassador.velocity.ForgeClientConnectionPhase;
public class ForgeHandshakeHandler {
@ -45,47 +38,27 @@ public class ForgeHandshakeHandler {
this.ambassador = ambassador;
}
@Subscribe(order = PostOrder.LAST)
public void onPreLoginEvent(PreLoginEvent event, Continuation continuation) {
if (event.getConnection().getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_13) < 0) {
continuation.resume();
return;
}
MinecraftConnection connection = (MinecraftConnection)event.getConnection();
((LoginPhaseConnection) event.getConnection()).sendLoginPluginMessage(
MinecraftChannelIdentifier.create("fml","loginwrapper"),
ForgeHandshakeUtils.generateTestPacket(),(msg) -> {
if (connection.getType() == ConnectionTypes.VANILLA) {
if (msg != null) {
connection.setType(new ForgeConnectionType());
}
}
public void handleLogin(ConnectedPlayer player, ForgeClientConnectionPhase phase, Continuation continuation) {
getInitialHandshake(player).whenComplete((msg,ex) -> {
if (ex != null) {
//SEND RESET PACKET
} else {
//SEND MODLIST
}
});
//SEND ===CLIENT MODLIST REQUEST===
((LoginPhaseConnection) event.getConnection()).sendLoginPluginMessage(
MinecraftChannelIdentifier.create("fml","loginwrapper"),
ForgeHandshakeUtils.generateTestPacket(),(msg) -> {
if (msg != null) {
connection.setType(new ForgeConnectionType());
//Handle the response
}
});
continuation.resume();
}
@Subscribe
public void onPermissionsSetupEvent(PermissionsSetupEvent event, Continuation continuation) {
//Filters...
if (!(event.getSubject() instanceof ConnectedPlayer)) {
continuation.resume();
return;
private CompletableFuture<ForgeHandshakeUtils.CachedServerHandshake> getInitialHandshake(ConnectedPlayer player) {
CompletableFuture<ForgeHandshakeUtils.CachedServerHandshake> future;
RegisteredServer initialServer;
if((initialServer = ambassador.config.getServer(player.getConnection().getProtocolVersion().getProtocol())) != null) {
future = ForgeHandshakeUtils.HandshakeReceiver.downloadHandshake(initialServer);
} else {
future = CompletableFuture.failedFuture(new Exception("No initial server specified"));
}
ConnectedPlayer player = ((ConnectedPlayer) event.getSubject());
if (!(player.getConnection().getType() instanceof ForgeConnectionType)) {
continuation.resume();
return;
}
((ForgeClientConnectionPhase) player.getPhase()).handleLogin();
return future;
}
private void registerForgeConnection(ForgeConnection forgeConnection) {

View File

@ -1,32 +0,0 @@
package org.adde0109.ambassador.forge;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
import io.netty.buffer.Unpooled;
public class ForgeSessionHandler implements MinecraftSessionHandler {
private final MinecraftSessionHandler delegate;
private final MinecraftConnection connection;
public ForgeSessionHandler(MinecraftSessionHandler delegate, MinecraftConnection connection) {
this.delegate = delegate;
this.connection = connection;
}
@Override
public void handleGeneric(MinecraftPacket packet) {
packet.handle(delegate);
}
@Override
public void activated() {
}
@Override
public boolean handle(LoginPluginResponse packet) {
//DETECT FML or PCF
return false;
}

View File

@ -1,12 +1,14 @@
package org.adde0109.ambassador.forge;
package org.adde0109.ambassador.velocity;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.api.event.Continuation;
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.packet.PluginMessage;
public class ForgeClientConnectionPhase implements ClientConnectionPhase {
ForgeClientConnectionPhase(MinecraftConnection connection) {
}
public void handleLogin() {
}

View File

@ -1,15 +1,23 @@
package org.adde0109.ambassador.forge;
package org.adde0109.ambassador.velocity;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
import com.velocitypowered.proxy.connection.ConnectionType;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.backend.BackendConnectionPhase;
import com.velocitypowered.proxy.connection.client.ClientConnectionPhase;
import org.adde0109.ambassador.velocity.ForgeClientConnectionPhase;
public class ForgeConnectionType implements ConnectionType {
private final MinecraftConnection connection;
public ForgeConnectionType(MinecraftConnection connection) {
this.connection = connection;
}
@Override
public ClientConnectionPhase getInitialClientPhase() {
return new ForgeClientConnectionPhase();
return new ForgeClientConnectionPhase(connection);
}
@Override

View File

@ -0,0 +1,39 @@
package org.adde0109.ambassador.velocity;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
import com.velocitypowered.proxy.network.Connections;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
public class VelocityChannelInitializer extends ChannelInitializer<Channel> {
private static final Method INIT_CHANNEL;
private final ChannelInitializer<?> original;
static {
try {
INIT_CHANNEL = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
INIT_CHANNEL.setAccessible(true);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
public VelocityChannelInitializer(ChannelInitializer<?> original) {
this.original = original;
}
@Override
protected void initChannel(@NotNull Channel ch) throws Exception {
INIT_CHANNEL.invoke(original,ch);
ChannelHandler handler = ch.pipeline().get(Connections.HANDLER);
if (!(handler instanceof final MinecraftConnection connection)) throw new Exception("plugin conflict");
HandshakeSessionHandler originalSessionHandler = (HandshakeSessionHandler) connection.getSessionHandler();
connection.setSessionHandler(new VelocityHandshakeSessionHandler(originalSessionHandler, connection));
}
}

View File

@ -0,0 +1,29 @@
package org.adde0109.ambassador.velocity;
import com.velocitypowered.api.event.Continuation;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import org.adde0109.ambassador.Ambassador;
public class VelocityEventHandler {
private final Ambassador ambassador;
public VelocityEventHandler(Ambassador ambassador) {
this.ambassador = ambassador;
}
@Subscribe
public void onPermissionsSetupEvent(PermissionsSetupEvent event, Continuation continuation) {
if(!(event.getSubject() instanceof ConnectedPlayer player)) {
continuation.resume();
return;
}
if (!(player.getPhase() instanceof ForgeClientConnectionPhase phase)) {
continuation.resume();
return;
}
ambassador.forgeHandshakeHandler.handleLogin(player,phase,continuation);
}
}

View File

@ -0,0 +1,6 @@
package org.adde0109.ambassador.velocity;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
public class VelocityForgeHandshakeSessionHandler implements MinecraftSessionHandler {
}

View File

@ -0,0 +1,42 @@
package org.adde0109.ambassador.velocity;
import com.velocitypowered.proxy.connection.ConnectionTypes;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.Handshake;
import io.netty.buffer.ByteBuf;
public class VelocityHandshakeSessionHandler implements MinecraftSessionHandler {
private final HandshakeSessionHandler original;
private final MinecraftConnection connection;
public VelocityHandshakeSessionHandler(HandshakeSessionHandler original, MinecraftConnection connection) {
this.original = original;
this.connection = connection;
}
@Override
public boolean handle(Handshake handshake) {
handshake.handle(original);
if (connection.getType() == ConnectionTypes.VANILLA && connection.getState() == StateRegistry.LOGIN) {
if (handshake.getServerAddress().split("\0")[1].equals("FML2")) {
connection.setType(new ForgeConnectionType(connection));
}
}
return true;
}
@Override
public void handleGeneric(MinecraftPacket packet) {
packet.handle(original);
}
@Override
public void handleUnknown(ByteBuf buf) {
original.handleUnknown(buf);
}
}