Core/Scripts/DrainageAnalysis.cs is the reference's DrainageAnalysis ported verbatim: the Barnes priority-flood routing fill (8-connected, seeded from the four borders, index tiebreak, pit fills ONE ULP above the parent so every filled cell keeps a strictly descending path to its spill; the terrain heightmap itself is never written - the fill lives in its own array), terminal-basin qualification (depth >= 2 m AND area >= 10,000 px; the rest are pits filled through), D8 flow directions on the routing surface - FOR ANALYSIS ONLY, the reverted-as-carving landmine stated in the file - Kahn accumulation, the memoised destination walk crediting a terminal basin with TOTAL inflow, sea-reaching outlets ranked by drainage area with the outlet separation, main stems by max accumulation, mountain exits from the along-stem grade, lean tributaries, lean endorheic terminals, and the promoted giants (provisional routes computed as the reference did, not drawn - routing is a later task). WorldScale-denominated; Dir / Acc / Filled / FullFilled / BasinId / BasinInflow exposed so the caller can prove the invariants. "The sea" is the OCEAN body from the region layer: RegionLabeling.OceanMask - the 4-connected water component touching the border, on the CLASSIFY field (the water-side complement of the land contract). Enclosed lagoons, lake beds and island-fringe pockets are ordinary terrain to the router. DrainageTool (4 task-11 seeds at 8192, the eroded fields bit-identical to the 11 dumps) renders the log-scaled accumulation map and the promoted-candidates overlay (trunks cyan, endorheic giants orange, lean terminals red; nothing carved) and writes the accumulation .f32. Oracle, all passing: render AND classify fields bit-identical before/after the analysis (zero terrain cells written), no water added, full fill >= original everywhere with a non-ascending path to the border from every cell, ocean mask all below sea and on the border, dir/acc/candidates identical across two runs. Endorheic basins are the expected first-class output: on every seed the top giants out-drain the top trunks - the biggest drainages pool inland because erosion delivers the upland network only and cannot cross the flats. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013EY3ZTF6NwzF8ukBHQXSK7
72 lines
6 KiB
Markdown
72 lines
6 KiB
Markdown
# Core — math and data only
|
|
|
|
**Holds:** the column model, the material schemas, the scaling discipline, tooling path
|
|
resolution and the file-safety rails. Constants and contracts.
|
|
|
|
**Boundary: Core depends on nothing above it.** Not on `Server/`, not on `Client/`, not on
|
|
`Tools/`. The dependency arrow points one way into this folder and never out of it.
|
|
|
|
> ### ⚠ Additional boundary, tighter than the layer rule: **Core is engine-free.**
|
|
>
|
|
> No `using Godot;` anywhere in this folder. Core is plain C# — no `Node`, no `GD.Print`, no
|
|
> `ProjectSettings`, no engine types in any signature.
|
|
>
|
|
> **Two reasons, both load-bearing.** (1) D-049 commits to *"C# for fast iteration, with C++-ready
|
|
> seams… port path-by-path when settled and hot"* — the hot paths that get ported first are exactly
|
|
> the ones in here, and a type that names `Godot.Vector2` cannot cross that seam. (2) It keeps the
|
|
> column model testable and reviewable without standing up an engine.
|
|
>
|
|
> Where Core genuinely needs something the engine knows — the resolved `user://` directory — the
|
|
> engine layer **hands it in** (`ToolingPaths.Configure`), rather than Core reaching for it.
|
|
> If you find yourself wanting an engine type here, the type belongs one layer up.
|
|
|
|
## What is in here
|
|
|
|
| File | What it is |
|
|
|---|---|
|
|
| `Scripts/Column.cs` | ★★ **The load-bearing contract** (D-053). A column as run-length bands; `MaterialRun`; `RunOrigin`. Read its header before touching anything that stores world data. |
|
|
| `Scripts/ColumnGrid.cs` | The 2D grid of columns. Shape only — chunking and streaming are later phases. |
|
|
| `Scripts/MaterialKey.cs` | Material **identity** — a registry key, never an ordinal. |
|
|
| `Scripts/TerrainMaterial.cs` | A row in the terrain schema (D-054). |
|
|
| `Scripts/BuildingMaterial.cs` | A row in the building schema (D-054). |
|
|
| `Scripts/MaterialRegistry.cs` | Both registries, append-only, seed rows only. |
|
|
| `Scripts/RecipeRegistry.cs` | The transformation seam — **deliberately empty**. |
|
|
| `Scripts/GenerationScale.cs` | ⭐ The scaling discipline. `MapSize`, `ScaleFactor`, normalized offsets, the two frequency conventions. |
|
|
| `Scripts/WorldScale.cs` | ⭐ **The vertical yardstick.** The ONE metres↔raw conversion (251 m/unit). No literal `251f` anywhere else. |
|
|
| `Scripts/HeightCurve.cs` | ⭐⭐ The height-redistribution curve (v5), 7 bands. **Identity at and below sea.** |
|
|
| `Scripts/CurveKnots.cs` | The six INPUT knots — percentiles of the measured land CDF, plus the reference's for comparison. |
|
|
| `Scripts/CurveAnchors.cs` | The OUTPUT anchors — the storm-ladder elevations each band lands at. |
|
|
| `Scripts/TerrainDetailPass.cs` | Shelf micro-relief + the shelf-edge **knot warp**. Output-height only. |
|
|
| `Scripts/HydraulicErosion.cs` | ⭐⭐ **Droplet (hydraulic) erosion** (chat2/11) — the reference's pass ported VERBATIM: four governors (count, lifetime, carve cap, deposit cap) on a net-displacement ledger proven on exit, the sea clamp (below-sea read-only both ways), the cone brush shared by erode and deposit, the crater exclusion (inert until the carve exists). Engine-free, own PCG32, `WorldScale`-denominated (no literal 251). Render-map only — the caller (`Tools/ErosionPass`) owns the split and the flood guard. |
|
|
| `Scripts/DrainageAnalysis.cs` | ⭐⭐ **Drainage analysis** (chat2/12) — the reference's river-PLAN pass ported verbatim: priority-flood routing fill (one ulp above the parent, terrain never written), **D8 flow directions FOR ANALYSIS ONLY** (D8 was reverted as a carving technique), Kahn accumulation, outlets ranked by drainage area, endorheic terminals credited TOTAL inflow, promoted giants. Engine-free, `WorldScale`-denominated. "The sea" = the ocean body from `RegionLabeling.OceanMask`. |
|
|
| `Scripts/RegionLabeling.cs` | ⭐⭐ **The region-labeling layer** (chat2/07) — shared infrastructure. 8-connected land components on the CLASSIFY field; mainland = the centre component; per component id / size / centroid / hemisphere (by centroid) / isMainland. Pure, engine-free, C++-candidate; a **contract** downstream phases consume (islands first; biomes, placement, rivers, the crater later). The hemisphere convention lives here. |
|
|
| `Scripts/ToolingPaths.cs` | Every tooling path, env-overridable, resolved in one place. |
|
|
| `Scripts/FileSafety.cs` | The permanent file-safety rules, as throws rather than sentences. |
|
|
|
|
## The three rules this layer exists to make unbreakable
|
|
|
|
1. **Air is the top run.** There is no "air vs solid" height branch, anywhere, ever.
|
|
→ `Scripts/Column.cs`.
|
|
2. **Properties come from the registry, never from storage.** A run stores an identity.
|
|
→ `Scripts/MaterialRegistry.cs`.
|
|
3. **Nothing uses a raw pixel number.** Every distance is a fraction of `MapSize`.
|
|
→ `Scripts/GenerationScale.cs`.
|
|
4. **There is one metres-per-raw-unit number.** The prototype scattered `251` across three
|
|
duplicate constants and ~20 literals, and the generator never used the derived one at all.
|
|
→ `Scripts/WorldScale.cs`.
|
|
|
|
## Not here, and not by accident
|
|
|
|
- **No water.** Water is an overlay over the columns (levels-not-cells), never a band.
|
|
- **No biomes.** Biomes are a later *classification* of finished shape, not an input to it (D-049).
|
|
- **No algorithms** *beyond the height curve and the region layer*. Phase 2 added `HeightCurve` and
|
|
`TerrainDetailPass` here because they are pure, engine-free, C++-candidate math that defines the
|
|
world's elevation profile — a contract, not a tool's dial. chat2/07 added `RegionLabeling` on the
|
|
same grounds: region identity is a contract every later phase reads, and the flood fill is a hot
|
|
path. (The speck REVERT that uses it is a pass, and lives in `Tools/` — `RegionPass`.) Stratigraphy, feature passes, meshing
|
|
and run-splitting on dig are still later phases.
|
|
- **No erosion, rivers, water bodies, crater carve, coast shelf or offshore islets.** Later chat2
|
|
tasks; the curve is deliberately the only pass-2 element present.
|
|
|
|
→ `Design - Data - Column Model.md`, `Design - Data - Material Schema.md`,
|
|
`Design - Tooling - Scaling Discipline.md`
|