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.
This commit is contained in:
Camotoy 2021-05-23 15:55:01 -04:00 committed by GitHub
parent f831557919
commit 4734ce2059
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 79 additions and 26 deletions

View file

@ -66,8 +66,10 @@
<shadedPattern>org.geysermc.platform.bungeecord.shaded.jackson</shadedPattern> <shadedPattern>org.geysermc.platform.bungeecord.shaded.jackson</shadedPattern>
</relocation> </relocation>
<relocation> <relocation>
<pattern>io.netty</pattern> <!-- This is not used because relocating breaks natives, but we must include it
<shadedPattern>org.geysermc.platform.bungeecord.shaded.netty</shadedPattern> or else we get ClassDefNotFound -->
<pattern>io.netty.channel.kqueue</pattern>
<shadedPattern>org.geysermc.platform.bungeecord.shaded.io.netty.channel.kqueue</shadedPattern>
</relocation> </relocation>
<relocation> <relocation>
<pattern>org.reflections</pattern> <pattern>org.reflections</pattern>
@ -98,6 +100,15 @@
<excludes> <excludes>
<exclude>com.google.code.gson:*</exclude> <exclude>com.google.code.gson:*</exclude>
<exclude>org.yaml:*</exclude> <exclude>org.yaml:*</exclude>
<exclude>io.netty:netty-transport-native-epoll:*</exclude>
<exclude>io.netty:netty-transport-native-unix-common:*</exclude>
<exclude>io.netty:netty-handler:*</exclude>
<exclude>io.netty:netty-common:*</exclude>
<exclude>io.netty:netty-buffer:*</exclude>
<exclude>io.netty:netty-resolver:*</exclude>
<exclude>io.netty:netty-transport:*</exclude>
<exclude>io.netty:netty-codec:*</exclude>
<exclude>io.netty:netty-resolver-dns:*</exclude>
</excludes> </excludes>
</artifactSet> </artifactSet>
</configuration> </configuration>

View file

@ -68,10 +68,6 @@
</goals> </goals>
<configuration> <configuration>
<relocations> <relocations>
<relocation>
<pattern>io.netty</pattern>
<shadedPattern>org.geysermc.platform.spigot.shaded.netty</shadedPattern>
</relocation>
<relocation> <relocation>
<pattern>it.unimi.dsi.fastutil</pattern> <pattern>it.unimi.dsi.fastutil</pattern>
<shadedPattern>org.geysermc.platform.spigot.shaded.fastutil</shadedPattern> <shadedPattern>org.geysermc.platform.spigot.shaded.fastutil</shadedPattern>
@ -109,6 +105,20 @@
<excludes> <excludes>
<exclude>com.google.code.gson:*</exclude> <exclude>com.google.code.gson:*</exclude>
<exclude>org.yaml:*</exclude> <exclude>org.yaml:*</exclude>
<!-- We cannot shade Netty, or else native libraries will not load -->
<!-- Needed because older Spigot builds do not provide the haproxy module -->
<exclude>io.netty:netty-transport-native-epoll:*</exclude>
<exclude>io.netty:netty-transport-native-unix-common:*</exclude>
<exclude>io.netty:netty-transport-native-kqueue:*</exclude>
<exclude>io.netty:netty-handler:*</exclude>
<exclude>io.netty:netty-common:*</exclude>
<exclude>io.netty:netty-buffer:*</exclude>
<exclude>io.netty:netty-resolver:*</exclude>
<exclude>io.netty:netty-transport:*</exclude>
<exclude>io.netty:netty-codec:*</exclude>
<exclude>io.netty:netty-codec-dns:*</exclude>
<exclude>io.netty:netty-resolver-dns:*</exclude>
<exclude>io.netty:netty-resolver-dns-native-macos:*</exclude>
</excludes> </excludes>
</artifactSet> </artifactSet>
</configuration> </configuration>

View file

