Home Visibility, Maps & Coordinates

Visibility, Exploration Maps, Coordinates & Inventory


1. Summary

Three related systems define what a player perceives and what the server sends them:

System Question it answers Primary driver
Network horizon (AOI) Which live entities get tick updates to this client? Performance
Exploration knowledge Which terrain and static features does this player know? Gameplay / progression
Cartography (skill + ledger) Permanent character knowledge; map items are inputs and trade goods Progression / economy / social

These must stay conceptually separate but compose when building each client's view. Sending every player and NPC in the entire Area to every client is not viable at 30–60 Hz — a horizon (area of interest) is required. The cartography ledger (§4) is the permanent fog-of-war mask; live entities still require AOI.

World position is modeled as (x, y, z, w) with t reserved at 0 until a future design pass (§6).


2. Network Horizon (Area of Interest)

2.1 Recommendation: Yes — mandatory from Phase 1

There is no need to transmit full updates for distant entities. Every successful MMO uses interest management (AOI). Without it:

  • Bandwidth scales O(players × entities) instead of O(players × nearby entities)
  • Encode cost on the server becomes the bottleneck before sim does
  • 100 players × 500 NPCs @ 60 Hz is untenable; 100 × ~15 nearby is fine

Rule: A client receives high-frequency tick deltas only for entities inside their network horizon. Everything else is omitted (not even “stale” updates).

2.2 Layered rings — omnidirectional

The character looks all around — no forward-facing cone for AOI or exploration. Interest zones are cylindrical or spherical around the observer's position (x,y,z):

        top-down (all directions equal)

              beyond
         ╭─────────────────╮
         │    horizon      │
         │   ╭─────────╮   │
         │   │  core   │   │
         │   │    ●    │   │  ← player; radius, not facing
         │   ╰─────────╯   │
         ╰─────────────────╯
Ring Radius (tunable) Update rate Contents
Core scale-aware (§2.3) Every sim tick (30–60 Hz) Positions, combat state, animations, projectiles
Horizon 2× core (typical) 5–10 Hz or on change Position + identity only; no fine combat detail
Beyond outside horizon None No entity stream; optional ambient events (see §2.5)

Radii are per-Area config and may scale with observer body size class. Cartography skill does not extend combat AOI — only map revelation efficiency (§4).

Implemented (2026-07-11): entity AOI uses horizontal radius AOI_CORE_RADIUS_M (32 m) and vertical half-extent AOI_Z_EXTENT_M (6 m) — entities on adjacent z-bands (platforms, cliffs) are visible; distant floors are filtered. See crates/sim/src/aoi.rs query_radius_z.

2.3 Multi-scale spatial grid (decided)

A single fixed chunk size cannot represent a child-sized human, a giant monster, and a city building equally well. Use a hierarchical grid with a small micro-cell base and larger macro-cells for big footprints and terrain LOD.

Scale classes

Class Example entities Footprint (indicative)
Tiny Child, small creature, familiar ≤ 1 m
Small Human adolescent 1–2 m
Medium Adult human, wolf 2–4 m
Large Horse, ogre 4–12 m
Huge Giant, dragon, house 12–64 m
Structure Building, wall segment, terrain tile 64 m+

Grid levels

Level Cell size (default) Used for
L0 micro 1 m Tiny/Small/Medium entity AOI, fine exploration reveal
L1 meso 8 m Large entities, interior rooms, combat clustering
L2 macro 64 m Huge entities, buildings, terrain blocks, map LOD

Rules:

  • Every entity registers in all levels its axis-aligned bounding volume touches
  • AOI subscription: player at L0 cell + rings in all directions; also subscribe L1/L2 cells overlapping horizon radius
  • Giants span many L1/L2 cells — one entity, many grid keys; fan-out uses entity keys, not point sampling
  • Buildings / terrain are static at L2 (and L1 for doorways); streamed when cartography or AOI includes that cell
  • Per-Area manifest can tune cell sizes (dungeon: smaller L2; overworld: larger L2)
