From b350b5819167415f48d6c5b1bd72755fc65284ad Mon Sep 17 00:00:00 2001 From: Outfluencer Date: Sat, 14 Sep 2024 14:56:11 +0200 Subject: [PATCH 1/2] update bungee injector --- .../inject/bungee/BungeeInjector.java | 57 +++++++------------ 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/bungee/src/main/java/org/geysermc/floodgate/inject/bungee/BungeeInjector.java b/bungee/src/main/java/org/geysermc/floodgate/inject/bungee/BungeeInjector.java index ac39d4d0..b12a3597 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/inject/bungee/BungeeInjector.java +++ b/bungee/src/main/java/org/geysermc/floodgate/inject/bungee/BungeeInjector.java @@ -28,15 +28,16 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; import java.lang.reflect.Field; +import java.lang.reflect.Method; import lombok.Getter; import lombok.RequiredArgsConstructor; import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.protocol.MinecraftEncoder; import net.md_5.bungee.protocol.Varint21LengthFieldExtraBufPrepender; -import net.md_5.bungee.protocol.Varint21LengthFieldPrepender; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.inject.CommonPlatformInjector; import org.geysermc.floodgate.util.BungeeReflectionUtils; @@ -52,8 +53,10 @@ public final class BungeeInjector extends CommonPlatformInjector { @Override public void inject() { // Can everyone just switch to Velocity please :) + // :( ~BungeeCord Collaborator // Newer Bungee versions have a separate prepender for backend and client connections + // this field is not touched by client -> proxy Field serverFramePrepender = ReflectionUtils.getField(PipelineUtils.class, "serverFramePrepender"); if (serverFramePrepender != null) { @@ -63,16 +66,25 @@ public void inject() { BungeeReflectionUtils.setFieldValue(null, serverFramePrepender, customServerPrepender); } - Field framePrepender = ReflectionUtils.getField(PipelineUtils.class, "framePrepender"); - - // Required in order to inject into both Geyser <-> proxy AND proxy <-> server - // (Instead of just replacing the ChannelInitializer which is only called for - // player <-> proxy) - BungeeCustomPrepender customPrepender = new BungeeCustomPrepender( - this, ReflectionUtils.castedStaticValue(framePrepender) + // wrap the client -> proxy channel init because the framePrepender field was deleted + ChannelInitializer original = PipelineUtils.SERVER_CHILD; + Field clientChannelInitField = ReflectionUtils.getField( + PipelineUtils.class, "SERVER_CHILD" ); - - BungeeReflectionUtils.setFieldValue(null, framePrepender, customPrepender); + Method initChannelMethod = ReflectionUtils.getMethod( + original.getClass(), "initChannel", Channel.class + ); + ChannelInitializer wrapper = new ChannelInitializer() { + @Override + protected void initChannel(Channel channel) { + ReflectionUtils.invoke(original, initChannelMethod, channel); + channel.pipeline().addBefore( + PipelineUtils.FRAME_DECODER, BUNGEE_INIT, + new BungeeClientToProxyInjectInitializer(BungeeInjector.this) + ); + } + }; + BungeeReflectionUtils.setFieldValue(null, clientChannelInitField, wrapper); injected = true; } @@ -105,31 +117,6 @@ void injectClient(Channel channel, boolean clientToProxy) { addInjectedClient(channel); } - @RequiredArgsConstructor - private static final class BungeeCustomPrepender extends Varint21LengthFieldPrepender { - private final BungeeInjector injector; - private final Varint21LengthFieldPrepender original; - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - original.handlerAdded(ctx); - // The Minecraft encoder being in the pipeline isn't present until later - - if (ctx.channel().parent() != null) { - // Client <-> Proxy - ctx.pipeline().addBefore( - PipelineUtils.FRAME_DECODER, BUNGEE_INIT, - new BungeeClientToProxyInjectInitializer(injector) - ); - } else { - // Proxy <-> Server - ctx.pipeline().addLast( - BUNGEE_INIT, new BungeeProxyToServerInjectInitializer(injector) - ); - } - } - } - @RequiredArgsConstructor private static final class BungeeCustomServerPrepender extends Varint21LengthFieldExtraBufPrepender { From 2a23d3c46b16b44b86ee885d8f9e5aba482b98a6 Mon Sep 17 00:00:00 2001 From: Outfluencer Date: Sat, 14 Sep 2024 20:52:12 +0200 Subject: [PATCH 2/2] add backwards compatibility --- .../inject/bungee/BungeeInjector.java | 78 ++++++++++++++----- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/bungee/src/main/java/org/geysermc/floodgate/inject/bungee/BungeeInjector.java b/bungee/src/main/java/org/geysermc/floodgate/inject/bungee/BungeeInjector.java index b12a3597..53e56b67 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/inject/bungee/BungeeInjector.java +++ b/bungee/src/main/java/org/geysermc/floodgate/inject/bungee/BungeeInjector.java @@ -38,6 +38,7 @@ import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.protocol.MinecraftEncoder; import net.md_5.bungee.protocol.Varint21LengthFieldExtraBufPrepender; +import net.md_5.bungee.protocol.Varint21LengthFieldPrepender; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.inject.CommonPlatformInjector; import org.geysermc.floodgate.util.BungeeReflectionUtils; @@ -66,25 +67,39 @@ public void inject() { BungeeReflectionUtils.setFieldValue(null, serverFramePrepender, customServerPrepender); } - // wrap the client -> proxy channel init because the framePrepender field was deleted - ChannelInitializer original = PipelineUtils.SERVER_CHILD; - Field clientChannelInitField = ReflectionUtils.getField( - PipelineUtils.class, "SERVER_CHILD" - ); - Method initChannelMethod = ReflectionUtils.getMethod( - original.getClass(), "initChannel", Channel.class - ); - ChannelInitializer wrapper = new ChannelInitializer() { - @Override - protected void initChannel(Channel channel) { - ReflectionUtils.invoke(original, initChannelMethod, channel); - channel.pipeline().addBefore( - PipelineUtils.FRAME_DECODER, BUNGEE_INIT, - new BungeeClientToProxyInjectInitializer(BungeeInjector.this) - ); - } - }; - BungeeReflectionUtils.setFieldValue(null, clientChannelInitField, wrapper); + // for backwards compatibility + Field framePrepender = ReflectionUtils.getField(PipelineUtils.class, "framePrepender"); + if (framePrepender != null) { + logger.warn("You are running an old version of BungeeCord consider updating to a newer version"); + // Required in order to inject into both Geyser <-> proxy AND proxy <-> server + // (Instead of just replacing the ChannelInitializer which is only called for + // player <-> proxy) + BungeeCustomPrepender customPrepender = new BungeeCustomPrepender( + this, ReflectionUtils.castedStaticValue(framePrepender) + ); + + BungeeReflectionUtils.setFieldValue(null, framePrepender, customPrepender); + } else { + // wrap the client -> proxy channel init because the framePrepender field was deleted + ChannelInitializer original = PipelineUtils.SERVER_CHILD; + Field clientChannelInitField = ReflectionUtils.getField( + PipelineUtils.class, "SERVER_CHILD" + ); + Method initChannelMethod = ReflectionUtils.getMethod( + original.getClass(), "initChannel", Channel.class + ); + ChannelInitializer wrapper = new ChannelInitializer() { + @Override + protected void initChannel(Channel channel) { + ReflectionUtils.invoke(original, initChannelMethod, channel); + channel.pipeline().addBefore( + PipelineUtils.FRAME_DECODER, BUNGEE_INIT, + new BungeeClientToProxyInjectInitializer(BungeeInjector.this) + ); + } + }; + BungeeReflectionUtils.setFieldValue(null, clientChannelInitField, wrapper); + } injected = true; } @@ -117,6 +132,31 @@ void injectClient(Channel channel, boolean clientToProxy) { addInjectedClient(channel); } + @RequiredArgsConstructor + private static final class BungeeCustomPrepender extends Varint21LengthFieldPrepender { + private final BungeeInjector injector; + private final Varint21LengthFieldPrepender original; + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + original.handlerAdded(ctx); + // The Minecraft encoder being in the pipeline isn't present until later + + if (ctx.channel().parent() != null) { + // Client <-> Proxy + ctx.pipeline().addBefore( + PipelineUtils.FRAME_DECODER, BUNGEE_INIT, + new BungeeClientToProxyInjectInitializer(injector) + ); + } else { + // Proxy <-> Server + ctx.pipeline().addLast( + BUNGEE_INIT, new BungeeProxyToServerInjectInitializer(injector) + ); + } + } + } + @RequiredArgsConstructor private static final class BungeeCustomServerPrepender extends Varint21LengthFieldExtraBufPrepender {