Byte-accurate v2 contract (magic/version, tagged sections, registered FourCC table, validation rules, re-encode sentinels, extension path) plus the v1 legacy summary — v1 stays live per the safety-net plan. READMEs updated additively: parser dispatch, dual-write outputs, harness usage, server params cross-check, wire-format hazard rewording (u8 on v2 path, range-checked; append-only rule unchanged). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
56 lines
3.4 KiB
Markdown
56 lines
3.4 KiB
Markdown
# Server Module
|
||
|
||
Authoritative world building. Turns the static `WorldBlueprint` in RAM into physical 3D chunks. In a
|
||
future multiplayer setup this is the side that dictates terrain and ships chunk data to clients.
|
||
|
||
## `ServerChunkManager.cs`
|
||
|
||
Attached to the `World` root node of `Scenes/Main.tscn`. Runs the whole 3D world at boot.
|
||
|
||
### Startup
|
||
1. Loads `ServerConfig.json` and the seed's `.dat` blueprint (v2 or legacy v1 — the parser
|
||
dispatches automatically; see `Core/Scripts/BLUEPRINT_FORMAT.md`).
|
||
2. **Cross-checks the blueprint's embedded params** (v2 only) against the config and logs a
|
||
prominent `BLUEPRINT/CONFIG DESYNC` warning if the seed or MapSize disagree — a config edited
|
||
after generation is loud now, not silent.
|
||
3. **Finds the Capitol** in the parsed town list and uses it as the world origin point.
|
||
4. Converts its pixel position to chunk coordinates (`pixel / CHUNK_SIZE`).
|
||
5. Builds a `(2 × ChunkRadius)²` grid of chunks around it — **synchronously, all at boot**.
|
||
6. Teleports the `Camera3D` to 120 m above the Capitol, looking down.
|
||
|
||
⚠ **Two things to know about startup.** The chunk grid is built in one blocking pass with no
|
||
streaming or unloading, so `ChunkRadius` directly controls boot cost — 32 means 4,096 chunks and
|
||
roughly 3.6 GB. And the camera `LookAt` points straight down, which is a degenerate case: the up
|
||
vector ends up parallel to the view direction, so camera roll is undefined and Godot logs a warning.
|
||
|
||
### Per-chunk generation
|
||
- **Road culling first.** Only the road segments whose bounding box reaches this chunk are kept,
|
||
each tagged with its `RoadTier`. The padding is derived from the widest shoulder any tier has plus
|
||
a margin, so widening a road cannot silently truncate it at chunk edges.
|
||
- **Surface height per column** (`GetExactSurface`) — the blueprint height scaled into the chunk's
|
||
usable vertical band, then modified by any road carving.
|
||
- **Density per voxel** — `(y − surfaceY)` normalised by the local slope, giving a signed distance to
|
||
the surface. Positive above, negative below.
|
||
- **Block IDs per voxel** via `BiomePalette`, plus the per-column data the renderer needs.
|
||
- Hands the finished chunk to a `ChunkRenderer`.
|
||
|
||
### Road carving
|
||
All four tiers carve, each with its own character (widest and smoothest for highways, narrow and
|
||
terrain-hugging for trails — values in `Constants.cs`).
|
||
|
||
For each column, the carve finds **the nearest road whose shoulder actually reaches it** — not simply
|
||
the nearest road, since tiers have different reach and a nearby footpath must not shadow a highway
|
||
still covering the column. It then reads the roadbed height at the closest point *along* that
|
||
segment, blending between a straight ramp between the segment's endpoints ("holds a grade") and the
|
||
terrain directly beneath ("hugs the land") according to the tier.
|
||
|
||
Inside the road radius the column is flattened to that height and flagged with the tier's surface
|
||
material; out to the shoulder radius it eases back to natural ground with a smoothstep.
|
||
|
||
`HeightAtPixel` samples the heightmap **bilinearly** — road path points are fractional, and nearest-cell
|
||
sampling produced a metre-scale staircase along the roadbed.
|
||
|
||
## Not here yet
|
||
No chunk streaming or unloading, no collision, no networking, no player. The "server" is currently a
|
||
node in the same scene as the renderer — the server/client split is structural, not a process
|
||
boundary.
|