mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-29 20:09:17 +00:00
Originally vanilla logic is to use stream, and Mojang switched it to Guava's Collections2 since 1.21.4. It is much faster than using stream or manually adding to a new ArrayList. Manually adding to a new ArrayList requires allocating a new object array. However, the Collections2 lazy handles filter condition on iteration, so much better.
149 lines
9.5 KiB
Diff
149 lines
9.5 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: hayanesuru <hayanesuru@outlook.jp>
|
|
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 ce7013f14f78b0d28806c91679cfe56f02998ee6..d04531c7316fc13207a6b7312a82697eb51b96f7 100644
|
|
--- a/net/minecraft/network/Connection.java
|
|
+++ b/net/minecraft/network/Connection.java
|
|
@@ -344,6 +344,11 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
|
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);
|
|
@@ -353,7 +358,14 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
|
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
|
|
}
|
|
}
|
|
|
|
@@ -375,6 +387,31 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
|
}
|
|
}
|
|
|
|
+ // 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 c032d5beb28a2181697cc43bd295d839464d34ed..ed593fa6795f0fd05e38bba3b656dcd72e690af8 100644
|
|
--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
|
+++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
|
@@ -153,11 +153,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 f68923c5f6fbecd8f1c10a30dbd06ed0dfee8b84..4fe2fbe7b8329a0507ac94f42b0db78038c566d8 100644
|
|
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
@@ -416,11 +416,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
|