World position (47.3, 12.8, z=2)  →  L0 (47,12)  L1 (5,1)  L2 (0,0)   // example floor

Giant bbox 48m × 40m              →  occupies L2 cells in 1×1 or more
Child bbox 0.8m                   →  single L0 cell

Why this satisfies the scale requirement

  • Small characters resolve to 1 m cells — movement and reveal are precise, not swallowed by 32 m buckets
  • Giants don't force the whole world onto 1 m grids — they register at L1/L2 without per-tick full-map scans
  • Buildings and terrain live at macro levels; micro exploration still records "I walked past this wall" at L0 for cartography

Implementation sketch:

CellKey { area: w, level: L0|L1|L2, cx, cy, cz }
EntityId → set<CellKey>   // from bbox at each level
PlayerId → subscribed cells = omnidirectional horizon ∩ union of levels
Per tick: dirty entities fan-out to players subscribed to any overlapping cell

2.4 Spatial indexing (summary)

  • Omnidirectional radius + hierarchical cells — not a forward cone
  • Cell crossing triggers subscribe/unsubscribe — amortizes work across ticks
  • Cartography revelation uses primarily L0 (and promotes aggregates to L1/L2 for map display); AOI uses all relevant levels

2.5 What about “I know the map but nothing is near me?”

Exploration knowledge (§3–4) does not imply live entity streams. A player with a full cartography ledger for an Area still only receives AOI-filtered entity updates. Their map view shows ledger terrain; live dots for players/NPCs appear only in core/horizon.

Optional ambient channel (low bandwidth): non-positional hints beyond horizon — e.g. “distant explosion”, weather front, faction alert. Gossip, not per-entity state.

2.6 Join, leave, teleport

  • Entity enters horizon: reliable Spawn snapshot (full component subset), then tick deltas
  • Entity leaves horizon: Despawn (client keeps exploration data; removes live entity)
  • Teleport (w changes): only when changing realm (OSS); within one world, use movement/portals (01)

2.7 Protocol impact

  • Per-client interest set maintained server-side (authoritative)
  • Tick packets are per-client filtered — same sim, different views
  • Metrics: interest_set_size, bytes_per_client_tick, subscription_churn

2.8 Design feedback

Idea Verdict
Horizon for performance Strong yes — non-negotiable for targets in 00-initial-vision.html §5
Send all entities “just in case” No — wastes bandwidth; clients cannot use the data
Same radius for map fog and network No — decouple; fog is knowledge, horizon is presence
Horizon only (no exploration) Possible for Phase 1 spike; add fog in Phase 2

| Omnidirectional AOI | Yes — no facing requirement; radius-based | | Single global chunk size | No — use L0/L1/L2 hierarchy (§2.3) | | Horizon only (no cartography) | Possible for Phase 1 spike; ledger in Phase 2 |


3. Omnidirectional exploration reveal

When a character moves or stands, they perceive all around them — same as AOI philosophy.

3.1 Revelation sweep

Each revelation pass (on cell entry or periodic while idle):

  • Center on (x,y,z); sweep 360° horizontally and configured z bands (current floor ± adjacent layers)
  • Mark L0 micro-cells within reveal radius R_reveal
  • R_reveal defaults from body size class; Cartography skill increases radius and/or cells-per-tick efficiency (§4.3)
  • Optional later: line-of-sight raycast to trim cells behind solid L2 walls — not required for Phase 1

3.2 What gets revealed

Data Stored in ledger
Terrain type / walkability L0, aggregated to L2 for map UI
Static props & resource nodes L0 cell markers
Building footprints L2 when any exterior L0 touched
Labels (town names, POI) on first L0 of POI or from map item annotations

4. Cartography — skill, ledger & map items

Cartography is a first-class character skill and a permanent knowledge store, not just consumable scrolls.

4.1 Two layers: ledger vs items

