Skip to content

[1.20.1] Worldgen stability fixes: carver crash, flooded caves, legacy preset compatibility - #1024

Open
jmcjm wants to merge 5 commits into
PG85:1.20.1from
jmcjm:1.20.1-worldgen-fixes
Open

[1.20.1] Worldgen stability fixes: carver crash, flooded caves, legacy preset compatibility#1024
jmcjm wants to merge 5 commits into
PG85:1.20.1from
jmcjm:1.20.1-worldgen-fixes

Conversation

@jmcjm

@jmcjm jmcjm commented Jul 13, 2026

Copy link
Copy Markdown

What this fixes

Five independent worldgen issues, one commit each:

  1. Carver crash below y=0 on extended-height worlds — the carving mask index used the raw block Y (relativeX | relativeZ << 4 | y << 8), which goes negative with MinY below zero and crashes BitSet with IndexOutOfBoundsException as soon as a cave or ravine carves under y=0. The Y is now offset by the world minimum, the same way the ravine height cache a few lines above already does.

  2. Legacy 4-argument Dungeon() format — old presets use Dungeon(Frequency,Rarity,MinAltitude,MaxAltitude); the current 3-argument parser silently misreads them, shifting rarity/altitudes by one. Both forms are accepted now (frequency is fixed to 1 either way).

  3. Entity() .txt NBT files crashed chunk generation — these files contain text NBT (the old mojangson format), but the code fed them to the binary NbtIo reader, which throws EOFException on any such file — and the handler rethrew it as RuntimeException, killing the whole chunk. Reproducible with Biome Bundle's Ruins/Generic/Cleric.txt. .txt is now parsed with TagParser (SNBT), and a broken file logs an error and skips the entity instead of taking the world down.

  4. Out-of-range guards in biome smoothing and CHC lookups — legacy presets carry CustomHeightControl lists sized for 256-high worlds; on extended-height worlds the CHC smoothing indexes past them and crashes. Missing layers are now treated as no height control, and the biome-array lookups in both smoothing loops are bounds/null-checked so a short region from the biome provider degrades to a skipped sample instead of a crash.

  5. Everything below the water level was one big flooded cave system — with aquifers disabled, NoiseChunk uses Aquifer.createDisabled(fluidPicker) and every carved or noise-cave block below the biome water level becomes water. The vanilla aquifer noises (values from NoiseRouterData.overworld, 1.20.1) are now wired into the router's aquifer slots and aquifers are enabled in the runtime settings. OTGFluidPicker remains the global picker, so open terrain (oceans, lakes) still floods to the per-biome water level, while caves below it stay dry apart from vanilla-style aquifer pockets and deep lava.

Testing

Manually tested in-game on MC 1.20.1 (Forge 47.4.21, NeoForge 47.1.106, Fabric Loader 0.19.3 + Fabric API 0.92.6+1.20.1): caves below sea level generate dry with occasional aquifer pockets, Biome Bundle no longer crashes on entity ruins, and cave/ravine carving below y=0 no longer crashes. Also smoke-tested as a fabric dev dedicated server (fresh world, level-type=otg:default_preset, no log errors).

jmcjm added 5 commits July 13, 2026 22:11
The carving mask index used the raw block Y (relativeX | relativeZ << 4 |
y << 8), which goes negative on 1.18+ worlds with MinY below zero and
crashes BitSet with IndexOutOfBoundsException as soon as a cave or ravine
carves below y=0. Offset the Y by the world minimum, like the ravine
height cache a few lines above already does.
Old presets (Biome Bundle era) use Dungeon(Frequency,Rarity,MinAltitude,
MaxAltitude); the current parser expects 3 arguments and misreads the
legacy ones, shifting rarity/altitudes by one. Detect the 4-argument form
and skip the frequency (fixed to 1 either way).
Entity() .txt files contain text NBT (the old mojangson format that presets
like Biome Bundle ship), but the code fed them to the binary NbtIo reader,
which throws EOFException on any such file — and the handler rethrew it as
RuntimeException, crashing the whole chunk generation. Parse .txt with
TagParser and log + skip the entity on failure instead of taking the world
down with one broken preset file.
Legacy presets ship CustomHeightControl lists sized for 256-high worlds;
on extended-height worlds the CHC smoothing indexes past them and crashes.
Treat missing layers as no height control. Also bounds/null-check the
biome array lookups in both smoothing loops so a short or sparse region
from the biome provider degrades to a skipped sample instead of killing
the noise column.
…ooded

With aquifers disabled, NoiseChunk uses Aquifer.createDisabled(fluidPicker)
and every carved or noise-cave block below the biome water level becomes
water — all underground below sea level was one big flooded cave system.
Wire the vanilla aquifer noises (NoiseRouterData.overworld values) into the
router's aquifer slots and enable aquifers in the runtime settings.
OTGFluidPicker remains the global picker, so open terrain still floods to
the per-biome water level while caves stay dry apart from vanilla-style
aquifer pockets.
@authvin

authvin commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

This PR conflicts with local fixes I haven't pushed to 1.20.1 yet - will have to wait to merge this until that feature is done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants