docs(workspace): index the new notes and refresh chunk streaming

This commit is contained in:
Serkyo 2026-08-03 03:12:56 +02:00
parent a7fd8dca3b
commit 824702f0fb
2 changed files with 7 additions and 1 deletions

View file

@ -39,6 +39,8 @@ Each subsystem note should name the design topic it implements (by title, e.g. "
- [`adr/0007-declarative-content-via-modding-api.md`](adr/0007-declarative-content-via-modding-api.md): declarative content loads through the modding API. - [`adr/0007-declarative-content-via-modding-api.md`](adr/0007-declarative-content-via-modding-api.md): declarative content loads through the modding API.
- [`adr/0008-split-coordinate-entity-positions.md`](adr/0008-split-coordinate-entity-positions.md): split-coordinate entity positions. - [`adr/0008-split-coordinate-entity-positions.md`](adr/0008-split-coordinate-entity-positions.md): split-coordinate entity positions.
- [`adr/0009-baseline-relative-sparse-chunk-persistence.md`](adr/0009-baseline-relative-sparse-chunk-persistence.md): baseline-relative sparse chunk persistence. - [`adr/0009-baseline-relative-sparse-chunk-persistence.md`](adr/0009-baseline-relative-sparse-chunk-persistence.md): baseline-relative sparse chunk persistence.
- [`adr/0010-net-crate-async-runtime.md`](adr/0010-net-crate-async-runtime.md): dedicated `net` crate with a confined async runtime.
- [`adr/0011-authority-stream-for-server-pushed-state.md`](adr/0011-authority-stream-for-server-pushed-state.md): a dedicated authority stream for server-pushed state.
- [`adr/template.md`](adr/template.md): template for new decisions. - [`adr/template.md`](adr/template.md): template for new decisions.
Subsystem notes: Subsystem notes:
@ -46,6 +48,8 @@ Subsystem notes:
- [`packs.md`](packs.md): data packs & resource packs (load order, layout, resolution). - [`packs.md`](packs.md): data packs & resource packs (load order, layout, resolution).
- [`rendering.md`](rendering.md): rendering & coordinate gotchas (Vulkan clip space, Blender/glTF import). - [`rendering.md`](rendering.md): rendering & coordinate gotchas (Vulkan clip space, Blender/glTF import).
- [`chunk_streaming.md`](chunk_streaming.md): chunk streaming and async worker pipeline. - [`chunk_streaming.md`](chunk_streaming.md): chunk streaming and async worker pipeline.
- [`meshing.md`](meshing.md): greedy meshing, the mesh worker pool, and frustum culling.
- [`diagnostics.md`](diagnostics.md): runtime statistics collection and the debug panel.
- [`save_format.md`](save_format.md): chunk persistence, region-file layout, save actor, and load pipeline. - [`save_format.md`](save_format.md): chunk persistence, region-file layout, save actor, and load pipeline.
Further subsystem notes are added here as systems are implemented and locked. Further subsystem notes are added here as systems are implemented and locked.

View file

@ -64,13 +64,15 @@ The server-side pump is `chunk_stream_task`; its client mirror is `client_chunk_
Each connected client is tracked by a `ClientStream` holding its `ChunkSink`, its current desired set (radius-clamped to `SERVER_MAX_RADIUS`), and its `sent` set. On each subscription, `desired_diff(previous, new)` yields the load list (`new previous`) and drop list (`previous new`); a `ChunkMessage::Drop` is emitted for every already-**sent** chunk that left the set. Newly-desired chunks are **not** sent immediately — chunk loads are async, so `ClientStream::flush` runs each tick and delivers every desired-but-unsent chunk that has since become resident, retrying on later ticks until the pool returns it. Each connected client is tracked by a `ClientStream` holding its `ChunkSink`, its current desired set (radius-clamped to `SERVER_MAX_RADIUS`), and its `sent` set. On each subscription, `desired_diff(previous, new)` yields the load list (`new previous`) and drop list (`previous new`); a `ChunkMessage::Drop` is emitted for every already-**sent** chunk that left the set. Newly-desired chunks are **not** sent immediately — chunk loads are async, so `ClientStream::flush` runs each tick and delivers every desired-but-unsent chunk that has since become resident, retrying on later ticks until the pool returns it.
Delivery is bounded by `MAX_DELIVERIES_PER_TICK` (32 chunks per client per tick). Encoding a chunk is the expensive part of `flush`, and a client whose subscription has just jumped can have hundreds of chunks pending at once; without a cap that backlog is encoded in a single tick and shows up directly as a tick overrun. The budget counts chunks **actually encoded**, so a tick where most of the desired set is still in flight is not charged for work it did not do. The fixed count is a placeholder for a time budget, which becomes necessary once per-chunk cost varies with LOD.
### Self-contained payloads (all-air diff) ### Self-contained payloads (all-air diff)
`ChunkMessage::Chunk` carries a `ChunkData` (the sparse, baseline-relative form; see [ADR-0009](adr/0009-baseline-relative-sparse-chunk-persistence.md)). Because the client runs **no** worldgen (the server owns world content; worldgen never runs client-side), it cannot reconstruct a worldgen baseline to diff against. So delivered chunks are diffed against an **all-air baseline** (`Chunk::default()`): the edits become the chunk's full non-air content, and the client materializes each payload against its own all-air `Chunk::default()`. This makes every delivery self-contained, at the cost of not exploiting the deterministic baseline for compression — a compression concern deferred to the LOD/compression pass. `ChunkMessage::Chunk` carries a `ChunkData` (the sparse, baseline-relative form; see [ADR-0009](adr/0009-baseline-relative-sparse-chunk-persistence.md)). Because the client runs **no** worldgen (the server owns world content; worldgen never runs client-side), it cannot reconstruct a worldgen baseline to diff against. So delivered chunks are diffed against an **all-air baseline** (`Chunk::default()`): the edits become the chunk's full non-air content, and the client materializes each payload against its own all-air `Chunk::default()`. This makes every delivery self-contained, at the cost of not exploiting the deterministic baseline for compression — a compression concern deferred to the LOD/compression pass.
### Client application ### Client application
The client subscribes with its own `LOAD_RADIUS` (so the server's per-client resident set matches what the client keeps) whenever its center chunk changes. It drains deliveries under a per-frame meshing budget: `ChunkMessage::Chunk` → materialize → `generate_mesh``insert_mesh` (skipping empty meshes); `ChunkMessage::Drop``remove_mesh`. It **also** evicts chunks outside `LOAD_RADIUS` locally, independent of the server `Drop`, so memory stays bounded even if the server is slow. The client subscribes with its own `LOAD_RADIUS` (so the server's per-client resident set matches what the client keeps) whenever its center chunk changes. Deliveries are drained under per-frame budgets: a `ChunkMessage::Chunk` is materialized and the position (plus its six neighbours) is queued for meshing, while a `ChunkMessage::Drop` removes the mesh. Meshing itself runs on a worker pool rather than inline, so the client retains chunk voxels after upload; that pipeline is described in [`meshing.md`](meshing.md). The client **also** evicts chunks outside `LOAD_RADIUS` locally, independent of the server `Drop`, so memory stays bounded even if the server is slow.
## Multiplayer ## Multiplayer