From 024ec3cd966a0875ef36642d8b45829bab1a2f8e Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Mon, 28 Oct 2024 17:27:29 +0800 Subject: [PATCH] fix: fix deadlock in finding world spawn point --- .../org/allaymc/server/world/AllayWorld.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/org/allaymc/server/world/AllayWorld.java b/server/src/main/java/org/allaymc/server/world/AllayWorld.java index 6ec32b20c..75a262798 100644 --- a/server/src/main/java/org/allaymc/server/world/AllayWorld.java +++ b/server/src/main/java/org/allaymc/server/world/AllayWorld.java @@ -161,20 +161,24 @@ protected void checkFirstTick() { } isFirstTick = true; - // Check spawn point - if (!isSafeStandingPos(new Position3i(worldData.getSpawnPoint(), getOverWorld()))) { - var newSpawnPoint = getOverWorld().findSuitableGroundPosAround(this::isSafeStandingPos, 0, 0, 32); - if (newSpawnPoint == null) { - log.warn("Cannot find a safe spawn point in the overworld dimension of world {}", worldData.getName()); - newSpawnPoint = new Vector3i(0, getOverWorld().getHeight(0, 0) + 1, 0); - } - worldData.setSpawnPoint(newSpawnPoint); - } - if (Server.SETTINGS.worldSettings().loadSpawnPointChunks()) { // Add spawn point chunk loader getOverWorld().getChunkService().addChunkLoader(new SpawnPointChunkLoader()); } + + // Shouldn't block world tick poll here, otherwise there will be a deadlock because + // Dimension#findSuitableGroundPosAround() -wait-> Dimension#getBlockState() -wait-> ChunkService#getOrLoadChunkSync() + // -wait-> WorldGenerator#generateChunk(), and WorldGenerator should be ticked in order to generate chunk normally + Thread.ofVirtual().name("World " + worldData.getName() + " Spawn Point Finding Thread").start(() -> { + if (!isSafeStandingPos(new Position3i(worldData.getSpawnPoint(), getOverWorld()))) { + var newSpawnPoint = getOverWorld().findSuitableGroundPosAround(this::isSafeStandingPos, 0, 0, 32); + if (newSpawnPoint == null) { + log.warn("Cannot find a safe spawn point in the overworld dimension of world {}", worldData.getName()); + newSpawnPoint = new Vector3i(0, getOverWorld().getHeight(0, 0) + 1, 0); + } + worldData.setSpawnPoint(newSpawnPoint); + } + }); } protected boolean isSafeStandingPos(Position3ic pos) {