No description
Find a file
beezm 9c255a4fc6 feat: render the water we already had (terrain-water task 13, Phase C1)
The blueprint has carried water since task 03 -- WBID per-pixel body id,
WBTB body table, WSRF per-pixel surface level. Nothing ever drew it. Now
the runtime does. No new water data: the blueprint is the authority on
where water is and at what level, and this only reads it.

WHY WATER IS ITS OWN MESH, not a block in the terrain field. The terrain
is a Marching-Cubes iso-surface over ChunkData.Densities. Writing WATER
into that field would not lay a sheet on top of the seabed -- it would
move the iso-surface, fusing the sea into the terrain as if it were solid
ground. A second surface is the only way water can sit at ITS level
independent of the ground under it. So ChunkRenderer builds a water
MeshInstance3D as a child of the chunk's terrain mesh.

TRANSPARENCY IS SHIPPED, NOT DEFERRED (Step 2.4's cheap branch). Because
water is a distinct MeshInstance3D it carries its own StandardMaterial3D,
so alpha is one flag and Godot sorts transparent surfaces after opaque
ones by itself. Zero mesher changes. Alpha runs 0.62 shallow -> 0.97 deep,
so the shelved coast stays readable and open ocean closes up.

WHICH DATA DROVE IT: WSRF for the level (per-pixel, quantised to 1/32768
raw ~ 7.7 mm, far under the 1 m voxel, and no table lookup), WBID for
presence (it is the water stage's own classification output -- the same
set the biome grid's Ocean/Lake pixels form by construction), WBTB as the
fallback when a column is flagged wet but carries the WSRF no-water
sentinel. A body the table does not know leaves the column DRY rather
than guessing a level.

Details worth keeping:
- Water Y uses Constants.HEIGHT_SCALE, the SAME mapping as the terrain
  surface, named so the sheet and the seabed cannot drift apart if the
  vertical band is ever retuned.
- Depth for shading comes from BLUEPRINT heights, not rendered geometry:
  the terrain render clamps its floor at Y=2, so every deep-ocean column
  would otherwise read as one flat ~36 m and the gradient would die
  exactly where the ocean gets interesting.
- A cell is drawn if ANY corner is wet, flat at the highest wet level.
  Drawing onto a partly-dry cell is deliberate -- it carries the sheet
  under the shoreline where the opaque terrain hides it. Only-fully-wet
  cells retreat the waterline a metre and leave a dry gap around every
  coast and lake.
- Non-metallic, roughness 0.35: the scene environment is minimal, and a
  metallic surface reads near-black when there is nothing to reflect.

BlockRegistry gains WATER (id 11). Wire-safe: block IDs are never
serialized -- the blueprint's section table stores heights, biome ordinals
and water data, never block IDs, and chunks are not persisted yet.

MEASURED on seed 1825907253: 241,415 water columns across 454 of 4096
chunks; surface Y 37.6..37.6 m (flat, = 0.15 x 251 -- the flat sea model,
rendered); depth to 32.3 m, matching an independent read of the blueprint
exactly. Both an ocean and a lake fall in the default view.

NO REGRESSION to the 2D pipeline, verified section by section: a
regeneration of the working seed is byte-identical to task 12's run in
TCRV, TDTL, HGTS, BIOM, WBID, WBTB, WSRF, TOWN and all four road
sections; only PRMS differs, and only in its write timestamp. All four
snapshot PNGs md5-identical.

No storms, no waves, no animation, no flow -- water at rest. Those are C2+.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 02:32:04 -04:00
Client feat: render the water we already had (terrain-water task 13, Phase C1) 2026-08-09 02:32:04 -04:00
Core feat: render the water we already had (terrain-water task 13, Phase C1) 2026-08-09 02:32:04 -04:00
Data docs: bring all READMEs current with actual code (post-sweep-10 truth pass) 2026-08-05 05:23:58 -04:00
Resources docs: bring all READMEs current with actual code (post-sweep-10 truth pass) 2026-08-05 05:23:58 -04:00
Scenes docs: bring all READMEs current with actual code (post-sweep-10 truth pass) 2026-08-05 05:23:58 -04:00
Server feat: render the water we already had (terrain-water task 13, Phase C1) 2026-08-09 02:32:04 -04:00
Tools chore: Godot .uid for IslandFalloff (terrain-water task 11) 2026-08-09 00:53:41 -04:00
.gitignore baseline: working salvaged prototype on Godot 4.7.1 (pre-F1) 2026-08-05 01:45:41 -04:00
icon.svg baseline: working salvaged prototype on Godot 4.7.1 (pre-F1) 2026-08-05 01:45:41 -04:00
icon.svg.import baseline: working salvaged prototype on Godot 4.7.1 (pre-F1) 2026-08-05 01:45:41 -04:00
islaApocolypse.csproj baseline: working salvaged prototype on Godot 4.7.1 (pre-F1) 2026-08-05 01:45:41 -04:00
islaApocolypse.csproj.old baseline: working salvaged prototype on Godot 4.7.1 (pre-F1) 2026-08-05 01:45:41 -04:00
islaApocolypse.sln baseline: working salvaged prototype on Godot 4.7.1 (pre-F1) 2026-08-05 01:45:41 -04:00
project.godot baseline: working salvaged prototype on Godot 4.7.1 (pre-F1) 2026-08-05 01:45:41 -04:00
README.md docs: bring all READMEs current with actual code (post-sweep-10 truth pass) 2026-08-05 05:23:58 -04:00
ServerConfig.json feat: config-gated flat-scalar sea level (D-033, terrain-water task 04) 2026-08-07 06:20:48 -04:00

IslaApocalypse

Version: v0.0.1 — prototyping / salvage. Not a playable build. Engine: Godot 4.7.1 · C# / .NET 8 (Godot.NET.Sdk 4.7.1)

A procedurally generated, multiplayer-ready voxel survival game on a post-nuclear Caribbean island. Terrain is smooth (Marching Cubes), not blocky.

Design intent, decisions and rationale live in the design vault, not here. This README and the per-directory ones describe what the code does. For why, see the vault repo (islaApocalypse-vault-v0.1).


How the world gets built

Two phases, with a file in between.

  1. 2D blueprint (Tools/Scripts/MapGenerator.cs) — FastNoiseLite topography, dynamic sea level, an impact crater, biome zoning, tiered town placement, and an A* road network in four tiers (Highway, Branch, Rugged, Trail). Written to a binary .dat.
  2. 3D voxel world (Server/ + Core/) — the .dat is parsed into RAM, and chunks are built around the Capitol: a density field per chunk, meshed with Marching Cubes, vertex-coloured by biome and depth, with roads carved into the terrain.

Map size is config-driven, not fixed. The shipped ServerConfig.json selects the 8K profile → 8192 × 8192, where 1 pixel = 1 metre = 1 voxel footprint.


⚠️ How to actually run it

Pressing Play (F5) does NOT run the game. The project's main scene is the 2D map generator, so F5 regenerates the entire world (minutes — and it currently stalls in the A* road pass) and overwrites your .dat.

To view the 3D world:

  1. Open Scenes/Main.tscn.
  2. Press F6Run Current Scene.

It reads ServerConfig.json, loads the existing .dat, and builds the chunk grid.

To generate a new world (only when you actually want a new map): press F5, or open Tools/Scenes/MapPreview.tscn and press F6.

Before you run it — set ChunkRadius

ServerConfig.json, at the project root:

{ "WorldSeed": 1063685222, "MapProfile": "8K", "TownDensity": "Normal", "ChunkRadius": 32 }

ChunkRadius is a load radius in chunks, not a chunk size. The grid built at boot is (2 × radius)² chunks, all synchronously:

ChunkRadius Chunks built Cost
4 64 loads in seconds
8 256 still quick
32 (shipped) 4,096 ~3.6 GB, minutes

Use 48 while iterating. 32 is for looking at a lot of world at once.

MapProfile accepts 4K / 6K / 8K / 10K → 4096 / 6144 / 8192 / 10240.

Where the generated world lives

Outputs go to Godot's user://, not into this repo — on Linux, ~/.local/share/godot/app_userdata/islaApocolypse/:

  • MapData_Seed_<seed>.dat — the blueprint (~512 MB at 8K)
  • Map_Seed_<seed>.png — a visual snapshot of the map, for reviewing and picking seeds

WorldSeed must match an existing .dat, or the load fails with CRITICAL ERROR: Map file not found and you get an empty scene.


Directory layout

Path What's in it
Core/ Shared, stateless logic: the .dat parser, Marching Cubes, chunk data, block registry, biome palette, constants. Used by both the server and client paths.
Server/ Authoritative world building: loads the blueprint, builds chunks around the Capitol, computes densities, carves roads.
Client/ Rendering: turns finished chunk data into MeshInstance3D geometry with a vertex-coloured material.
Tools/ Offline developer tooling — the 2D map generator and its scenes. Never shipped.
Scenes/ Runtime scenes. Main.tscn is the 3D world.
Data/ Handoff folder for static world data. Currently documentation only.
Resources/ Intended home for Godot .tres asset definitions. Currently documentation only.

Current state

Working: 2D generation end to end at 8K · .dat write and read · chunk building · Marching Cubes meshing with analytical normals and seam-free integer vertex welding · road carving for all four tiers with per-tier width and grade · biome/depth vertex colouring with soft material fades.

Known issues:

  • A* road generation is slow enough to stall a full regeneration — a 67-million-node grid at 1 px granularity, with a same-sized setup loop. The dominant open problem.
  • Faint seam lines along chunk borders — a normals/shading difference between independently meshed chunks, not a gap in the geometry.
  • No player, no collision, no water, and no camera controller — there is no input handling in the codebase at all. Inspect the world with the editor camera.
  • The world is built once at boot: no chunk streaming or unloading yet.
  • Two road issues remain: roadbed elevation can jump where two separate stretches of road pass close together, and road materials are only a coarse asphalt/dirt split.