islaApocalypse/Tools
beezm 8f5767308a feat: stepped river water + widen + lake-ender join + the task-22 nits (terrain-water task 23, C0b finale)
THE PAYOFF: rivers now carry water. Each carved main river becomes a chain of
stepped flat water-body reaches — a new reach every RiverStepDropM (2 m) of bed
descent, sitting RiverWaterDepthM (1.2 m) above its bed, strictly descending to
the outlet. Reaches are ordinary water bodies (WBID cells + WBTB type 2 'river',
fresh; WSRF derives from body levels as ever), so river water renders through
the C1 path with the task-15 presence rule at its banks, untouched. Existing
bodies are never overwritten — a river MEETS its lake or the sea. Measured on
1280587109: 298 reaches across 6 rivers, 184,620 wet px, levels stepping 278 m
down to 39.5 m; in-engine, one valley frame renders surfaces 46.2-114.5 m.

Beds widened (RiverWidthScale default 1.75). Lake-enders: the stem's pooling
terminal IS a local minimum, so the first extension attempt (blind steepest
descent) dead-ended in 0 steps — replaced with the lowground Dijkstra to the
nearest classify-water cell; the E-lagoon river now joins its lake (87 px).
Smoothing is applied ONLY to lowland routes: smoothing upland stems moved them
off their carved valley floors into the walls (max cut 14.6 -> 27.3 m measured;
split restores valley-floor fidelity). TYPE_RIVER added to the WBTB registry
(parser validation extended; doc updated in the docs commit).

Task-22 nits fixed: max-cut is now CUMULATIVE vs the pre-pass surface (the
honest number: p95 carve 7.0 m; 339 cells island-wide exceed 20 m — localized
outlet-gorge notches where stems cross deposit ridges, deepest 26 m); and
0_height/0_water are re-drawn and re-captured AFTER the river pass so the
exported snapshots show beds and water.

Guards: flood guard holds (water pixels unchanged around the carve; the water
stage touches no heights), BIOME oracle md5-identical to the task-22 baseline,
0_water changed (that IS the river water), island top 457.65 m exact, crater
core excluded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 19:55:04 -04:00
..
Scenes feat: drainage-network promotion analysis — the river PLAN (terrain-water task 21, C0b part 1) 2026-08-11 18:06:21 -04:00
Scripts feat: stepped river water + widen + lake-ender join + the task-22 nits (terrain-water task 23, C0b finale) 2026-08-11 19:55:04 -04:00
README.md docs: water sections (WBID/WBTB/WSRF), no-BSIN rationale, SkipRoads + water stage in READMEs (terrain-water task 03) 2026-08-07 01:40:48 -04:00

/Tools

Offline developer utilities. Nothing here ships. These generate the source data that /Server and /Client later consume, which keeps world-generation logic out of the shipped client.

The 2D world generator

Script: Tools/Scripts/MapGenerator.cs · Scenes: Tools/Scenes/MapPreview.tscn and Scenes/MapCaptureTool.tscn

Builds the topographical and logistical foundation of the island before any 3D exists.

  • Resolution is config-driven, from ServerConfig.json's MapProfile: 4K/6K/8K/10K → 4096 / 6144 / 8192 / 10240. Shipped default is 8K. 1 pixel = 1 in-game metre = 1 voxel footprint. (The MapSize field initialiser in the script says 4096, but it is overwritten from config before use.)
  • Topography: FastNoiseLite plus distance-falloff maths for a guaranteed mainland island, a mountain spine, dynamic temperature-driven sea level, and an impact crater pushed into the northern coast (carved at 80 % of its radius so a landbridge always survives).
  • Water bodies: the classified water promoted into explicit blueprint data (ocean + labeled lakes with transitional per-body levels — WBID/WBTB/WSRF sections), plus priority-flood basin diagnostics. The SkipRoads config toggle turns a full ~26-min generation into a ~80 s road-less iteration cycle.
  • Logistics: AStarGrid2D pathfinding producing a looping continental highway, a branch to the mountain hub, and county roads daisy-chained outward with Prim's algorithm. Paths are decimated (RamerDouglasPeucker) then smoothed (4 Chaikin passes).
  • Zoning: biome mapping and tiered town/POI placement by slope, temperature and proximity.

⚠️ A* is the known bottleneck

The grid is one node per pixel — 67 million nodes at 8K — and the weight-setup pass walks every one of them. A full generation can stall long enough that runs get abandoned. await yields are sprinkled through the road stage, but they cannot interrupt a single engine-side GetPointPath call, so they only help between paths. Expect a regeneration to take minutes, or to need abandoning.

Outputs — written to user://, not into the project

File What it is
MapData_Seed_<seed>.dat The binary blueprint the server reads — v2 tagged container (~336 MB at 8K; contract in Core/Scripts/BLUEPRINT_FORMAT.md)
MapData_Seed_<seed>_v1.dat The same content in the legacy v1 format (~512 MB), dual-written as a safety net until a future removal task
Map_Seed_<seed>.png Visual snapshot of the map, for reviewing and picking seeds

On Linux: ~/.local/share/godot/app_userdata/islaApocolypse/.

Running it

Open Tools/Scenes/MapPreview.tscn and press F6. It is also the project's main scene, so pressing F5 anywhere runs this — which is why F5 regenerates your world instead of starting the game. Use Scenes/MapCaptureTool.tscn when you specifically want the full-resolution PNG.

Rules

  1. No client dependencies. Nothing here may reference UI, player controllers or shaders in /Client.
  2. Data out, nothing in. Tools emit .dat/.png/.json; they never write to a live server save.
  3. No magic numbers. Distances and radii scale off MapSize or the derived scaleFactor, so the generator behaves the same at every profile.