diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index 5dcfbd0f8..9f7e21579 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -178,9 +178,8 @@ public class GeyserSpigotInjector extends GeyserInjector { MinecraftProtocol protocol = new MinecraftProtocol(); LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().address(), bootstrap.getGeyserConfig().getRemote().port(), this.serverSocketAddress, - InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper()); + InetAddress.getLoopbackAddress().getHostAddress(), protocol, Runnable::run); session.connect(); - session.disconnect(""); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 0a8222f8d..065c1f0cc 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -414,9 +414,6 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { } } - // Ensure that PacketLib does not create an event loop for handling packets; we'll do that ourselves - TcpSession.USE_EVENT_LOOP_FOR_PACKETS = false; - pendingMicrosoftAuthentication = new PendingMicrosoftAuthentication(config.getPendingAuthenticationTimeout()); this.newsHandler = new NewsHandler(BRANCH, this.buildNumber()); diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 378dc5078..c762cf5d3 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -28,7 +28,7 @@ package org.geysermc.geyser.network; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; -import org.cloudburstmc.protocol.bedrock.codec.v765.Bedrock_v765; +import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec; import org.geysermc.mcprotocollib.protocol.codec.PacketCodec; @@ -46,9 +46,8 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v765.CODEC.toBuilder() + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v766.CODEC.toBuilder() .minecraftVersion("1.21.50") - .protocolVersion(766) .build()); /** diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 0cf161c6a..dfebb93dc 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -96,7 +96,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } private PacketSignal translateAndDefault(BedrockPacket packet) { - Registries.BEDROCK_PACKET_TRANSLATORS.translate(packet.getClass(), packet, session); + Registries.BEDROCK_PACKET_TRANSLATORS.translate(packet.getClass(), packet, session, false); return PacketSignal.HANDLED; // PacketSignal.UNHANDLED will log a WARN publicly } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index 739c1c25e..3b86a0bf9 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -59,6 +59,7 @@ import java.net.Inet4Address; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; /** @@ -72,11 +73,11 @@ public final class LocalSession extends TcpSession { private final String clientIp; private final PacketCodecHelper codecHelper; - public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper) { - super(host, port, protocol); + public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, Executor packetHandlerExecutor) { + super(host, port, protocol, packetHandlerExecutor); this.targetAddress = targetAddress; this.clientIp = clientIp; - this.codecHelper = codecHelper; + this.codecHelper = protocol.createHelper(); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index b31f2b4f0..e81935edf 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -56,15 +56,15 @@ public class PacketTranslatorRegistry extends AbstractMappedRegistry boolean translate(Class clazz, P packet, GeyserSession session) { + public