@ -95,6 +95,23 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
ex.printStackTrace(); 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 // By default this should be localhost but may need to be changed in some circumstances
if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) { if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) {
geyserConfig.setAutoconfiguredRemote(true); geyserConfig.setAutoconfiguredRemote(true);

View file

@ -103,6 +103,7 @@
<exclude>io.netty:netty-resolver:*</exclude> <exclude>io.netty:netty-resolver:*</exclude>
<exclude>io.netty:netty-transport:*</exclude> <exclude>io.netty:netty-transport:*</exclude>
<exclude>io.netty:netty-codec:*</exclude> <exclude>io.netty:netty-codec:*</exclude>
<exclude>io.netty:netty-codec-haproxy:*</exclude>
<exclude>org.slf4j:*</exclude> <exclude>org.slf4j:*</exclude>
<exclude>org.ow2.asm:*</exclude> <exclude>org.ow2.asm:*</exclude>
<!-- Exclude all Kyori dependencies except the legacy NBT serializer --> <!-- Exclude all Kyori dependencies except the legacy NBT serializer -->

View file

@ -122,7 +122,7 @@
<dependency> <dependency>
<groupId>com.github.steveice10</groupId> <groupId>com.github.steveice10</groupId>
<artifactId>mcprotocollib</artifactId> <artifactId>mcprotocollib</artifactId>
<version>26201a4</version> <version>8c204eb</version>
<scope>compile</scope> <scope>compile</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -142,7 +142,7 @@
<dependency> <dependency>
<groupId>com.github.GeyserMC</groupId> <groupId>com.github.GeyserMC</groupId>
<artifactId>PacketLib</artifactId> <artifactId>PacketLib</artifactId>
<version>b77a427</version> <version>6e5dea9</version>
<scope>compile</scope> <scope>compile</scope>
<exclusions> <exclusions>
<exclusion> <!-- Move this exclusion back to MCProtocolLib it gets the latest PacketLib --> <exclusion> <!-- Move this exclusion back to MCProtocolLib it gets the latest PacketLib -->

View file

@ -31,6 +31,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.nukkitx.network.raknet.RakNetConstants; import com.nukkitx.network.raknet.RakNetConstants;
import com.nukkitx.network.util.EventLoops; import com.nukkitx.network.util.EventLoops;
import com.nukkitx.protocol.bedrock.BedrockServer; import com.nukkitx.protocol.bedrock.BedrockServer;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.kqueue.KQueue;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.geysermc.common.PlatformType; import org.geysermc.common.PlatformType;
@ -203,6 +205,19 @@ public class GeyserConnector {
EventLoops.commonGroup(), EventLoops.commonGroup(),
enableProxyProtocol 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.setHandler(new ConnectorServerEventHandler(this));
bedrockServer.bind().whenComplete((avoid, throwable) -> { bedrockServer.bind().whenComplete((avoid, throwable) -> {
if (throwable == null) { if (throwable == null) {

View file

@ -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.client.LoginPluginResponsePacket;
import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket; import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket;
import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.BuiltinFlags;
import com.github.steveice10.packetlib.Client;
import com.github.steveice10.packetlib.event.session.*; import com.github.steveice10.packetlib.event.session.*;
import com.github.steveice10.packetlib.packet.Packet; 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.GenericMath;
import com.nukkitx.math.vector.*; import com.nukkitx.math.vector.*;
import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.BedrockPacket;
@ -118,7 +117,7 @@ public class GeyserSession implements CommandSender {
private final GeyserConnector connector; private final GeyserConnector connector;
private final UpstreamSession upstream; private final UpstreamSession upstream;
private Client downstream; private TcpClientSession downstream;
@Setter @Setter
private AuthData authData; private AuthData authData;
@Setter @Setter
@ -587,7 +586,7 @@ public class GeyserSession implements CommandSender {
authenticationService.setPassword(password); authenticationService.setPassword(password);
authenticationService.login(); authenticationService.login();
protocol = new MinecraftProtocol(authenticationService); protocol = new MinecraftProtocol(authenticationService.getSelectedProfile(), authenticationService.getAccessToken());
} else { } else {
protocol = new MinecraftProtocol(username); protocol = new MinecraftProtocol(username);
} }
@ -645,7 +644,7 @@ public class GeyserSession implements CommandSender {
} }
try { try {
msaAuthenticationService.login(); msaAuthenticationService.login();
protocol = new MinecraftProtocol(msaAuthenticationService); protocol = new MinecraftProtocol(msaAuthenticationService.getSelectedProfile(), msaAuthenticationService.getAccessToken());
connectDownstream(); connectDownstream();
} catch (RequestException e) { } catch (RequestException e) {
@ -685,17 +684,17 @@ public class GeyserSession implements CommandSender {
// Start ticking // Start ticking
tickThread = connector.getGeneralThreadPool().scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS); 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(); disableSrvResolving();
if (connector.getConfig().getRemote().isUseProxyProtocol()) { if (connector.getConfig().getRemote().isUseProxyProtocol()) {
downstream.getSession().setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true); downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
downstream.getSession().setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress()); downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
} }
if (connector.getConfig().isForwardPlayerPing()) { if (connector.getConfig().isForwardPlayerPing()) {
// Let Geyser handle sending the keep alive // 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 @Override
public void packetSending(PacketSendingEvent event) { public void packetSending(PacketSendingEvent event) {
//todo move this somewhere else //todo move this somewhere else
@ -818,15 +817,15 @@ public class GeyserSession implements CommandSender {
if (!daylightCycle) { if (!daylightCycle) {
setDaylightCycle(true); setDaylightCycle(true);
} }
downstream.getSession().connect(); downstream.connect();
connector.addPlayer(this); connector.addPlayer(this);
} }
public void disconnect(String reason) { public void disconnect(String reason) {
if (!closed) { if (!closed) {
loggedIn = false; loggedIn = false;
if (downstream != null && downstream.getSession() != null) { if (downstream != null) {
downstream.getSession().disconnect(reason); downstream.disconnect(reason);
} }
if (upstream != null && !upstream.isClosed()) { if (upstream != null && !upstream.isClosed()) {
connector.getPlayers().remove(this); connector.getPlayers().remove(this);
@ -954,7 +953,7 @@ public class GeyserSession implements CommandSender {
* Will be overwritten for GeyserConnect. * Will be overwritten for GeyserConnect.
*/ */
protected void disableSrvResolving() { protected void disableSrvResolving() {
this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false); this.downstream.setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false);
} }
@Override @Override
@ -1210,8 +1209,8 @@ public class GeyserSession implements CommandSender {
* @param packet the java edition packet from MCProtocolLib * @param packet the java edition packet from MCProtocolLib
*/ */
public void sendDownstreamPacket(Packet packet) { public void sendDownstreamPacket(Packet packet) {
if (downstream != null && downstream.getSession() != null && (protocol.getSubProtocol().equals(SubProtocol.GAME) || packet.getClass() == LoginPluginResponsePacket.class)) { if (downstream != null && (protocol.getSubProtocol().equals(SubProtocol.GAME) || packet.getClass() == LoginPluginResponsePacket.class)) {
downstream.getSession().send(packet); downstream.send(packet);
} else { } else {
connector.getLogger().debug("Tried to send downstream packet " + packet.getClass().getSimpleName() + " before connected to the server"); connector.getLogger().debug("Tried to send downstream packet " + packet.getClass().getSimpleName() + " before connected to the server");
} }

View file

@ -68,7 +68,7 @@ public class BookEditCache {
packet = null; packet = null;
return; return;
} }
session.getDownstream().getSession().send(packet); session.sendDownstreamPacket(packet);
packet = null; packet = null;
lastBookUpdate = System.currentTimeMillis(); lastBookUpdate = System.currentTimeMillis();
} }

@ -1 +1 @@
Subproject commit 9b08df51898fd71ee24e7accdfbe56f164b5c539 Subproject commit e1e8fd6c2b8abf366e60085c23a55a2c943806ae