From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 12 Mar 2022 06:31:13 -0800 Subject: [PATCH] Fix swamp hut cat generation deadlock The worldgen thread will attempt to get structure references via the world's getChunkAt method, which is fine if the gen is not cancelled - but if the chunk was unloaded, the call will block indefinitely. Instead of using the world state, we use the already supplied ServerLevelAccessor which will always have the chunk available. diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java index 5ad968a2f1add27da0d6a858e683d5d771128092..e44352857272a2a4027c67bd25a28a9498b7bb49 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cat.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java @@ -361,7 +361,7 @@ public class Cat extends TamableAnimal { }); ServerLevel worldserver = world.getLevel(); - if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) { + if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK, world).isValid()) { // Paper - fix deadlock this.setCatVariant(CatVariant.ALL_BLACK); this.setPersistenceRequired(); } diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java index e7445c1ff0d1e3e989fcd8d3630dd5269a64598d..16740418e22560687c0326084c004f19681f8da6 100644 --- a/src/main/java/net/minecraft/world/level/StructureManager.java +++ b/src/main/java/net/minecraft/world/level/StructureManager.java @@ -43,7 +43,12 @@ public class StructureManager { } public List startsForStructure(ChunkPos pos, Predicate predicate) { - Map map = this.level.getChunk(pos.x, pos.z, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences(); + // Paper start + return this.startsForStructure(chunkPos, predicate, null); + } + public List startsForStructure(ChunkPos pos, Predicate predicate, @Nullable ServerLevelAccessor levelAccessor) { + Map map = (levelAccessor == null ? this.level : levelAccessor).getChunk(pos.x, pos.z, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences(); + // Paper end ImmutableList.Builder builder = ImmutableList.builder(); for(Map.Entry entry : map.entrySet()) { @@ -107,13 +112,18 @@ public class StructureManager { } public StructureStart getStructureWithPieceAt(BlockPos pos, TagKey structureTag) { + // Paper start + return this.getStructureWithPieceAt(pos, structureTag, null); + } + public StructureStart getStructureWithPieceAt(BlockPos pos, TagKey structureTag, @Nullable ServerLevelAccessor levelAccessor) { + // Paper end Registry registry = this.registryAccess().registryOrThrow(Registry.STRUCTURE_REGISTRY); for(StructureStart structureStart : this.startsForStructure(new ChunkPos(pos), (structure) -> { return registry.getHolder(registry.getId(structure)).map((holder) -> { return holder.is(structureTag); }).orElse(false); - })) { + }, levelAccessor)) { // Paper if (this.structureHasPieceAt(pos, structureStart)) { return structureStart; }