Layer Persistence Role
Cartography ledger Permanent per character, central-persisted Source of truth for "what I know" about each Area w
Map items Physical inventory objects Loot, trade goods, quest rewards; input to ledger

Effective map view = cartography ledger for Area w (always). Map items in bags are optional until added to cartography.

4.2 Adding a map to cartography (decided)

When a player buys, finds, loots, or receives a map item, they get a prompt (TUI / CLI: flatland cartography add <item>):

  • Add to cartographypermanent merge into ledger; item may be consumed or kept (item template flag)
  • Keep in inventory only — tradeable; ledger unchanged until they add later

Merge is server-authoritative (§4.6). Once added, knowledge persists across sessions (death impact TBD in 07-death-and-respawn.html).

4.3 Cartography skill

Trainable skill affecting exploration efficiency and crafted map quality:

Skill effect Low skill High skill
Reveal radius R_reveal base +up to 50%
Cells revealed per movement tick 2–3× (efficient path mapping)
Crafted map region size small bounds large bounds
Map detail / annotation slots coarse fine labels, danger marks
Craft time & material cost higher lower
Sale value / NPC recognition low high

Skill XP from: walking unrevealed L0 cells, completing surveys, crafting maps, first-time Area discovery.

4.4 Map item sources (decided)

Maps enter the economy through:

  • Player craft — from own ledger subset (Cartography skill gate)
  • Player trade / sale — physical item then add-to-cartography
  • NPC vendors — regional maps, partial Areas
  • Quest rewards — scripted regions
  • Monster drops — rare survey loot
  • World placement — chests, hidden caches (Area-authored)

All map items are central-signed payloads (§4.5). Forgery impossible without server.

4.5 Map item payload (server-signed)

MapItemData {
  cartographer_id,          // player id or "world" for authored drops
  area_id (w),
  created_at_tick,
  bounds: ChunkRegion,      // L0/L1/L2 region
  chunk_bits: CompressedBitmap,
  annotations: Vec<Label>,
  skill_tier,               // quality at creation
  consume_on_add: bool,     // destroy when added to ledger?
  signature: CentralSig,
}
  • Physical item — inventory space (§5); droppable, tradable
  • Add to cartography — permanent ledger merge; item consumed if consume_on_add

4.6 Ledger merge rules

CartographyLedger {
  character_id,
  areas: Map<AreaId, AreaCartography>,
}

AreaCartography {
  l0_bits: SparseBitmap,      // primary
  l2_summary: SparseBitmap,   // derived for UI zoom-out
  annotations: Vec<Label>,
  version,
}

When adding map M or revealing by walking:

for cell in M.cells:
  ledger[cell] = merge(ledger[cell], M[cell])
  • Prefer higher reveal_strength / skill_tier
  • Annotations: union; conflicts show both or higher-tier wins
  • Walking always upgrades own reveal strength for cells visited

4.7 Player-crafted maps for sale / share

  1. Select region ⊆ ledger for Area w
  2. Skill + station check → mint MapItemData with quality tier
  3. Sell on trade, give to alt, drop for others to add to cartography
  4. Enables knowledge economy — explorers monetize routes without sharing live AOI

4.8 Design feedback

Idea Verdict
Permanent cartography ledger Yes — decided
Optional add-from-map-item Yes — sharing & rewards
Cartography skill Yes — efficiency + craft quality
Maps as drops / NPC / quest Yes — progression hooks
Death clears ledger No — ledger persists (07-death-and-respawn.html)

5. Complex Inventory

5.1 Design intent

Inventory is a management game, not a bottomless list. Players make meaningful choices about what to carry — including maps, tools, resources, and consumables.

5.2 Dimensions of complexity (proposed)

Mechanic Description
Weight Encumbrance affects movement speed, stamina regen
Volume / slots Containers have grid or slot counts; items have shapes (later)
Container nesting Bags inside bags — depth limit
Equipment layers Armor slots, accessories, hotbar, quest items
Item instances Durability, charges, unique affixes
Binding BoP, BoE, BoU — affects trade
Sorting / tags Player organization; agent CLI inventory list --tag map
Bank / stash Central-persisted overflow (Phase 2+)
Loot overflow Drop to ground or mail if full — player problem

