From 0c760d925629e5745455519654063f25b79b611e Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 28 Oct 2026 03:56:54 -0500 Subject: [PATCH] Fix main thread deadlock when spawning rise-out-of-ground entities IrisEntity.spawn waited on J.sfut(...).get() to move the spawn point below ground. J.sfut schedules the task for the next main thread tick, so when spawn already runs on the main thread (ambient spawning in WorldEntitySpawner) the future can never complete and the server stops ticking. Run the check inline when already on the main thread. --- .../arcane/iris/world/entity/IrisEntity.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/art/arcane/iris/world/entity/IrisEntity.java b/core/src/main/java/art/arcane/iris/world/entity/IrisEntity.java index 7ffd950bc..c1c51c11c 100644 --- a/core/src/main/java/art/arcane/iris/world/entity/IrisEntity.java +++ b/core/src/main/java/art/arcane/iris/world/entity/IrisEntity.java @@ -278,14 +278,20 @@ public class IrisEntity extends IrisRegistrant implements NativeEntityOptions { } if (isSpawnEffectRiseOutOfGround()) { AtomicReference f = new AtomicReference<>(at); + Runnable riseStart = () -> { + if (Chunks.hasPlayersNearby(f.get())) { + Location b = f.get().clone(); + Location start = new Location(b.getWorld(), b.getX(), b.getY() - 5, b.getZ()); + f.set(start); + } + }; try { - J.sfut(() -> { - if (Chunks.hasPlayersNearby(f.get())) { - Location b = f.get().clone(); - Location start = new Location(b.getWorld(), b.getX(), b.getY() - 5, b.getZ()); - f.set(start); - } - }).get(); + // J.sfut schedules onto the next main thread tick, so waiting on it from the main thread never returns. + if (Bukkit.isPrimaryThread()) { + riseStart.run(); + } else { + J.sfut(riseStart).get(); + } } catch (InterruptedException e) { Thread.currentThread().interrupt(); IrisLogging.reportError("Iris entity spawn preparation was interrupted.", e);