Sparse discoverable islets from a low-frequency ocean noise layer, seeded
resolved+7607 at 14 undulations/island (~585 px blobs).
Placed by LERPING the seabed toward a target crest (34 m raw above sea)
rather than adding to it, so an islet can surface at any ambient depth
instead of only where the seafloor happens to be shallow. After the curve's
toe compresses them they stand 5-8 m above the water: low, sandy, ringed by
beach -- which is what the existing biome rules make of that height, with no
biome-rule change.
THE THREE CONSTRAINTS, each by construction rather than by hope:
Never merges with the mainland. The raise is EXACTLY zero wherever the
ambient water is shallower than 14 m, so any continuous path from the
mainland shore to an islet must cross that depth contour, and every pixel
on it is untouched water. Measured: 0 of 13 islets merged, closest
approach 78 px.
Never touches the Trench. A distance mask zeroes the layer by 0.86 of
half-map, and the ramp starts at 0.90. Measured max islet reach 0.795.
All four corners stay below sea.
Never spawns inland. Depth alone is not a test -- a deep lake and the
carved crater bay are also below sea. The pre-Trench falloff is the honest
discriminator (mainland coast sits near f = 0.66; islets need f > 0.72),
and it is axis-invariant, because elongation moves WHERE a given f occurs,
not the f at which land ends.
Two bugs found and fixed by measuring instead of trusting the first run:
1. The density dial treated [-1,1] as the noise's actual range. Simplex
is concentrated well inside it -- this field measures 0.050..0.958 --
so "top 6%" resolved to a threshold almost nothing cleared: the first
build raised 171 px on the entire map, none above sea. The threshold is
now CALIBRATED against the field's own distribution (quantile over a
1M-sample stride grid, deterministic from the seed), so the dial means
what it says whatever FastNoiseLite returns.
2. At 26/island the layer produced 77 islets under 200 px -- scatter, not
"a handful". Retuned to 14/island at density 0.02: 13 islets of
200-4792 px.
The pass prints its own islet area, so every run says what it did.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| BiomePalette.cs | ||
| BiomePalette.cs.uid | ||
| BlockData.cs | ||
| BlockData.cs.uid | ||
| BlockRegistry.cs | ||
| BlockRegistry.cs.uid | ||
| BLUEPRINT_FORMAT.md | ||
| BlueprintFormat.cs | ||
| BlueprintFormat.cs.uid | ||
| BlueprintWriter.cs | ||
| BlueprintWriter.cs.uid | ||
| ChunkData.cs | ||
| ChunkData.cs.uid | ||
| ConfigManager.cs | ||
| ConfigManager.cs.uid | ||
| Constants.cs | ||
| Constants.cs.uid | ||
| Enums.cs | ||
| Enums.cs.uid | ||
| MapDataParser.cs | ||
| MapDataParser.cs.uid | ||
| MarchingCubes.cs | ||
| MarchingCubes.cs.uid | ||
| MATH_MARCHING_CUBES.md | ||
| README.md | ||
/Core/Scripts
Pure C# data structures, shared enums, and static maths. Compiled into the shared assembly used by
both /Server and /Client.
"Pure data, zero state." These scripts define what things are and how to calculate them. They never track live game events — who is online, which chunks are loaded, what time it is.
What's actually here
Voxel materials
BlockData.cs— struct describing one block type (ID, name, IsSolid, BaseColor).BlockRegistry.cs— the byte-ID master list (AIR0,BEDROCK,STONE,DIRT,SAND, the three grasses,SNOW,WASTELAND_DIRT,ASPHALT) with a safeGetBlocklookup.BiomePalette.cs— decides which material sits where, given biome, depth, and whether the column is roadbed. Two paths on purpose: an integer classification that decides what is stored in each voxel, and a float-depth version used for rendering that returns the two materials either side of a boundary so colours fade rather than snap.
⚠ Note that BlockRegistry and the mesher's colour table hold different RGB values for some
blocks. The mesher's table is what you actually see; BlockData.BaseColor is currently unused by
rendering.
Shared identifiers
-
Enums.cs—Biome,TownTier,MapHalf,RoadTier.⚠
BiomeandTownTierare the.datwire format (u8 in the v2 container, i32 in legacy v1). They are declared without explicit values, so each member's ordinal is the number written to disk. Append only, at the end — never reorder or insert. The v2 reader range-checks ordinals so drift fails loudly at parse time, but only the append-only rule keeps old files meaning the same thing. Legacy v1 has no gate and no validation at all.RoadTieris exempt: road tiers live in separate sections of the file, so it is never serialized.
World data
BLUEPRINT_FORMAT.md— the byte-accurate.datcontainer contract (v2 tagged sections + the v1 legacy summary). Read this before touching the writer or parser.BlueprintFormat.cs— the single registry of v2 constants: magic, version gate, section tags (FourCC), validation bounds, re-encode sentinels.BlueprintWriter.cs— writes aWorldBlueprintas a v2 file. Blueprint-typed on purpose: the map generator and the round-trip harness are both just callers.MapDataParser.cs— decodes a.datblueprint into aWorldBlueprint(heightmap, biome map, towns, four road tiers, and — v2 only — the embedded generation params, per-town highway-node flag, and the optional water-bodies data:WaterBodyIds,WaterBodiestable,WaterSurfaceQ). Dispatches on the first byte: v2 tagged-section files get validation (version gate, size bounds, section-length and ordinal range checks); legacy v1 files still load, intact, with a deprecation warning. Nothing at runtime consumes the water data yet.ChunkData.cs— one chunk's density and block-ID fields,+1padded on every axis so the mesher can reach into the neighbouring chunk, plus the per-column data the renderer needs.Constants.cs— chunk dimensions,ISO_LEVEL,VOXEL_SCALE, and the visual/road tunables (material blend band; per-tier road width, shoulder, grade smoothing and surface).
Maths
MarchingCubes.cs— density field →ArrayMesh, with analytical normals and deterministic integer-keyed vertex welding.MATH_MARCHING_CUBES.md— an explainer of the algorithm.
Rules
- No Godot node inheritance. Pure classes, structs and statics.
- No
_Process/_Ready. Nothing here is attached to a live scene object. - Dependencies flow inward only.
/Serverand/Clientreference/Core;/Corenever references them.