World generation overhaul: biomes, terrain, coasts & blending#5
Conversation
Modular world-gen pipeline (src/game/gen/) replacing the single-file generator with declarative, deterministic stages: Climate (heat/humidity + altitude chill), Biomes (Voronoi climate selection, 12 biomes), TerrainNoise (continents + ridged mountains + rivers + detail), Caves (worm tunnels + caverns), Ores (depth-gated veins), Surface (coastal + snow + blend painting), Trees (6 species w/ variants), Decorations (clustered ground cover), WorldgenStats. Generation is deterministic per seed (byte-identical, seamless chunk borders) and budgeted (~3.6ms/chunk). Biome system: 12 biomes selected by nearest climate point with altitude chill; fixed a climate-map DC-bias bug that had frozen half the map to freezing. All biomes appear across seeds. Coastlines (multi-pass tuning): - Beaches are a proximity effect, not an elevation biome; sand requires real water adjacency so low inland plains stay grassy. - Beach PRESENCE is a low-frequency patch mask gated by per-biome tendency (desert always sandy; forest/snow/mountain mostly earthen banks w/ sand pockets) — breaks the uniform sand ring around lakes. - Beach width noise-modulated + slope-aware; steep shores never sandy. - Elevation-aware rocky threshold near sea kills grey stone rings. - 3D solidity wobble damped near sea so dressed floor tracks the heightmap (fixes invisible-water/beach gaps). - Underwater shelves grade sand -> gravel -> dirt by depth. Biome blending: continuous temperature-driven snow mask (tapers Snow -> Snowy Grass -> Grass, biome-independent) + biome-edge mottling, removing hard biome/snow boundary lines. Blocks: +8 (dead bush, fern, papyrus, cornflower, birch wood/leaves, spruce leaves, snowy leaves) + 9 atlas tiles. Debug: WorldgenOverlay (G toggle, H cycle) w/ live minimap (biome/heat/humidity/height/slope/shore/snow modes) + target-column readout (biome, surface, snow, beach strength/presence, water extent, shore distance, slope). Gen timing in the F3 perf overlay. __voxl.worldgen()/worldgenMode()/worldgenInfo() console API. Spawn search now finds dry land near origin. Typecheck clean; build passes; 3/3 test suites pass.
📋 SummaryNo linked issues (e.g., “Fixes #123”) were found in the PR description. The PR title/body position this as a feature overhaul rather than a bug-fix tied to a tracked issue. This PR replaces the monolithic 📌 Review Metadata
🔴 Critical Issues (Must Fix - Blocks Merge)None identified.
|
| Principle | Score | Notes |
|---|---|---|
| Single Responsibility | 8 | Generator is cleanly split into Climate, Biomes, TerrainNoise, Caves, Ores, Surface, Trees, Decorations, Stats. |
| Open/Closed | 7 | New biomes require editing BIOME_DEFS and possibly TreeGenerator; could be more plugin-like. |
| Liskov Substitution | 8 | No deep inheritance; small data-driven types behave consistently. |
| Interface Segregation | 8 | Focused types (SetBlock, DecoColumn, SurfaceCtx) keep call sites narrow. |
| Dependency Inversion | 7 | Modules depend directly on the concrete Noise class, but that matches the existing codebase. |
| Average | 7.6 |
🎯 Final Assessment
Overall Confidence Score: 78%
Confidence Breakdown:
- Code Quality: 85% (clean modular structure, minor dead code / redundant branches)
- Completeness: 90% (delivers all stated world-gen features and debug tooling)
- Risk Level: 60% (large change to core generation; a few terrain/perf artifacts possible)
- Test Coverage: 70% (existing suites pass, but no new automated tests for determinism/biome distribution)
Merge Readiness:
- All critical issues resolved
- SOLID average score >= 6.0
- Overall confidence >= 60%
- No security concerns
- Tests present and passing
Verdict:
MERGE WITH FIXES
The PR is well-architected, deterministic, and passes all build/test gates, but address the sub-sea cave air pockets and the river-offset ocean-floor artifact before merging.
[HIGH] Caves: never carve below sea level. Previously, worm tunnels carved
at y < sea under land columns (height > sea+1), leaving dry air pockets
underwater (fillWater only floods columns whose surface is below sea).
Now all sub-sea crust stays solid; caves live only above sea under land.
Verified: 0 sub-sea air cells, 55k+ above-sea cave cells remain. Removed
the now-unreachable deep-cavern branch.
[MED] River carve clamped to never raise terrain (was ridging the deep
ocean floor where bands crossed water). Also refactored height() to pass
the continent+hills base to riverOffset() instead of recomputing two fbm
octaves per column (~1.7k fewer noise evals/chunk; gen dropped 3.6->3.4ms).
[MED] WorldgenOverlay hint text corrected ('G toggle · H cycle').
[MED] Minimap perf: debugAt() gains a fast flag that skips the radius-8
water-extent scan and radius-6 shore distance for the per-pixel minimap
render (~600 fewer noise evals/pixel); full readout still used for the
single target column.
[MED] Trees: collapsed redundant birch canopy layerR branch.
[LOW] Biomes: documented 'beach' as a reserved palette entry (selectBiome
never returns it by design).
[LOW] Removed dead re-exports (landBiome/landBlend/BiomeId) and the now-
unused landBiome import from TerrainGenerator.
[LOW] findSpawnColumn spiral step 6->8 to halve worst-case ocean-start cost.
Typecheck clean; build passes; 3/3 tests pass.
📋 SummaryNo linked issues (e.g., “Fixes #123”) were found in the PR description. The PR is a feature overhaul of world generation. This PR replaces the monolithic 📌 Review Metadata
🔴 Critical Issues (Must Fix - Blocks Merge)None identified.
|
| Principle | Score | Notes |
|---|---|---|
| Single Responsibility | 8 | Generator cleanly split into Climate, Biomes, TerrainNoise, Caves, Ores, Surface, Trees, Decorations, Stats. |
| Open/Closed | 7 | New biomes require editing BIOME_DEFS and tendencyFor; could be more plugin-like. |
| Liskov Substitution | 8 | No deep inheritance; small data-driven types behave consistently. |
| Interface Segregation | 8 | Focused types (SetBlock, DecoColumn, SurfaceCtx) keep call sites narrow. |
| Dependency Inversion | 7 | Modules depend directly on the concrete Noise class, matching existing codebase style. |
| Average | 7.6 |
🎯 Final Assessment
Overall Confidence Score: 78%
Confidence Breakdown:
- Code Quality: 85% (clean modular structure, minor control/surface-blend issues)
- Completeness: 90% (delivers all stated world-gen features and debug tooling)
- Risk Level: 60% (large change to core generation; a couple of terrain/UX artifacts possible)
- Test Coverage: 70% (existing suites pass, but no new automated tests for determinism/biome distribution)
Merge Readiness:
- All critical issues resolved
- SOLID average score >= 6.0
- Overall confidence >= 60%
- No security concerns
- Tests present and passing
Verdict:
MERGE WITH FIXES
The PR is well-architected, deterministic, and passes all build/test gates. Address the biome-center blending bug in landBlend() and the KeyH control conflict before merging.
[MED] Biomes.landBlend(): the edge metric was broken — the formula 1 - sqrt(secondD)/(sqrt(bestD)+eps) evaluated to ~0 everywhere (center AND boundary), and the bestD<1e-6 ? 1 special case returned max edge at biome CENTERS (backwards). Replaced with a correct fixed-width band: edge = 1 - (dSecond - dBest)/0.05, so it's 0 deep inside a biome and 1 on a boundary. Biome-edge mottling now actually fires near climate boundaries (was effectively dead). Verified: max edge 1.0, ~22% of columns in the mottle band. [MED] Game.ts: KeyH fell through from the worldgen mode-cycle into handleLightingDebugKey (which toggles shadows), so one keypress changed two unrelated toggles. Added an early return after cycling. [LOW] findSpawnColumn: the biomeAt(... !== 'ocean') check was redundant with columnHeight > SEA (selectBiome returns ocean iff height <= sea), so it duplicated the heightmap + climate work. Dropped it — check is now a single columnHeight() call, roughly halving worst-case ocean-start cost. Typecheck clean; build passes; 3/3 tests pass; determinism holds.
📋 SummaryNo linked issues (e.g., “Fixes #123”) were found in the PR description or title. The PR is a feature overhaul of world generation. This PR replaces the monolithic 📌 Review Metadata
🔴 Critical Issues (Must Fix - Blocks Merge)None identified. ✅ All previously reported critical/high issues have been resolved (sub-sea cave air pockets fixed).
|
| Principle | Score | Notes |
|---|---|---|
| Single Responsibility | 8 | Generator is cleanly split into Climate, Biomes, TerrainNoise, Caves, Ores, Surface, Trees, Decorations, Stats. |
| Open/Closed | 7 | New biomes require editing BIOME_DEFS and tendencyFor; could be more plugin-like. |
| Liskov Substitution | 8 | No deep inheritance; small data-driven types behave consistently. |
| Interface Segregation | 8 | Focused types (SetBlock, DecoColumn, SurfaceCtx) keep call sites narrow. |
| Dependency Inversion | 7 | Modules depend directly on the concrete Noise class, matching existing codebase style. |
| Average | 7.6 |
🎯 Final Assessment
Overall Confidence Score: 85%
Confidence Breakdown:
- Code Quality: 85% (clean modular structure; minor survival-parity oversights)
- Completeness: 90% (delivers all stated world-gen features and debug tooling)
- Risk Level: 70% (large change to core generation, but deterministic and well-tested)
- Test Coverage: 70% (existing suites pass, but no new automated tests for determinism/biome distribution)
Merge Readiness:
- All critical issues resolved
- SOLID average score >= 6.0
- Overall confidence >= 60%
- No security concerns
- Tests present and passing
Verdict:
MERGE WITH FIXES
The PR is well-architected, deterministic, and passes all build/test gates. Address the survival-parity inconsistencies in Items.ts (plantlike dig time and leaf drops) before merging; the remaining items are optional cleanups.
[MED] Items: new plantlike blocks (dead bush 30, fern 31, papyrus 32, cornflower 33) now break instantly in survival like the existing plantlike blocks, instead of defaulting to 0.9s. [MED] Items: new leaf blocks (birch 35, spruce 36, snowy 37) now drop nothing, matching oak (6) and jungle (26) leaves. [LOW] Items: added the new blocks (b30-b37) to the creative palette so they're pickable without console/survival gathering. [LOW] WorldgenOverlay: fixed misleading humidity-mode colour comment (dry=red, not brown); invalidate the minimap render cache on hide so reopening forces a fresh render instead of a stale canvas. [LOW] Trees: removed dead placeCactus() (cacti are placed by the decoration generator). [LOW] Surface: removed the unused height parameter from decideSurface() (and the void height; placeholder) plus its callers + SurfaceCtx field. Typecheck clean; build passes; 3/3 tests pass; determinism holds.
📋 SummaryNo linked issues (e.g., “Fixes #123”) were found in the PR description or title. This is a feature overhaul, not a bug-fix tied to a tracked issue. This PR replaces the monolithic 📌 Review Metadata
The PR fully implements its stated scope: modular generation, 12 biomes, coast/beach tuning, continuous snow blending, new blocks, debug overlay, and dry-land spawn search. Code quality is high, determinism is maintained, and the survival/creative parity issues from earlier review rounds are resolved. 🔴 Critical Issues (Must Fix - Blocks Merge)None identified. ✅ All previously reported critical issues have been resolved.
|
| Principle | Score | Notes |
|---|---|---|
| Single Responsibility | 8 | Generator cleanly split into Climate, Biomes, TerrainNoise, Caves, Ores, Surface, Trees, Decorations, Stats. |
| Open/Closed | 7 | New biomes require editing BIOME_DEFS and tendencyFor; could be more plugin-like. |
| Liskov Substitution | 8 | No deep inheritance; small data-driven types behave consistently. |
| Interface Segregation | 8 | Focused types (SetBlock, DecoColumn, SurfaceCtx) keep call sites narrow. |
| Dependency Inversion | 7 | Modules depend directly on the concrete Noise class, matching existing codebase style. |
| Average | 7.6 |
🎯 Final Assessment
Overall Confidence Score: 88%
Confidence Breakdown:
- Code Quality: 90% (clean modular structure; minor dead-data/perf nits only)
- Completeness: 95% (delivers all stated world-gen features and debug tooling)
- Risk Level: 65% (large change to core generation, but deterministic and well-tested)
- Test Coverage: 70% (existing suites pass, but no new automated tests for determinism/biome distribution)
Merge Readiness:
- All critical issues resolved
- SOLID average score >= 6.0
- Overall confidence >= 60%
- No security concerns
- Tests present and passing
Verdict:
MERGE
The PR is well-architected, deterministic, and passes all build/test gates. All previously reported correctness and survival-parity issues are fixed; the remaining spawn-search cost is a minor optional optimization.




Modular, deterministic world-gen pipeline replacing the single-file generator. Closes the gap to Minetest/Luanti world richness.
What changed
Verification
Manual checklist
Grassland lake (sandy coves + grass banks) · forest lake (earthen banks) · desert/snowy/mountain coasts · steep shore (no sand) · shallow shelves · chunk-boundary shoreline · walk a beach · G -> shore/snow overlay to inspect block reasons.
Notes / TODOs