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 a3402a752b..9f7e21579d 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,7 +178,7 @@ private void workAroundWeirdBug(GeyserBootstrap bootstrap) { 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(); } diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 0a8222f8d7..065c1f0cc6 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 @@ private void startInstance() { } } - // 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/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 0cf161c6aa..dfebb93dc7 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 UpstreamPacketHandler(GeyserImpl geyser, GeyserSession session) { } 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 739c1c25ec..3b86a0bf9f 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.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 b31f2b4f00..e81935edfa 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 @@ protected PacketTranslatorRegistry() { } @SuppressWarnings("unchecked") - public
boolean translate(Class extends P> clazz, P packet, GeyserSession session) { + public
boolean translate(Class extends P> 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/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
index cfb981b7d1..b4a8e6203f 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;
@@ -653,10 +653,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);
@@ -947,17 +947,17 @@ private void connectDownstream() {
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;
@@ -1143,7 +1143,7 @@ public void disconnected(DisconnectedEvent event) {
@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
@@ -1213,10 +1213,11 @@ public void disconnect(String reason) {
* 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);
}
@@ -1224,15 +1225,7 @@ public void ensureInEventLoop(Runnable runnable) {
* 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));
}
/**
@@ -1241,19 +1234,25 @@ public void executeInEventLoop(Runnable runnable) {
* 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 be0f8560fa..10d45658ea 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 @@ private static UUID getUUID(NbtMap profile) {
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 d49cdd6d08..da5cd5cb0a 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