Byte-accurate entries for the three water sections (transitional per-body level rule, provisional salinity, WSRF sentinel/quantization), updated size math (~576 MiB at 8K with water), the on-the-record rationale for NOT serializing basins, and README updates for the new pipeline stage, the 0_water snapshot, and the SkipRoads toggle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
67 lines
4.5 KiB
Markdown
67 lines
4.5 KiB
Markdown
# Core Module
|
||
|
||
Shared, stateless logic used by both the server and client paths: the `.dat` parser, the mesher, the
|
||
voxel data containers, and the material lookups. **No Godot nodes, no scene state.** These scripts
|
||
define what things are and how to calculate them; they never remember what is currently happening.
|
||
|
||
## Components
|
||
|
||
### `MapDataParser.cs` — the data bridge
|
||
Deserializes the binary `.dat` blueprint written by `/Tools` into a `WorldBlueprint` held in RAM:
|
||
map size, the float heightmap, the biome map, town locations, **all four tiers** of A\* road
|
||
vectors (Highways, Branch Roads, Rugged Roads, Trails), and — from v2 files — the embedded
|
||
generation params (seed, sizes, impact centre, provenance) and each town's highway-node flag.
|
||
|
||
**Two formats are live** (byte-accurate contract: `Core/Scripts/BLUEPRINT_FORMAT.md`). The parser
|
||
dispatches on the file's first byte:
|
||
- **v2 (primary)** — raw `ISLA` magic, u32 version gate, then tagged sections
|
||
`[u32 tag][u64 length][payload]`. Unknown tags are skipped by length, so future sections are
|
||
invisible to older readers. Validated on read: version, MapSize bounds, section lengths against
|
||
the file, biome/tier ordinal ranges. Since the water-bodies stage, v2 files also carry the
|
||
optional `WBID`/`WBTB`/`WSRF` water sections (per-pixel body ids, the body table, quantized
|
||
surface levels) — parsed into `WorldBlueprint` and consumed by nothing at runtime yet.
|
||
- **v1 (legacy)** — the positional `"ISLA_V1"` format, still written beside v2 as `_v1.dat` and
|
||
still loadable (with a deprecation warning) until a future removal task.
|
||
|
||
⚠ **Wire-format hazard.** Biome and town-tier enums are serialized as their **ordinal values**
|
||
(u8 in v2, i32 in v1). **Never reorder or insert members** in `Enums.cs` — append only, at the end.
|
||
v2's range checks make drift fail loudly at parse time; legacy v1 has no validation and silently
|
||
reinterprets every pixel. (`RoadTier` is exempt: road tiers are stored in separate file sections —
|
||
tagged in v2, positional in v1 — so that enum never hits disk.)
|
||
|
||
### `ChunkData.cs` + `Constants.cs` — voxel containers and tuning
|
||
- **Chunk dimensions:** `24 × 24` horizontal, `256` vertical (`Constants.cs`).
|
||
- **The `+1` padding is structural.** `Densities` and `BlockIDs` are one cell larger on every axis —
|
||
`[25, 257, 25]` — so the mesher can evaluate the boundary cells shared with the neighbouring chunk
|
||
and the meshes meet without gaps.
|
||
- **Per-column data for rendering:** `SurfaceHeights` (the true, unrounded surface), `ColumnBiomes`,
|
||
and `ColumnRoadMaterial` (0 = not a road). These let the mesher colour by real height rather than a
|
||
rounded integer.
|
||
- **Tunables in `Constants.cs`:** `BLEND_BAND_METERS` (how far one surface material fades into the
|
||
next) and the per-tier road block — width, shoulder, grade-smoothing and surface material for each
|
||
of the four road tiers, plus the derived cull padding.
|
||
|
||
### `MarchingCubes.cs` — the mesher
|
||
Turns a chunk's density field into a Godot `ArrayMesh`.
|
||
- **Analytical normals:** exact density gradients at each cell corner, interpolated along the edge by
|
||
the same fraction used for the vertex position — smooth lighting without Godot's normal pass.
|
||
- **Deterministic vertex welding:** shared vertices are keyed by an integer `EdgeKey` ordered
|
||
lowest-to-highest, so neighbouring chunks compute identical keys and no float drift creeps in.
|
||
- **Vertex colouring:** each vertex is coloured from its true float depth below the surface, fading
|
||
between the two materials either side of a boundary rather than switching at an integer depth.
|
||
|
||
**Density sign convention (load-bearing):** density is **positive above** the surface and **negative
|
||
below** it. A corner counts as inside the terrain when `density < ISO_LEVEL`.
|
||
|
||
### `BiomePalette.cs` + `BlockRegistry.cs` + `BlockData.cs` — materials
|
||
- **`BlockRegistry`:** byte-ID lookup for every block (`AIR`, `BEDROCK`, `STONE`, `DIRT`, `SAND`, the
|
||
three grasses, `SNOW`, `WASTELAND_DIRT`, `ASPHALT`).
|
||
- **`BiomePalette`** answers "what material is here?" twice, deliberately:
|
||
- `GetVoxelID(...)` — the authoritative **integer** classification by whole-block depth. Decides
|
||
what is actually stored in each voxel; used for everything non-visual.
|
||
- `GetBlendedVoxelIDs(...)` — the **rendering** version. Same question by *float* depth, returning
|
||
the two materials either side of the nearest boundary plus how far between them the point is, so
|
||
the renderer fades instead of snapping.
|
||
|
||
Both take a road-surface byte, so a trail is surfaced in dirt where a highway is surfaced in
|
||
asphalt.
|