From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Fri, 9 May 2025 16:55:34 +0900 Subject: [PATCH] Async switch connection state diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java index f3e9de8716f5e1a72ec465ee897c8f0413f7b1c3..3dce0665e7438d2994a86450e31fb2a10431df9b 100644 --- a/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java @@ -342,6 +342,11 @@ public class Connection extends SimpleChannelInboundHandler> { if (protocolInfo.flow() != this.getReceiving()) { throw new IllegalStateException("Invalid inbound protocol: " + protocolInfo.id()); } else { + // Leaf start - Async switch connection state + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled && ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) { + this.channel.config().setAutoRead(false); + } + // Leaf end - Async switch connection state this.packetListener = packetInfo; this.disconnectListener = null; UnconfiguredPipelineHandler.InboundConfigurationTask inboundConfigurationTask = UnconfiguredPipelineHandler.setupInboundProtocol(protocolInfo); @@ -351,7 +356,14 @@ public class Connection extends SimpleChannelInboundHandler> { inboundConfigurationTask = inboundConfigurationTask.andThen(context -> context.pipeline().addAfter("decoder", "bundler", packetBundlePacker)); } - syncAfterConfigurationChange(this.channel.writeAndFlush(inboundConfigurationTask)); + // Leaf start - Async switch connection state + var cf = this.channel.writeAndFlush(inboundConfigurationTask); + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled && ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) { + cf.addListener((ChannelFutureListener) Connection::syncAfterConfigurationChange); + return; + } + syncAfterConfigurationChange(cf); + // Leaf end - Async switch connection state } } @@ -373,6 +385,31 @@ public class Connection extends SimpleChannelInboundHandler> { } } + // Leaf start - Async switch connection state + public @Nullable ChannelFuture setupOutboundProtocolAsync(ProtocolInfo protocolInfo) { + if (protocolInfo.flow() != this.getSending()) { + throw new IllegalStateException("Invalid outbound protocol: " + protocolInfo.id()); + } else { + UnconfiguredPipelineHandler.OutboundConfigurationTask outboundConfigurationTask = UnconfiguredPipelineHandler.setupOutboundProtocol(protocolInfo); + BundlerInfo bundlerInfo = protocolInfo.bundlerInfo(); + if (bundlerInfo != null) { + PacketBundleUnpacker packetBundleUnpacker = new PacketBundleUnpacker(bundlerInfo); + outboundConfigurationTask = outboundConfigurationTask.andThen( + context -> context.pipeline().addAfter("encoder", "unbundler", packetBundleUnpacker) + ); + } + + boolean flag = protocolInfo.id() == ConnectionProtocol.LOGIN; + var cf = this.channel.writeAndFlush(outboundConfigurationTask.andThen(context -> this.sendLoginDisconnect = flag)); + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) { + cf.addListener((ChannelFutureListener) Connection::syncAfterConfigurationChange); + return cf; + } + return null; + } + } + // Leaf end - Async switch connection state + public void setListenerForServerboundHandshake(PacketListener packetListener) { if (this.packetListener != null) { throw new IllegalStateException("Listener already set"); diff --git a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java index 2e9eb04c7c4342393c05339906c267bca9ff29b1..53b9daa909c2b89046d5af515e17afe09ea7015a 100644 --- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java @@ -140,11 +140,34 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis } } + private volatile boolean changingState = false; // Leaf - Async switch connection state @Override public void handleConfigurationFinished(ServerboundFinishConfigurationPacket packet) { + // Leaf start - Async switch connection state + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled && !changingState) { + changingState = true; + this.finishCurrentTask(JoinWorldTask.TYPE); + this.connection.setupOutboundProtocolAsync(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()))).addListener(l -> { + try { + PacketUtils.ensureRunningOnSameThread(packet, this, this.server); + } catch (net.minecraft.server.RunningOnDifferentThreadException ignored) { + } catch ( + io.papermc.paper.util.ServerStopRejectedExecutionException ignored) { // Paper - do not prematurely disconnect players on stop + } catch (java.util.concurrent.RejectedExecutionException var6) { + this.connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown")); + } catch (ClassCastException var7) { + LOGGER.error("Received {} that couldn't be processed", packet.getClass(), var7); + this.connection.disconnect(Component.translatable("multiplayer.disconnect.invalid_packet")); + } + }); + return; + } PacketUtils.ensureRunningOnSameThread(packet, this, this.server); - this.finishCurrentTask(JoinWorldTask.TYPE); - this.connection.setupOutboundProtocol(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()))); + if (!org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) { + this.finishCurrentTask(JoinWorldTask.TYPE); + this.connection.setupOutboundProtocol(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()))); + } + // Leaf end - Async switch connection state try { PlayerList playerList = this.server.getPlayerList(); diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java index 6b0b0ccc18a5da05685867656705e1fcf94b5891..889bab9613fb32d239bb0613db4a900a442116a3 100644 --- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -493,11 +493,31 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, this.disconnect(ServerCommonPacketListenerImpl.DISCONNECT_UNEXPECTED_QUERY); } + private volatile boolean changingState = false; // Leaf - Async switch connection state @Override public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket packet) { + // Leaf start - Async switch connection state + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled && !changingState) { + changingState = true; + this.connection.setupOutboundProtocolAsync(ConfigurationProtocols.CLIENTBOUND).addListener(l -> { + try { + net.minecraft.network.protocol.PacketUtils.ensureRunningOnSameThread(packet, this, this.server); + } catch (net.minecraft.server.RunningOnDifferentThreadException ignored) { + } catch ( + io.papermc.paper.util.ServerStopRejectedExecutionException ignored) { // Paper - do not prematurely disconnect players on stop + } catch (java.util.concurrent.RejectedExecutionException var6) { + this.connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown")); + } catch (ClassCastException var7) { + LOGGER.error("Received {} that couldn't be processed", packet.getClass(), var7); + this.connection.disconnect(Component.translatable("multiplayer.disconnect.invalid_packet")); + } + }); + return; + } + // Leaf end - Async switch connection state net.minecraft.network.protocol.PacketUtils.ensureRunningOnSameThread(packet, this, this.server); // CraftBukkit Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet"); - this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND); + if (!org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND); // Leaf - Async switch connection state CommonListenerCookie commonListenerCookie = CommonListenerCookie.createInitial(Objects.requireNonNull(this.authenticatedProfile), this.transferred); ServerConfigurationPacketListenerImpl serverConfigurationPacketListenerImpl = new ServerConfigurationPacketListenerImpl( this.server, this.connection, commonListenerCookie, this.player // CraftBukkit