boolean translate(Class clazz, P packet, GeyserSession session, boolean canRunImmediately) { if (session.getUpstream().isClosed() || session.isClosed()) { return false; } PacketTranslator

translator = (PacketTranslator

) this.mappings.get(clazz); if (translator != null) { - EventLoop eventLoop = session.getEventLoop(); - if (!translator.shouldExecuteInEventLoop() || eventLoop.inEventLoop()) { + EventLoop eventLoop = session.getTickEventLoop(); + if (canRunImmediately || !translator.shouldExecuteInEventLoop() || eventLoop.inEventLoop()) { translate0(session, translator, packet); } else { eventLoop.execute(() -> translate0(session, translator, packet)); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java index 46a820c16..e86bfe7c4 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java @@ -45,7 +45,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.nbt.NbtUtils; import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; -import org.cloudburstmc.protocol.bedrock.codec.v765.Bedrock_v765; +import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -124,7 +124,7 @@ public final class BlockRegistryPopulator { private static void registerBedrockBlocks() { var blockMappers = ImmutableMap., Remapper>builder() .put(ObjectIntPair.of("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()), Conversion766_748::remapBlock) - .put(ObjectIntPair.of("1_21_50", Bedrock_v765.CODEC.getProtocolVersion()), tag -> tag) + .put(ObjectIntPair.of("1_21_50", Bedrock_v766.CODEC.getProtocolVersion()), tag -> tag) .build(); // We can keep this strong as nothing should be garbage collected diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java index 7c636cd24..f7b45ba1d 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java @@ -46,7 +46,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.nbt.NbtUtils; import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; -import org.cloudburstmc.protocol.bedrock.codec.v765.Bedrock_v765; +import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; @@ -108,7 +108,6 @@ public class ItemRegistryPopulator { } public static void populate() { - Map itemFallbacks = new HashMap<>(); itemFallbacks.put(Items.PALE_OAK_PLANKS, Items.BIRCH_PLANKS); itemFallbacks.put(Items.PALE_OAK_FENCE, Items.BIRCH_FENCE); @@ -147,7 +146,7 @@ public class ItemRegistryPopulator { List paletteVersions = new ArrayList<>(2); paletteVersions.add(new PaletteVersion("1_21_40", Bedrock_v748.CODEC.getProtocolVersion(), itemFallbacks, (item, mapping) -> mapping)); - paletteVersions.add(new PaletteVersion("1_21_50", Bedrock_v765.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_21_50", Bedrock_v766.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/TagRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/TagRegistryPopulator.java index dd654531a..bf1ed6194 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/TagRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/TagRegistryPopulator.java @@ -34,7 +34,7 @@ import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.ObjectIntPair; import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; -import org.cloudburstmc.protocol.bedrock.codec.v765.Bedrock_v765; +import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.item.type.Item; @@ -68,7 +68,7 @@ public final class TagRegistryPopulator { List> paletteVersions = List.of( ObjectIntPair.of("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()), - ObjectIntPair.of("1_21_50", Bedrock_v765.CODEC.getProtocolVersion()) + ObjectIntPair.of("1_21_50", Bedrock_v766.CODEC.getProtocolVersion()) ); Type type = new TypeToken>>() {}.getType(); diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 94b371668..d6fe6739b 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -253,7 +253,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * The loop where all packets and ticking is processed to prevent concurrency issues. * If this is manually called, ensure that any exceptions are properly handled. */ - private final EventLoop eventLoop; + private final EventLoop tickEventLoop; @Setter private AuthData authData; private BedrockClientData clientData; @@ -658,10 +658,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private MinecraftProtocol protocol; - public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop eventLoop) { + public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop tickEventLoop) { this.geyser = geyser; this.upstream = new UpstreamSession(bedrockServerSession); - this.eventLoop = eventLoop; + this.tickEventLoop = tickEventLoop; this.erosionHandler = new GeyserboundHandshakePacketHandler(this); @@ -952,17 +952,17 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { boolean floodgate = this.remoteServer.authType() == AuthType.FLOODGATE; // Start ticking - tickThread = eventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS); + tickThread = tickEventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS); TcpSession downstream; if (geyser.getBootstrap().getSocketAddress() != null) { // We're going to connect through the JVM and not through TCP downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(), geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(), - this.protocol, this.protocol.createHelper()); + this.protocol, tickEventLoop); this.downstream = new DownstreamSession(downstream); } else { - downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), this.protocol); + downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), "0.0.0.0", 0, this.protocol, null, tickEventLoop); this.downstream = new DownstreamSession(downstream); boolean resolveSrv = false; @@ -1148,7 +1148,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public void packetReceived(Session session, Packet packet) { - Registries.JAVA_PACKET_TRANSLATORS.translate(packet.getClass(), packet, GeyserSession.this); + Registries.JAVA_PACKET_TRANSLATORS.translate(packet.getClass(), packet, GeyserSession.this, true); } @Override @@ -1218,10 +1218,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * Moves task to the session event loop if already not in it. Otherwise, the task is automatically ran. */ public void ensureInEventLoop(Runnable runnable) { - if (eventLoop.inEventLoop()) { - runnable.run(); + if (tickEventLoop.inEventLoop()) { + executeRunnable(runnable); return; } + executeInEventLoop(runnable); } @@ -1229,15 +1230,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * Executes a task and prints a stack trace if an error occurs. */ public void executeInEventLoop(Runnable runnable) { - eventLoop.execute(() -> { - try { - runnable.run(); - } catch (ErosionCancellationException e) { - geyser.getLogger().debug("Caught ErosionCancellationException"); - } catch (Throwable e) { - geyser.getLogger().error("Error thrown in " + this.bedrockUsername() + "'s event loop!", e); - } - }); + tickEventLoop.execute(() -> executeRunnable(runnable)); } /** @@ -1246,19 +1239,25 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * The task will not run if the session is closed. */ public ScheduledFuture scheduleInEventLoop(Runnable runnable, long duration, TimeUnit timeUnit) { - return eventLoop.schedule(() -> { - try { + return tickEventLoop.schedule(() -> { + executeRunnable(() -> { if (!closed) { runnable.run(); } - } catch (ErosionCancellationException e) { - geyser.getLogger().debug("Caught ErosionCancellationException"); - } catch (Throwable e) { - geyser.getLogger().error("Error thrown in " + this.bedrockUsername() + "'s event loop!", e); - } + }); }, duration, timeUnit); } + private void executeRunnable(Runnable runnable) { + try { + runnable.run(); + } catch (ErosionCancellationException e) { + geyser.getLogger().debug("Caught ErosionCancellationException"); + } catch (Throwable e) { + geyser.getLogger().error("Error thrown in " + this.bedrockUsername() + "'s event loop!", e); + } + } + /** * Called every 50 milliseconds - one Minecraft tick. */ diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index be0f8560f..10d45658e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -131,11 +131,8 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + javaNbt); return; } - if (session.getEventLoop().inEventLoop()) { - putSkull(session, blockPosition, uuid, texturesProperty, blockState); - } else { - session.executeInEventLoop(() -> putSkull(session, blockPosition, uuid, texturesProperty, blockState)); - } + + session.ensureInEventLoop(() -> putSkull(session, blockPosition, uuid, texturesProperty, blockState)); }); // We don't have the textures yet, so we can't determine if a custom block was defined for this skull diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/PacketTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/PacketTranslator.java index d49cdd6d0..da5cd5cb0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/PacketTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/PacketTranslator.java @@ -34,6 +34,7 @@ public abstract class PacketTranslator { /** * Determines if this packet should be handled in the session's event loop. This should generally be true - * only when the packet has to be executed immediately should it be false. + * This method is only used for bedrock packets, java packets have a more sophisticated system through MCProtocolLib. */ public boolean shouldExecuteInEventLoop() { return true; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockEmoteTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockEmoteTranslator.java index 7a37aa72e..07af4ddc4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockEmoteTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockEmoteTranslator.java @@ -61,11 +61,8 @@ public class BedrockEmoteTranslator extends PacketTranslator { for (GeyserSession otherSession : session.getGeyser().getSessionManager().getSessions().values()) { if (otherSession != session) { if (otherSession.isClosed()) continue; - if (otherSession.getEventLoop().inEventLoop()) { - playEmote(otherSession, javaId, xuid, emote); - } else { - otherSession.executeInEventLoop(() -> playEmote(otherSession, javaId, xuid, emote)); - } + + otherSession.ensureInEventLoop(() -> playEmote(otherSession, javaId, xuid, emote)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java index 811449a99..c3108167b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java @@ -140,10 +140,4 @@ public class JavaCustomPayloadTranslator extends PacketTranslator { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 079309549..686064926 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,9 +10,9 @@ netty-io-uring = "0.0.25.Final-SNAPSHOT" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol-connection = "3.0.0.Beta5-20241121.192504-18" -protocol-common = "3.0.0.Beta5-20241121.192504-18" -protocol-codec = "3.0.0.Beta5-20241121.192504-18" +protocol-connection = "3.0.0.Beta5-20241203.200249-19" +protocol-common = "3.0.0.Beta5-20241203.200249-19" +protocol-codec = "3.0.0.Beta5-20241203.200249-19" raknet = "1.0.0.CR3-20240416.144209-1" minecraftauth = "4.1.1" mcprotocollib = "1.21.4-SNAPSHOT"