Three-way prep session (Jeroen + lead + Tyre) for the map-handler revision: Jeroen's design outline captured verbatim, two clarification rounds, Tyre's governance-delta/implications pass, brief co-written and ratified (zero misrepresentations, zero blocking gaps), signed off by Jeroen with three edit rounds (vocabulary repair tile->gridunit, client cache-store question with SQLite fact base, explicit DQR/ticket deprecation sweep as gated deliverable). Workshop: 5 seats (Dudley/Araminta/Stig/Tyre + Troblum r2), 2 rounds + lead interview extendable at Jeroen's call, round 1 gated on measurements T-1177/T-1178/T-1154/T-1179 (T-1180 non-gating). T-1176 in_progress with gate blocker edges; T-1154 repurposed as measurement (3) and set ready. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6.6 KiB
title, description, type, status, workshop, created
| title | description | type | status | workshop | created |
|---|---|---|---|---|---|
| Body Map Viewer — Jeroen's Design Outline | Verbatim capture of Jeroen's opening outline for the map-handler revision (T-1176 prep session, round 1) | workshop | active | body-map-viewer | 2026-07-25 |
Jeroen's Design Outline
Captured 2026-07-25, opening the three-way prep session (Jeroen, lead, Tyre).
His instruction accompanying it: "before we get to discussing the actual game
implications … read my text and ask for clarifications if I was ambiguous or
incomplete", and "Let's discuss/askuserquestion this properly the three of us
until I sign off on the briefing document." Clarification rounds follow in
clarifications.md.
Vocabulary repaired at Jeroen's request (sign-off round) to prevent context
confusion, per his round-A ruling (tile = the 1×1 m ground unit only; gridunit
(at zoom level) = the per-step data cell). Exactly two replacements were made,
each marked [was: tile(s)]: the "n by n grid", and the hydrology "two heights"
sentence. The two uses he ruled legitimately tile ("10px per tile", "largest to
visible tile") are untouched. Reading note for the same reason: where "pixel"
below means the data cell rather than a literal screen pixel (e.g. "what is in
each pixel", "tier0 pixels"), read it as gridunit; the 1-gridunit-per-screen-px
ideal vs ~5×5 fallback is recorded in clarifications.md. No other wording is
edited.
How I would build this
to honor late/lazy compute principles we will be designing this with LoD information exposure and generation in mind. In essense the rule is: don't calculate inside the game loop what is not needed for the game state: smart-precaching is okay, but it is not blocking for the user output. We cache calculated results so we don't recalculate things we already have (smart cache, dependent on zoom level and player position (atlas application viewport counts as player position. player is the focus, both character location as well as disembodied atlas usage) A function of detail level, time and distance determine the ttl. With this I mean, we keep always keep the global level calculations for each body to make atlas navigation snappy after first calc, but everything under that gets a shorter ttl as the values of detail level and the player distance increase.
architecture:
-
pixel drawing is a function of the client, not the server. There exists a map drawing component inside the client that can deal with drawing maps, zooming them and applying overlays.
-
content determination is a server function. The server sends what is at a given pixel (world coordinate) that is in screen at that zoom level
-
zoom levels are stepped:
- there is global zoom, which is the atlas opener screen for a body
- one zoom in we normalize to the highest zoom level of the dynamic set. this is a n by n grid of gridunits
[was: tiles]. always the same size on the smallest axis of the viewport, adding more pixels in the larger axis (widescreen support) - every subsequent zoom clicks step through a similar viewport bounding down, right up to the point the smaller axis is, say 10px per tile so we can show some detail if needed later.
- the amount of steps that make sense from largest to visible tile is to be discussed in the workshop and will also play a role in how we break up the load of the deterministic algos that generate the content
-
on opening of a body, the following happens:
- the heightmap and relevant inputs are read
- the seed generators run to do water distribution and global calculations that are relevant. (later, settlement generation and placement, roads, railroads, etc will also be in scope) We basically generate everything to show the world, it's main infrastructure, setllements and POIs
- here is where it starts getting tricky to do good code and step separation; the code also generates enough biome and coastline and height generation to fill out a pixel for each screen pixel. We probably want to do this at 4k resolution so we have spare room to scale out the map on larger monitors. This does not get drawn, this determines what is in each pixel: average biome, average ground type, height, is the pixel predominantly flooded or not, is the pixel predominantly frozen or not. This at the same time serves as seed informaation for the deeper cascade, as well as as input for the client. The server needs to be smart about this: if a river ends in a basin that is above sealevel, a lake will fill, which will overflow to a new path to the sea, or be such a large inland body that it maintains it's own water cycle. a river may carve a gorge through higher terrain over time when no easier overflow path is available. This will need to be properly communicated to the client and the underlying generators, since that will end with two heights in the same gridunit
[was: tile]and cliff forming. I feel this behavior should be governed by the moisture and climate properties of the body. - the client receives this pixel information (think: biome: grassland, settlement: null/"name here", river: null/"name here/unnamed", frozen: true/false, flooded: true/false, sea: true/false, etc, etc) It then smartly uses that information to color pixels, tween rivers/roads, apply settlements and names to the map and overlays, etc etc. What is shown and drawn is a map art function, not a data function.
-
on zooming a step the following happens:
- the server grabs the bounds of the data canvas (separate from the view canvas) (I think we may also want to land on a 4k window to make sure the client has enough for all monitors)
- with these bounds the server pulls the tier0 (atlas body level) pixels and their information that cover the data canvas and runs the deterministic generation to again fill out the information for all the pixels needed to send to the client (and again also serve as the seed input for tier2 generation) At this point the exact position of the river, biomes, coastlines, water etc etc are determined at pixel level for this layer.
- the client acts in the same pattern as above, but with different classes of content to draw at some point (at low enough zoom, a green forest biome may start showing clearings and ponds or such - to be determined and tinkered with)
- When the sizes become true, items start taking more than 1 pixel: at 50 km, a 1km wide settlement will stretch across pixels for example, and a river will, with varying width and maybe dependent on climate and rain/floodplane cycles or frost change shape and texture
There may be elements I miss in this, which is why we co-write the plan. or things that need to be done differently.