--- a/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java @@ -82,13 +82,13 @@ marker.add(Connection.PACKET_MARKER); }); public static final Supplier NETWORK_WORKER_GROUP = Suppliers.memoize(() -> { - return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build()); + return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()); // Paper }); public static final Supplier NETWORK_EPOLL_WORKER_GROUP = Suppliers.memoize(() -> { - return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Client IO #%d").setDaemon(true).build()); + return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Client IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()); // Paper }); public static final Supplier LOCAL_WORKER_GROUP = Suppliers.memoize(() -> { - return new DefaultEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).build()); + return new DefaultEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()); // Paper }); private static final ProtocolInfo INITIAL_PROTOCOL = HandshakeProtocols.SERVERBOUND; private final PacketFlow receiving; @@ -96,6 +96,11 @@ private final Queue> pendingActions = Queues.newConcurrentLinkedQueue(); public Channel channel; public SocketAddress address; + // Spigot Start + public java.util.UUID spoofedUUID; + public com.mojang.authlib.properties.Property[] spoofedProfile; + public boolean preparing = true; + // Spigot End @Nullable private volatile PacketListener disconnectListener; @Nullable @@ -114,7 +119,25 @@ private volatile DisconnectionDetails delayedDisconnect; @Nullable BandwidthDebugMonitor bandwidthDebugMonitor; + public String hostname = ""; // CraftBukkit - add field + // Paper start - NetworkClient implementation + public int protocolVersion; + 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) { + return impl.player; + } else if (this.packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl impl) { + org.bukkit.craftbukkit.entity.CraftPlayer player = impl.getCraftPlayer(); + return player == null ? null : player.getHandle(); + } + 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(); this.address = this.channel.remoteAddress(); + // Spigot Start + this.preparing = false; + // Spigot End if (this.delayedDisconnect != null) { this.disconnect(this.delayedDisconnect); } @@ -176,6 +202,7 @@ } } + if (net.minecraft.server.MinecraftServer.getServer().isDebugging()) io.papermc.paper.util.TraceUtil.printStackTrace(throwable); // Spigot // Paper } protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet packet) { @@ -205,7 +232,7 @@ } private static void genericsFtw(Packet packet, PacketListener listener) { - packet.handle(listener); + packet.handle((T) listener); // CraftBukkit - decompile error } private void validateListener(ProtocolInfo state, PacketListener listener) { @@ -431,7 +458,7 @@ } if (this.channel != null) { - this.channel.flush(); + if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - Disable explicit network manager flushing; we don't need to explicit flush here, but allow opt in incase issues are found to a better version } if (this.tickCount++ % 20 == 0) { @@ -464,12 +491,15 @@ } public void disconnect(DisconnectionDetails disconnectionInfo) { + // Spigot Start + this.preparing = false; + // Spigot End if (this.channel == null) { this.delayedDisconnect = disconnectionInfo; } if (this.isConnected()) { - this.channel.close().awaitUninterruptibly(); + this.channel.close(); // We can't wait as this may be called from an event loop. this.disconnectionDetails = disconnectionInfo; } @@ -537,7 +567,7 @@ } public void configurePacketHandler(ChannelPipeline pipeline) { - pipeline.addLast("hackfix", new ChannelOutboundHandlerAdapter(this) { + pipeline.addLast("hackfix", new ChannelOutboundHandlerAdapter() { // CraftBukkit - decompile error public void write(ChannelHandlerContext channelhandlercontext, Object object, ChannelPromise channelpromise) throws Exception { super.write(channelhandlercontext, object, channelpromise); } @@ -660,7 +690,28 @@ }); packetlistener1.onDisconnect(disconnectiondetails); + } + this.pendingActions.clear(); // Free up packet queue. + // Paper start - Add PlayerConnectionCloseEvent + final PacketListener packetListener = this.getPacketListener(); + if (packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) { + /* Player was logged in, either game listener or configuration listener */ + final com.mojang.authlib.GameProfile profile = commonPacketListener.getOwner(); + new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), + profile.getName(), ((InetSocketAddress) this.address).getAddress(), false).callEvent(); + } else if (packetListener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginListener) { + /* Player is login stage */ + switch (loginListener.state) { + case VERIFYING: + case WAITING_FOR_DUPE_DISCONNECT: + case PROTOCOL_SWITCHING: + case ACCEPTED: + final com.mojang.authlib.GameProfile profile = loginListener.authenticatedProfile; /* Should be non-null at this stage */ + new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(), + ((InetSocketAddress) this.address).getAddress(), false).callEvent(); + } } + // Paper end - Add PlayerConnectionCloseEvent } }