5.3 Map items in inventory

  • Occupy scroll/map slot class; quality tiers vary size
  • Atlases combine regions but weigh more
  • Unadded maps are trade goods; ledger holds permanent knowledge after add

5.4 TUI / cartography commands

  • Cartography panel — per-Area coverage %, ledger view, pending map items
  • World panel — fog from ledger; live entities on explored cells in AOI only
  • Agent CLI: flatland cartography show --area w, flatland cartography add <item>, JSON export

5.5 Server authority

All container mutations are transactions on central or area inventory service:

  • Atomic move, split stack, craft consume, equip
  • Validation: capacity, weight, permissions, combat lockout
  • Full audit log for high-value items

5.6 TUI requirements (inventory)

  • Multi-pane inventory: equipped | bags | weight bar | quick filters

  • Map items: preview region bounds before read

  • Agent mode: flatland inv move, structured JSON graph of containers

  • Map items: preview bounds; prompt add-to-cartography vs keep


6. World coordinates (x, y, z, w)t deferred

6.1 Definition (decided)

Dim Name Type Meaning
x easting f32 or fixed Horizontal axis within Area
y northing f32 or fixed Horizontal axis within Area
z elevation / layer i32 or f32 Vertical — floors, caves, sky layers
w realm / deployment RealmId0 = live world; separate OSS deployments use other ids Which Area shard
t time slice i64 Fixed at 0 for all gameplay until redesigned
struct WorldCoord {
    x: f32,
    y: f32,
    z: i32,
    w: AreaId,
    t: i64,  // always 0 for now; field reserved in protocol
}

Use w (not a) in docs and APIs.

6.2 Semantics (current)

  • Teleportation changes w; sets arrival (x,y,z)
  • t = 0 — single live timeline; no time travel, historical maps, or temporal shards in scope
  • Protocol and DB columns include t for forward compatibility but servers reject t != 0

6.3 Spatial indexing

Live sim indexes (w, level, cx, cy, cz) only — t not part of spatial keys.

6.4 Future t (out of scope)

When revisited, see prior notes: temporal maps, instanced flashbacks, separate sim per epoch. No implementation until explicitly replanned.

Idea Current verdict
x,y,z,w Active
t in protocol as reserved 0 Yes
t gameplay Deferred indefinitely

7. How the systems compose

Player at WorldCoord (x,y,z,w, t=0)
        │
        ├─► Multi-scale grid (L0/L1/L2) + omnidirectional AOI ──► tick deltas
        │
        ├─► Cartography ledger(w) ──► permanent fog / map UI
        │
        ├─► Map items ──► optional add-to-cartography (permanent merge)
        │
        ├─► Cartography skill ──► reveal efficiency & craft quality
        │
        └─► Inventory ──► map items as trade goods until added

Effective map view = cartography ledger for w (not ephemeral item reads).


8. Phasing

Phase Deliverable
1 L0/L1/L2 grid + omnidirectional AOI; (x,y,z,w), t=0
2 Cartography ledger + 360° reveal on movement; fog TUI
3 Cartography skill; map items; add-to-cartography; craft for trade
4 Horizon LOD ring; NPC/drop/quest authored maps
5 Line-of-sight trim (optional); party reveal (optional)

9. Open questions

Resolved (2026-07-06):

# Decision
M1 1 m L0 cell — global, no per-region overrides
M2 ~32 m base reveal radius (human), scale by body class + cartography skill
M3 Per templateconsume_on_add flag on map items
M4 Full 3D movement on z (flight/swim/climb per skills)
M5 No LoS trim for cartography Phase 1
M6 Opt-in party cartography share (leader toggles)

10. ADR candidates


Parent doc: 00-initial-vision.html — update cross-references when ADRs land.