From 4734ce20595bdc38608af54648142ed209c298ac Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 23 May 2021 15:55:01 -0400 Subject: [PATCH] Update MCProtocolLib + PacketLib (#2211) By updating these dependencies, we bring in a couple fixes that should improve network performance: Use TCP_NODELAY for the Java connection Use Epoll/KQueue if possible for the Java connection Only use one event loop for the Java connection Fix Netty dependencies so Spigot and BungeeCord can use native network types Currently, Geyser-Spigot pre-1.12 breaks with these changes. It is unlikely that this will be fixed. --- bootstrap/bungeecord/pom.xml | 15 +++++++-- bootstrap/spigot/pom.xml | 18 ++++++++--- .../platform/spigot/GeyserSpigotPlugin.java | 17 ++++++++++ bootstrap/velocity/pom.xml | 1 + connector/pom.xml | 4 +-- .../geysermc/connector/GeyserConnector.java | 15 +++++++++ .../network/session/GeyserSession.java | 31 +++++++++---------- .../network/session/cache/BookEditCache.java | 2 +- connector/src/main/resources/languages | 2 +- 9 files changed, 79 insertions(+), 26 deletions(-) diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml index 738c1ee1c..9cf8b4763 100644 --- a/bootstrap/bungeecord/pom.xml +++ b/bootstrap/bungeecord/pom.xml @@ -66,8 +66,10 @@ org.geysermc.platform.bungeecord.shaded.jackson - io.netty - org.geysermc.platform.bungeecord.shaded.netty + + io.netty.channel.kqueue + org.geysermc.platform.bungeecord.shaded.io.netty.channel.kqueue org.reflections @@ -98,6 +100,15 @@ com.google.code.gson:* org.yaml:* + io.netty:netty-transport-native-epoll:* + io.netty:netty-transport-native-unix-common:* + io.netty:netty-handler:* + io.netty:netty-common:* + io.netty:netty-buffer:* + io.netty:netty-resolver:* + io.netty:netty-transport:* + io.netty:netty-codec:* + io.netty:netty-resolver-dns:* diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml index 12c8292e9..3dd25312c 100644 --- a/bootstrap/spigot/pom.xml +++ b/bootstrap/spigot/pom.xml @@ -68,10 +68,6 @@ - - io.netty - org.geysermc.platform.spigot.shaded.netty - it.unimi.dsi.fastutil org.geysermc.platform.spigot.shaded.fastutil @@ -109,6 +105,20 @@ com.google.code.gson:* org.yaml:* + + + io.netty:netty-transport-native-epoll:* + io.netty:netty-transport-native-unix-common:* + io.netty:netty-transport-native-kqueue:* + io.netty:netty-handler:* + io.netty:netty-common:* + io.netty:netty-buffer:* + io.netty:netty-resolver:* + io.netty:netty-transport:* + io.netty:netty-codec:* + io.netty:netty-codec-dns:* + io.netty:netty-resolver-dns:* + io.netty:netty-resolver-dns-native-macos:* diff --git a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java index 671ad18cf..b45cb7000 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java @@ -95,6 +95,23 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { ex.printStackTrace(); } + try { + // Required for the Cloudburst Network dependency to initialize. + Class.forName("io.netty.channel.kqueue.KQueue"); + } catch (ClassNotFoundException e) { + // While we could support these older versions, the downside is not having KQueue working at all + // And since there are alternative ways to get Geyser working for these aging platforms, it's not worth it. + getLogger().severe("*********************************************"); + getLogger().severe(""); + getLogger().severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.unsupported_server.header")); + getLogger().severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.12.2")); + getLogger().severe(""); + getLogger().severe("*********************************************"); + + Bukkit.getPluginManager().disablePlugin(this); + return; + } + // By default this should be localhost but may need to be changed in some circumstances if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) { geyserConfig.setAutoconfiguredRemote(true); diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml index bcc62ed4c..b9f2e64f2 100644 --- a/bootstrap/velocity/pom.xml +++ b/bootstrap/velocity/pom.xml @@ -103,6 +103,7 @@ io.netty:netty-resolver:* io.netty:netty-transport:* io.netty:netty-codec:* + io.netty:netty-codec-haproxy:* org.slf4j:* org.ow2.asm:* diff --git a/connector/pom.xml b/connector/pom.xml index 7d4bae7a0..9feb717b9 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -122,7 +122,7 @@ com.github.steveice10 mcprotocollib - 26201a4 + 8c204eb compile @@ -142,7 +142,7 @@ com.github.GeyserMC PacketLib - b77a427 + 6e5dea9 compile diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index d2caac216..3f82889f5 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -31,6 +31,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.nukkitx.network.raknet.RakNetConstants; import com.nukkitx.network.util.EventLoops; import com.nukkitx.protocol.bedrock.BedrockServer; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.kqueue.KQueue; import lombok.Getter; import lombok.Setter; import org.geysermc.common.PlatformType; @@ -203,6 +205,19 @@ public class GeyserConnector { EventLoops.commonGroup(), enableProxyProtocol ); + + if (config.isDebugMode()) { + logger.debug("EventLoop type: " + EventLoops.getChannelType()); + if (EventLoops.getChannelType() == EventLoops.ChannelType.NIO) { + if (System.getProperties().contains("disableNativeEventLoop")) { + logger.debug("EventLoop type is NIO because native event loops are disabled."); + } else { + logger.debug("Reason for no Epoll: " + Epoll.unavailabilityCause().toString()); + logger.debug("Reason for no KQueue: " + KQueue.unavailabilityCause().toString()); + } + } + } + bedrockServer.setHandler(new ConnectorServerEventHandler(this)); bedrockServer.bind().whenComplete((avoid, throwable) -> { if (throwable == null) { diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 3748a3ba2..1130356c1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -46,10 +46,9 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTelepo import com.github.steveice10.mc.protocol.packet.login.client.LoginPluginResponsePacket; import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket; import com.github.steveice10.packetlib.BuiltinFlags; -import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.event.session.*; import com.github.steveice10.packetlib.packet.Packet; -import com.github.steveice10.packetlib.tcp.TcpSessionFactory; +import com.github.steveice10.packetlib.tcp.TcpClientSession; import com.nukkitx.math.GenericMath; import com.nukkitx.math.vector.*; import com.nukkitx.protocol.bedrock.BedrockPacket; @@ -118,7 +117,7 @@ public class GeyserSession implements CommandSender { private final GeyserConnector connector; private final UpstreamSession upstream; - private Client downstream; + private TcpClientSession downstream; @Setter private AuthData authData; @Setter @@ -587,7 +586,7 @@ public class GeyserSession implements CommandSender { authenticationService.setPassword(password); authenticationService.login(); - protocol = new MinecraftProtocol(authenticationService); + protocol = new MinecraftProtocol(authenticationService.getSelectedProfile(), authenticationService.getAccessToken()); } else { protocol = new MinecraftProtocol(username); } @@ -645,7 +644,7 @@ public class GeyserSession implements CommandSender { } try { msaAuthenticationService.login(); - protocol = new MinecraftProtocol(msaAuthenticationService); + protocol = new MinecraftProtocol(msaAuthenticationService.getSelectedProfile(), msaAuthenticationService.getAccessToken()); connectDownstream(); } catch (RequestException e) { @@ -685,17 +684,17 @@ public class GeyserSession implements CommandSender { // Start ticking tickThread = connector.getGeneralThreadPool().scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS); - downstream = new Client(this.remoteAddress, this.remotePort, protocol, new TcpSessionFactory()); + downstream = new TcpClientSession(this.remoteAddress, this.remotePort, protocol); disableSrvResolving(); if (connector.getConfig().getRemote().isUseProxyProtocol()) { - downstream.getSession().setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true); - downstream.getSession().setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress()); + downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true); + downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress()); } if (connector.getConfig().isForwardPlayerPing()) { // Let Geyser handle sending the keep alive - downstream.getSession().setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false); + downstream.setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false); } - downstream.getSession().addListener(new SessionAdapter() { + downstream.addListener(new SessionAdapter() { @Override public void packetSending(PacketSendingEvent event) { //todo move this somewhere else @@ -818,15 +817,15 @@ public class GeyserSession implements CommandSender { if (!daylightCycle) { setDaylightCycle(true); } - downstream.getSession().connect(); + downstream.connect(); connector.addPlayer(this); } public void disconnect(String reason) { if (!closed) { loggedIn = false; - if (downstream != null && downstream.getSession() != null) { - downstream.getSession().disconnect(reason); + if (downstream != null) { + downstream.disconnect(reason); } if (upstream != null && !upstream.isClosed()) { connector.getPlayers().remove(this); @@ -954,7 +953,7 @@ public class GeyserSession implements CommandSender { * Will be overwritten for GeyserConnect. */ protected void disableSrvResolving() { - this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false); + this.downstream.setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false); } @Override @@ -1210,8 +1209,8 @@ public class GeyserSession implements CommandSender { * @param packet the java edition packet from MCProtocolLib */ public void sendDownstreamPacket(Packet packet) { - if (downstream != null && downstream.getSession() != null && (protocol.getSubProtocol().equals(SubProtocol.GAME) || packet.getClass() == LoginPluginResponsePacket.class)) { - downstream.getSession().send(packet); + if (downstream != null && (protocol.getSubProtocol().equals(SubProtocol.GAME) || packet.getClass() == LoginPluginResponsePacket.class)) { + downstream.send(packet); } else { connector.getLogger().debug("Tried to send downstream packet " + packet.getClass().getSimpleName() + " before connected to the server"); } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/BookEditCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/BookEditCache.java index c82645dbf..cb3737895 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/BookEditCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/BookEditCache.java @@ -68,7 +68,7 @@ public class BookEditCache { packet = null; return; } - session.getDownstream().getSession().send(packet); + session.sendDownstreamPacket(packet); packet = null; lastBookUpdate = System.currentTimeMillis(); } diff --git a/connector/src/main/resources/languages b/connector/src/main/resources/languages index 9b08df518..e1e8fd6c2 160000 --- a/connector/src/main/resources/languages +++ b/connector/src/main/resources/languages @@ -1 +1 @@ -Subproject commit 9b08df51898fd71ee24e7accdfbe56f164b5c539 +Subproject commit e1e8fd6c2b8abf366e60085c23a55a2c943806ae