From 35cc32c4a1e5fae5a5e7f4919084565fc2e92d4f Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 12 Mar 2022 06:32:31 -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. Missed patch from tuinity merge --- ...ix-swamp-hut-cat-generation-deadlock.patch | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 patches/server/Fix-swamp-hut-cat-generation-deadlock.patch 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 000000000..c982e3698 --- /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; + }