diff --git a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/handlers/BukkitChannelInitializer.java b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/handlers/BukkitChannelInitializer.java index 532b784a2..60178857b 100644 --- a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/handlers/BukkitChannelInitializer.java +++ b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/handlers/BukkitChannelInitializer.java @@ -51,20 +51,23 @@ public class BukkitChannelInitializer extends ChannelInitializer @Override protected void initChannel(SocketChannel socketChannel) throws Exception { - UserConnection info = new UserConnectionImpl(socketChannel); - // init protocol - new ProtocolPipelineImpl(info); // Add originals this.method.invoke(this.original, socketChannel); + afterChannelInitialize(socketChannel); + } + + public static void afterChannelInitialize(Channel channel) { + UserConnection connection = new UserConnectionImpl(channel); + new ProtocolPipelineImpl(connection); - HandlerConstructor constructor = ClassGenerator.getConstructor(); // Add our transformers - MessageToByteEncoder encoder = constructor.newEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder")); - ByteToMessageDecoder decoder = constructor.newDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder")); - BukkitPacketHandler chunkHandler = new BukkitPacketHandler(info); + HandlerConstructor constructor = ClassGenerator.getConstructor(); + MessageToByteEncoder encoder = constructor.newEncodeHandler(connection, (MessageToByteEncoder) channel.pipeline().get("encoder")); + ByteToMessageDecoder decoder = constructor.newDecodeHandler(connection, (ByteToMessageDecoder) channel.pipeline().get("decoder")); - socketChannel.pipeline().replace("encoder", "encoder", encoder); - socketChannel.pipeline().replace("decoder", "decoder", decoder); - socketChannel.pipeline().addAfter("packet_handler", "viaversion_packet_handler", chunkHandler); + BukkitPacketHandler chunkHandler = new BukkitPacketHandler(connection); + channel.pipeline().replace("encoder", "encoder", encoder); + channel.pipeline().replace("decoder", "decoder", decoder); + channel.pipeline().addAfter("packet_handler", "viaversion_packet_handler", chunkHandler); } } diff --git a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaInjector.java b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaInjector.java index 97f8dfa26..371dc4453 100644 --- a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaInjector.java +++ b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaInjector.java @@ -45,11 +45,15 @@ public class BukkitViaInjector implements ViaInjector { private final List injectedFutures = new ArrayList<>(); private final List> injectedLists = new ArrayList<>(); - private final boolean modernPaper = hasServerProtocolMethod(); private boolean protocolLib; @Override public void inject() throws Exception { + if (PaperViaInjector.PAPER_INJECTION_METHOD) { + PaperViaInjector.setPaperChannelInitializeListener(); + return; + } + try { Object connection = getServerConnection(); if (connection == null) { @@ -189,7 +193,7 @@ public class BukkitViaInjector implements ViaInjector { @Override public int getServerProtocolVersion() throws Exception { - if (modernPaper) { + if (PaperViaInjector.PAPER_PROTOCOL_METHOD) { // *Trust me, it's safe* return Bukkit.getUnsafe().getProtocolVersion(); } @@ -266,6 +270,7 @@ public class BukkitViaInjector implements ViaInjector { } public static boolean isBinded() { + if (PaperViaInjector.PAPER_INJECTION_METHOD) return true; try { Object connection = getServerConnection(); if (connection == null) { @@ -354,6 +359,8 @@ public class BukkitViaInjector implements ViaInjector { } public static void patchLists() throws Exception { + if (PaperViaInjector.PAPER_INJECTION_METHOD) return; + Object connection = getServerConnection(); if (connection == null) { Via.getPlatform().getLogger().warning("We failed to find the core component 'ServerConnection', please file an issue on our GitHub."); @@ -375,17 +382,4 @@ public class BukkitViaInjector implements ViaInjector { public void setProtocolLib(boolean protocolLib) { this.protocolLib = protocolLib; } - - public boolean isModernPaper() { - return modernPaper; - } - - private static boolean hasServerProtocolMethod() { - try { - Class.forName("org.bukkit.UnsafeValues").getDeclaredMethod("getProtocolVersion"); - return true; - } catch (ReflectiveOperationException e) { - return false; - } - } } \ No newline at end of file diff --git a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/PaperViaInjector.java b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/PaperViaInjector.java new file mode 100644 index 000000000..bdac563c6 --- /dev/null +++ b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/PaperViaInjector.java @@ -0,0 +1,51 @@ +package com.viaversion.viaversion.bukkit.platform; + +import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer; +import io.netty.channel.Channel; +import net.kyori.adventure.key.Key; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +public final class PaperViaInjector { + public static final boolean PAPER_INJECTION_METHOD = hasPaperInjectionMethod(); + public static final boolean PAPER_PROTOCOL_METHOD = hasServerProtocolMethod(); + + private PaperViaInjector() { + } + + public static void setPaperChannelInitializeListener() throws ReflectiveOperationException { + // Call io.papermc.paper.network.ChannelInitializeListenerHolder.addListener(net.kyori.adventure.key.Key, io.papermc.paper.network.ChannelInitializeListener) + // Create an interface proxy of ChannelInitializeListener + Class listenerClass = Class.forName("io.papermc.paper.network.ChannelInitializeListener"); + Object channelInitializeListener = Proxy.newProxyInstance(BukkitViaInjector.class.getClassLoader(), new Class[]{listenerClass}, (proxy, method, args) -> { + if (method.getName().equals("afterInitChannel")) { + BukkitChannelInitializer.afterChannelInitialize((Channel) args[0]); + return null; + } + return method.invoke(proxy, args); + }); + + Class holderClass = Class.forName("io.papermc.paper.network.ChannelInitializeListenerHolder"); + Method addListenerMethod = holderClass.getDeclaredMethod("addListener", Key.class, listenerClass); + addListenerMethod.invoke(null, Key.key("viaversion", "injector"), channelInitializeListener); + } + + private static boolean hasServerProtocolMethod() { + try { + Class.forName("org.bukkit.UnsafeValues").getDeclaredMethod("getProtocolVersion"); + return true; + } catch (ReflectiveOperationException e) { + return false; + } + } + + private static boolean hasPaperInjectionMethod() { + try { + Class.forName("io.papermc.paper.network.ChannelInitializeListener"); + return true; + } catch (ReflectiveOperationException e) { + return false; + } + } +}