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 534630b0161c8d869e49e7a59572193550be0671..a744cb70ac719eae376fb2ab2271e4f8ac7b12f2 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cat.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java @@ -364,7 +364,7 @@ public class Cat extends TamableAnimal implements VariantHolder { }); 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.setVariant((CatVariant) BuiltInRegistries.CAT_VARIANT.getOrThrow(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 8b545682621554856a28a29869b2e82626a1d2f5..beccf9346cb0bad1b2c0e19104e394c016f8329a 100644 --- a/src/main/java/net/minecraft/world/level/StructureManager.java +++ b/src/main/java/net/minecraft/world/level/StructureManager.java @@ -44,7 +44,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(pos, 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()) { @@ -108,13 +113,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(Registries.STRUCTURE); for(StructureStart structureStart : this.startsForStructure(new ChunkPos(pos), (structure) -> { return registry.getHolder(registry.getId(structure)).map((reference) -> { return reference.is(structureTag); }).orElse(false); - })) { + }, levelAccessor)) { // Paper if (this.structureHasPieceAt(pos, structureStart)) { return structureStart; }