diff --git a/patches/server/Fix-swamp-hut-cat-generation-deadlock.patch b/patches/server/Fix-swamp-hut-cat-generation-deadlock.patch new file mode 100644 index 0000000000..c982e3698c --- /dev/null +++ b/patches/server/Fix-swamp-hut-cat-generation-deadlock.patch @@ -0,0 +1,56 @@ +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 generatoraccess 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Cat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java +@@ -0,0 +0,0 @@ public class Cat extends TamableAnimal { + Registry> iregistry = worldserver1.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY); + + if (ChunkGenerator.allConfigurations(iregistry, StructureFeature.SWAMP_HUT).anyMatch((structurefeature) -> { +- return worldserver1.structureFeatureManager().getStructureWithPieceAt(this.blockPosition(), structurefeature).isValid(); ++ return worldserver1.structureFeatureManager().getStructureWithPieceAt(this.blockPosition(), structurefeature, world).isValid(); // Paper - fix deadlock + })) { + this.setCatType(10); + this.setPersistenceRequired(); +diff --git a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java ++++ b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +@@ -0,0 +0,0 @@ public class StructureFeatureManager { + } + + public List startsForFeature(SectionPos sectionPos, ConfiguredStructureFeature configuredStructureFeature) { +- LongSet longSet = this.level.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(configuredStructureFeature); ++ // Paper start - add world option ++ return this.startsForFeature(sectionPos, configuredStructureFeature, (ServerLevelAccessor)null); ++ } ++ public List startsForFeature(SectionPos sectionPos, ConfiguredStructureFeature configuredStructureFeature, ServerLevelAccessor world) { ++ LongSet longSet = (world == null ? this.level : world).getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(configuredStructureFeature); ++ // Paper end - add world option + Builder builder = ImmutableList.builder(); + this.fillStartsForFeature(configuredStructureFeature, longSet, builder::add); + return builder.build(); +@@ -0,0 +0,0 @@ public class StructureFeatureManager { + } + + public StructureStart getStructureWithPieceAt(BlockPos pos, ConfiguredStructureFeature configuredStructureFeature) { +- for(StructureStart structureStart : this.startsForFeature(SectionPos.of(pos), configuredStructureFeature)) { ++ // Paper start - add world option ++ return this.getStructureWithPieceAt(pos, configuredStructureFeature, (ServerLevelAccessor)null); ++ } ++ public StructureStart getStructureWithPieceAt(BlockPos pos, ConfiguredStructureFeature configuredStructureFeature, ServerLevelAccessor world) { ++ // Paper end - add world option ++ for(StructureStart structureStart : this.startsForFeature(SectionPos.of(pos), configuredStructureFeature, world)) { // Paper - add world option + if (this.structureHasPieceAt(pos, structureStart)) { + return structureStart; + }