diff --git a/paper-server/patches/sources/net/minecraft/network/Connection.java.patch b/paper-server/patches/sources/net/minecraft/network/Connection.java.patch index 6a6e63cbe9..e65aa315ef 100644 --- a/paper-server/patches/sources/net/minecraft/network/Connection.java.patch +++ b/paper-server/patches/sources/net/minecraft/network/Connection.java.patch @@ -29,7 +29,7 @@ @Nullable private volatile PacketListener disconnectListener; @Nullable -@@ -114,7 +119,25 @@ +@@ -114,6 +119,24 @@ private volatile DisconnectionDetails delayedDisconnect; @Nullable BandwidthDebugMonitor bandwidthDebugMonitor; @@ -39,7 +39,7 @@ + public java.net.InetSocketAddress virtualHost; + private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); // Paper - Disable explicit network manager flushing + // Paper end - ++ + // Paper start - add utility methods + public final net.minecraft.server.level.ServerPlayer getPlayer() { + if (this.packetListener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl impl) { @@ -51,10 +51,9 @@ + return null; + } + // Paper end - add utility methods -+ + public Connection(PacketFlow side) { this.receiving = side; - } @@ -123,6 +146,9 @@ super.channelActive(channelhandlercontext); this.channel = channelhandlercontext.channel(); @@ -163,7 +162,23 @@ public void write(ChannelHandlerContext channelhandlercontext, Object object, ChannelPromise channelpromise) throws Exception { super.write(channelhandlercontext, object, channelpromise); } -@@ -661,6 +708,27 @@ +@@ -633,6 +680,7 @@ + } else { + this.channel.pipeline().addAfter("prepender", "compress", new CompressionEncoder(compressionThreshold)); + } ++ this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_THRESHOLD_SET); // Paper - Add Channel initialization listeners + } else { + if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) { + this.channel.pipeline().remove("decompress"); +@@ -641,6 +689,7 @@ + if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) { + this.channel.pipeline().remove("compress"); + } ++ this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_DISABLED); // Paper - Add Channel initialization listeners + } + + } +@@ -661,6 +710,27 @@ packetlistener1.onDisconnect(disconnectiondetails); } diff --git a/paper-server/patches/sources/net/minecraft/server/network/ServerConnectionListener.java.patch b/paper-server/patches/sources/net/minecraft/server/network/ServerConnectionListener.java.patch index a1db509244..276667192a 100644 --- a/paper-server/patches/sources/net/minecraft/server/network/ServerConnectionListener.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/network/ServerConnectionListener.java.patch @@ -27,7 +27,7 @@ public ServerConnectionListener(MinecraftServer server) { this.server = server; -@@ -100,16 +109,27 @@ +@@ -100,16 +109,28 @@ Connection.configureSerialization(channelpipeline, PacketFlow.SERVERBOUND, false, (BandwidthDebugMonitor) null); int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); @@ -39,6 +39,7 @@ + pending.add(object); // Paper - prevent blocking on adding a new connection while the server is ticking ((Connection) object).configurePacketHandler(channelpipeline); ((Connection) object).setListenerForServerboundHandshake(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); ++ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper - Add Channel initialization listeners } - }).group(eventloopgroup).localAddress(address, port)).bind().syncUninterruptibly()); + }).group(eventloopgroup).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit @@ -58,7 +59,7 @@ public SocketAddress startMemoryChannel() { List list = this.channels; ChannelFuture channelfuture; -@@ -153,6 +173,14 @@ +@@ -153,6 +174,14 @@ List list = this.connections; synchronized (this.connections) { @@ -73,7 +74,7 @@ Iterator iterator = this.connections.iterator(); while (iterator.hasNext()) { -@@ -176,6 +204,10 @@ +@@ -176,6 +205,10 @@ networkmanager.setReadOnly(); } } else { diff --git a/paper-server/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/paper-server/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java new file mode 100644 index 0000000000..88099df34c --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java @@ -0,0 +1,15 @@ +package io.papermc.paper.network; + +import io.netty.channel.Channel; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Internal API to register channel initialization listeners. + *

+ * This is not officially supported API and we make no guarantees to the existence or state of this interface. + */ +@FunctionalInterface +public interface ChannelInitializeListener { + + void afterInitChannel(@NonNull Channel channel); +} diff --git a/paper-server/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/paper-server/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java new file mode 100644 index 0000000000..30e62719e0 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java @@ -0,0 +1,74 @@ +package io.papermc.paper.network; + +import io.netty.channel.Channel; +import net.kyori.adventure.key.Key; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Internal API to register channel initialization listeners. + *

+ * This is not officially supported API and we make no guarantees to the existence or state of this class. + */ +public final class ChannelInitializeListenerHolder { + + private static final Map LISTENERS = new HashMap<>(); + private static final Map IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS); + + private ChannelInitializeListenerHolder() { + } + + /** + * Registers whether an initialization listener is registered under the given key. + * + * @param key key + * @return whether an initialization listener is registered under the given key + */ + public static boolean hasListener(@NonNull Key key) { + return LISTENERS.containsKey(key); + } + + /** + * Registers a channel initialization listener called after ServerConnection is initialized. + * + * @param key key + * @param listener initialization listeners + */ + public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) { + LISTENERS.put(key, listener); + } + + /** + * Removes and returns an initialization listener registered by the given key if present. + * + * @param key key + * @return removed initialization listener if present + */ + public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) { + return LISTENERS.remove(key); + } + + /** + * Returns an immutable map of registered initialization listeners. + * + * @return immutable map of registered initialization listeners + */ + public static @NonNull Map getListeners() { + return IMMUTABLE_VIEW; + } + + /** + * Calls the registered listeners with the given channel. + * + * @param channel channel + */ + public static void callListeners(@NonNull Channel channel) { + for (ChannelInitializeListener listener : LISTENERS.values()) { + listener.afterInitChannel(channel); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/network/ConnectionEvent.java b/paper-server/src/main/java/io/papermc/paper/network/ConnectionEvent.java new file mode 100644 index 0000000000..0d7e7db9e3 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/network/ConnectionEvent.java @@ -0,0 +1,10 @@ +package io.papermc.paper.network; + +/** + * Internal connection pipeline events. + */ +public enum ConnectionEvent { + + COMPRESSION_THRESHOLD_SET, + COMPRESSION_DISABLED +}