Every README was read first, checked against the code in its directory, then rewritten to describe what the code actually does now. Corrected throughout: map size is config-driven (8192 default) not a fixed 4096; chunks are 24x24x256 not 32x32; road carving is implemented for all four tiers, not a 'next step'; Data/ and Resources/ are empty, not populated. Also fixed MATH_MARCHING_CUBES.md, which documented the density sign convention exactly backwards — it claimed positive was underground, where the code treats positive as above the surface and counts a corner inside when density < iso. Getting that backwards inverts every normal, a bug this project has hit before. The root README now carries accurate run steps: F5 runs the map generator (not the game), F6 on Scenes/Main.tscn runs the 3D world, and ChunkRadius is a load radius that should be dropped to 4-8 while iterating. Docs only. No code changed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
61 lines
3.4 KiB
Markdown
61 lines
3.4 KiB
Markdown
# /Tools/Scripts — generation logic
|
||
|
||
C# backend for the offline developer tools. Decoupled from the live server and client.
|
||
|
||
## `MapGenerator.cs`
|
||
|
||
Generates the entire 2D blueprint. Roughly in order:
|
||
|
||
1. **Config** — reads `ServerConfig.json`, which sets `MapSize` (8192 by default) and the crater
|
||
radius. The `MapSize = 4096` field initialiser is a fallback that is immediately overwritten.
|
||
2. **Topography** — FastNoiseLite base height plus a mountain spine, minus a squircle distance
|
||
falloff, giving a guaranteed island. Noise frequency is divided by `scaleFactor`
|
||
(`MapSize / 1024f`) so terrain features stay the same real-world size at any map profile.
|
||
3. **Sea level and water** — temperature-driven sea level; flood fill separates true ocean from
|
||
inland lakes; a mainland fill guarantees one contiguous landmass.
|
||
4. **The crater** — placed along the northern coast and carved to below sea level, but only out to
|
||
**80 % of its radius**, which guarantees a landbridge rather than severing the island.
|
||
5. **Biomes and towns** — biome zoning by height and temperature; tiered town placement (Capitol,
|
||
Hubs, Villages, Outposts, POIs) filtered by slope, water proximity and spacing.
|
||
6. **Roads** — see below.
|
||
7. **Export** — writes the `.dat` blueprint, then renders the PNG snapshot.
|
||
|
||
### The road network
|
||
|
||
`AStarGrid2D` over the whole map at one node per pixel. Mountains are made expensive rather than
|
||
impassable (`1 + elevation³ × 400`), water and the crater are marked solid.
|
||
|
||
- **Continental loop** — highway nodes sorted by radial angle and connected in a ring.
|
||
- **Mountain branch** — a spur from the loop to the snow hub.
|
||
- **County roads** — Prim's algorithm daisy-chains remaining towns onto the network. Villages become
|
||
Rugged roads, everything else Trails.
|
||
- **Abandon protocol** — a town further than 8 % of the map from the network is skipped rather than
|
||
pathed to, so one unreachable outpost cannot hang generation.
|
||
- **Smoothing** — every path is decimated with Ramer–Douglas–Peucker (tolerance 4.0) then smoothed
|
||
with 4 Chaikin passes.
|
||
|
||
⚠ **This is the project's dominant performance problem.** At 8K the grid is 67 million nodes, and the
|
||
weight-setup pass touches every one before the first path is requested. The `await` yields between
|
||
stages cannot interrupt a single engine-side `GetPointPath` call, so a long path still blocks. Full
|
||
regenerations frequently get abandoned.
|
||
|
||
### The PNG snapshot
|
||
|
||
`SaveMapSnapshot()` builds an offscreen `SubViewport` in code rather than relying on the scene's
|
||
layout, because Godot's UI layout engine will otherwise crush a 4096+ render down to the editor
|
||
window size. A `MapDrawProxy` control re-issues the `_Draw()` calls into that viewport — `GetImage()`
|
||
captures only the base texture and would otherwise miss the roads and towns entirely — and the code
|
||
awaits two `RenderingServer.FramePostDraw` signals so the GPU has actually painted before the image
|
||
is read back.
|
||
|
||
Road colours on the snapshot, useful for identifying a road: **red** = Highway, **black** = Branch,
|
||
**dark brown** = Rugged, **light brown** = Trail.
|
||
|
||
### Outputs
|
||
`MapData_Seed_<seed>.dat` and `Map_Seed_<seed>.png`, both to `user://`.
|
||
|
||
## Rules
|
||
1. **No magic numbers.** Distances, radii and thresholds derive from `MapSize` or `scaleFactor`, so
|
||
the generator behaves identically at 4K and 10K.
|
||
2. **Respect the GPU.** Anything exporting visual data must `await` the appropriate frame signals
|
||
before reading pixels back.
|