Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -182,6 +_,7 @@
private final BlockMetadataStore blockMetadata = new BlockMetadataStore(this);
private final Object2IntOpenHashMap<SpawnCategory> spawnCategoryLimit = new Object2IntOpenHashMap<>();
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftWorld.DATA_TYPE_REGISTRY);
+ private static final ThreadLocal<Boolean> isInsideIsChunkGenerated = ThreadLocal.withInitial(() -> Boolean.FALSE); // ShreddedPaper - track recursive isChunkGenerated calls
// Paper start - void damage configuration
private boolean voidDamageEnabled;
private float voidDamageAmount;
@@ -240,7 +_,7 @@

@Override
Expand All @@ -40,7 +48,7 @@
warnUnsafeChunk("getting a faraway chunk", x, z); // Paper
net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) this.world.getChunk(x, z, ChunkStatus.FULL, true);
return new CraftChunk(chunk);
@@ -413,10 +_,12 @@
@@ -413,26 +_,37 @@
@Override
public boolean isChunkGenerated(int x, int z) {
// Paper start - Fix this method
Expand All @@ -51,11 +59,47 @@
return CraftWorld.this.isChunkGenerated(x, z);
- }, world.getChunkSource().mainThreadProcessor).join();
+ }, world.getChunkSource().tickingRegions.executorFor(RegionPos.forChunk(x, z))); // ShreddedPaper - regions
+ if (TickThread.isTickThread()) this.getHandle().getChunkSource().mainThreadProcessor.managedBlock(future::isDone); // ShreddedPaper - run tick thread tasks (this might be one tick thread accessing a chunk in another tick thread)
+ return future.join(); // ShreddedPaper - regions
+ return future.join(); // ShreddedPaper - don't use managedBlock to avoid deadlocks in multi-threaded context
}
ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z);
if (chunk != null) {
return chunk instanceof ImposterProtoChunk || chunk instanceof net.minecraft.world.level.chunk.LevelChunk;
}
- final java.util.concurrent.CompletableFuture<ChunkAccess> future = new java.util.concurrent.CompletableFuture<>();
- ca.spottedleaf.moonrise.common.PlatformHooks.get().scheduleChunkLoad(
- this.world, x, z, false, ChunkStatus.EMPTY, true, ca.spottedleaf.concurrentutil.util.Priority.NORMAL, future::complete
- );
- world.getChunkSource().mainThreadProcessor.managedBlock(future::isDone);
- return future.thenApply(c -> {
- if (c != null) {
- return c.getPersistedStatus() == ChunkStatus.FULL;
- }
- return false;
- }).join();
+ // ShreddedPaper start - avoid recursive deadlock by returning false for recursive calls when chunk not in memory
+ if (isInsideIsChunkGenerated.get()) {
+ return false; // Conservative answer: assume not generated if we can't check without blocking
+ }
+ isInsideIsChunkGenerated.set(Boolean.TRUE);
+ try {
+ // ShreddedPaper end
+ final java.util.concurrent.CompletableFuture<ChunkAccess> future = new java.util.concurrent.CompletableFuture<>();
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().scheduleChunkLoad(
+ this.world, x, z, false, ChunkStatus.EMPTY, true, ca.spottedleaf.concurrentutil.util.Priority.NORMAL, future::complete
+ );
+ world.getChunkSource().mainThreadProcessor.managedBlock(future::isDone);
+ return future.thenApply(c -> {
+ if (c != null) {
+ return c.getPersistedStatus() == ChunkStatus.FULL;
+ }
+ return false;
+ }).join();
+ } finally {
+ isInsideIsChunkGenerated.set(Boolean.FALSE);
+ }
// Paper end - Fix this method
}

@@ -751,13 +_,15 @@

@Override
Expand Down