Skip to content

Commit 330ce4b

Browse files
author
yynps
committed
fix: bypass BiomeManager to prevent WorldGenRegion.getChunk() deadlock in containers
1 parent f2e15d7 commit 330ce4b

File tree

6 files changed

+28
-29
lines changed

6 files changed

+28
-29
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ bin
66
.classpath
77
.project
88

9+
# vscode
10+
.vscode
11+
912
# idea
1013
out
1114
*.ipr

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ tasks.named('wrapper', Wrapper).configure {
1212
distributionType = Wrapper.DistributionType.BIN
1313
}
1414

15-
version = "${minecraft_version}-${mod_version}-uto26"
15+
version = "${minecraft_version}-${mod_version}-uto27"
1616
group = mod_group
1717

1818
base {

src/main/java/com/aetherteam/aether/world/BlockLogicUtil.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22

33
import net.minecraft.core.BlockPos;
44
import net.minecraft.core.Direction;
5+
import net.minecraft.core.Holder;
6+
import net.minecraft.core.QuartPos;
57
import net.minecraft.core.SectionPos;
68
import net.minecraft.world.level.ChunkPos;
9+
import net.minecraft.world.level.biome.Biome;
10+
import net.minecraft.world.level.chunk.ChunkAccess;
711
import net.minecraft.world.level.levelgen.structure.BoundingBox;
812

13+
import java.util.function.Function;
14+
915
public final class BlockLogicUtil {
1016
/**
1117
* Find the entry point for a tunnel piece to a room with an odd-numbered width
@@ -49,6 +55,18 @@ public static BlockPos tunnelFromEvenSquareRoom(BoundingBox box, Direction direc
4955
);
5056
}
5157

58+
/**
59+
* Biome getter that reads directly from chunk storage, bypassing BiomeManager → WorldGenRegion.getChunk().
60+
* Prevents deadlock: getChunk() hangs in CrashReport/OSHI before throwing, making try-catch useless.
61+
*/
62+
public static Function<BlockPos, Holder<Biome>> createSafeBiomeGetter(ChunkAccess localChunk) {
63+
return (pos) -> localChunk.getNoiseBiome(
64+
QuartPos.fromBlock(pos.getX()),
65+
QuartPos.fromBlock(pos.getY()),
66+
QuartPos.fromBlock(pos.getZ())
67+
);
68+
}
69+
5270
/**
5371
* Checks if a position for block placement is within a center chunk.
5472
*

src/main/java/com/aetherteam/aether/world/feature/CrystalIslandFeature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ private void setIslandBlock(WorldGenLevel level, BlockPos pos, BlockState testSt
8181
NoiseChunk noisechunk = ((ChunkAccessAccessor) chunkAccess).aether$getNoiseChunk();
8282
if (noisechunk != null) {
8383
CarvingContext carvingcontext = new CarvingContext(noiseBasedChunkGenerator, level.registryAccess(), chunkAccess.getHeightAccessorForGeneration(), noisechunk, serverChunkCache.randomState(), surfaceRule);
84-
Optional<BlockState> state = carvingcontext.topMaterial(level.getBiomeManager()::getNoiseBiomeAtPosition, chunkAccess, pos, false);
84+
Optional<BlockState> state = carvingcontext.topMaterial(BlockLogicUtil.createSafeBiomeGetter(chunkAccess), chunkAccess, pos, false);
8585
if (state.isPresent()) {
8686
if (testState.is(AetherTags.Blocks.AETHER_DIRT) && !testState.is(AetherBlocks.AETHER_DIRT.get()) && state.get().is(AetherTags.Blocks.AETHER_DIRT)) {
8787
newState = state.get();

src/main/java/com/aetherteam/aether/world/processor/SurfaceRuleProcessor.java

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@
2323
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
2424
import org.jetbrains.annotations.Nullable;
2525

26-
import net.minecraft.core.Holder;
27-
import net.minecraft.world.level.biome.Biome;
28-
2926
import java.util.Optional;
30-
import java.util.function.Function;
3127

3228
/**
3329
* This processor is used to replace grass blocks in the Aether with blocks determined by the biome's surface rules.
@@ -57,29 +53,11 @@ public StructureTemplate.StructureBlockInfo process(LevelReader level, BlockPos
5753
NoiseChunk noisechunk = ((ChunkAccessAccessor) chunkAccess).aether$getNoiseChunk();
5854
if (noisechunk != null) {
5955
CarvingContext carvingcontext = new CarvingContext(noiseBasedChunkGenerator, worldGenLevel.registryAccess(), chunkAccess.getHeightAccessorForGeneration(), noisechunk, serverChunkCache.randomState(), surfaceRule);
60-
// [uto26] Safe biome getter: WorldGenRegion.getChunk() throws IllegalStateException
61-
// when biome sampling reaches chunks outside the generation region. Catch at the
62-
// method reference level to prevent propagation through memoized Supplier chains.
63-
Function<BlockPos, Holder<Biome>> safeBiomeGetter = (pos) -> {
64-
try {
65-
return worldGenLevel.getBiomeManager().getNoiseBiomeAtPosition(pos);
66-
} catch (Exception e) {
67-
return chunkAccess.getNoiseBiome(
68-
net.minecraft.core.SectionPos.blockToSectionCoord(pos.getX()),
69-
net.minecraft.core.SectionPos.blockToSectionCoord(pos.getY()),
70-
net.minecraft.core.SectionPos.blockToSectionCoord(pos.getZ())
71-
);
72-
}
73-
};
74-
try {
75-
Optional<BlockState> state = carvingcontext.topMaterial(safeBiomeGetter, chunkAccess, modifiedBlockInfo.pos(), false);
76-
if (state.isPresent()) {
77-
if (modifiedBlockInfo.state().is(AetherTags.Blocks.AETHER_DIRT) && !modifiedBlockInfo.state().is(AetherBlocks.AETHER_DIRT.get()) && state.get().is(AetherTags.Blocks.AETHER_DIRT)) {
78-
return new StructureTemplate.StructureBlockInfo(modifiedBlockInfo.pos(), state.get(), null);
79-
}
56+
Optional<BlockState> state = carvingcontext.topMaterial(BlockLogicUtil.createSafeBiomeGetter(chunkAccess), chunkAccess, modifiedBlockInfo.pos(), false);
57+
if (state.isPresent()) {
58+
if (modifiedBlockInfo.state().is(AetherTags.Blocks.AETHER_DIRT) && !modifiedBlockInfo.state().is(AetherBlocks.AETHER_DIRT.get()) && state.get().is(AetherTags.Blocks.AETHER_DIRT)) {
59+
return new StructureTemplate.StructureBlockInfo(modifiedBlockInfo.pos(), state.get(), null);
8060
}
81-
} catch (Exception e) {
82-
return modifiedBlockInfo;
8361
}
8462
}
8563
}

src/main/java/com/aetherteam/aether/world/structurepiece/GlowstoneRuinedPortalPiece.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ public static BlockState getSurfaceBlockForPlacement(LevelAccessor level, BlockP
311311
NoiseChunk noisechunk = ((ChunkAccessAccessor) chunkAccess).aether$getNoiseChunk();
312312
if (noisechunk != null) {
313313
CarvingContext carvingcontext = new CarvingContext(noiseBasedChunkGenerator, worldGenLevel.registryAccess(), chunkAccess.getHeightAccessorForGeneration(), noisechunk, serverChunkCache.randomState(), surfaceRule);
314-
Optional<BlockState> state = carvingcontext.topMaterial(worldGenLevel.getBiomeManager()::getBiome, chunkAccess, pos, false);
314+
Optional<BlockState> state = carvingcontext.topMaterial(BlockLogicUtil.createSafeBiomeGetter(chunkAccess), chunkAccess, pos, false);
315315
if (state.isPresent()) {
316316
if (originalState.is(AetherTags.Blocks.AETHER_DIRT) && !originalState.is(AetherBlocks.AETHER_DIRT.get()) && state.get().is(AetherTags.Blocks.AETHER_DIRT)) {
317317
return state.get();

0 commit comments

Comments
 (0)