fix(simulation): Global was a 2x1 canvas — a sentinel outlived the extent inversion
Jeroen's Global map has been two coloured blocks all along. Not missing
hydrology, not a missing layer: serve_step_canvas_request zeroed Global's wire
extent, so every request arrived downstream as (0,0), clamped to (1,1), and
resolved to a 2x1 canvas.
That sentinel was correct when Global's size came from the body's region grid
and the client's extent field was meaningless. The D-255 extent inversion made
Global viewport-sized and this line silently outlived it. The commit titled
"size the Global rung to the viewport" was therefore correct and completely
unreachable — its tests passed by calling resolve_canvas_extent directly
rather than through the serve path, i.e. they tested the function that changed
instead of the path the data takes.
Two more places carried the same dead premise, both meaning the first canvas
ever built answered every later request and a resize could never take effect:
- GlobalTierCache keyed on body id alone. Now treats a size mismatch as a
miss, so the re-derive replaces it. Deliberately still ONE entry per body
rather than one per size: keying by size would make a tier that never
evicts accumulate an entry per viewport a player has ever used.
- The client's make_key collapsed Global's extent to a sentinel. Centre
stays collapsed — Global's canvas really is whole-body and origin-anchored
— but extent is now part of the key.
project.yaml 0.4.5 forces the 2x1 canvases already on disk to miss.
Verified through the capture harness, not by reasoning: server probe shows
req=(960,540) radius=6238.4 resolved=960x480, and Ferrath's Global now renders
continents, oceans, inland lakes and polar ice where it previously rendered
one solid rectangle.
Server suite green (45 binaries), client 1830 total / 1804 passed / 26 skipped.
Pair session with Jeroen, 2026-07-27.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -45,16 +45,24 @@ func _init(max_entries: int = DEFAULT_MAX_ENTRIES) -> void:
|
||||
_max_entries = maxi(1, max_entries)
|
||||
|
||||
|
||||
## Build the cache key. `rung == "Global"` collapses center/extent to a
|
||||
## fixed sentinel (0,0) regardless of what's passed — matching the wire's
|
||||
## own "Global ignores center/extent" contract, so a caller that
|
||||
## accidentally passes a stale center/extent for a Global request still
|
||||
## lands on the correct single per-body slot.
|
||||
## Build the cache key.
|
||||
##
|
||||
## `rung == "Global"` still collapses the CENTRE to a sentinel (0,0): Global's
|
||||
## canvas is whole-body and origin-anchored, so the server genuinely ignores
|
||||
## `center` for it and a caller passing a stale centre still lands on the
|
||||
## right slot.
|
||||
##
|
||||
## Its EXTENT is no longer collapsed (D-255 extent inversion, 2026-07-26).
|
||||
## Global used to have exactly one possible size per body — its region grid —
|
||||
## which is what made zeroing the extent safe. It is now viewport-sized, and
|
||||
## zeroing it collapsed every size onto a single key: the first canvas cached
|
||||
## for a body answered every later request, so a window resize could never take
|
||||
## effect, because the differently-sized request was a cache HIT on the old one.
|
||||
static func make_key(
|
||||
body_id: String, rung: String, center: Vector2i, extent: Vector2i, min_wl_m: int = 0
|
||||
) -> String:
|
||||
var key_center: Vector2i = Vector2i.ZERO if rung == "Global" else center
|
||||
var key_extent: Vector2i = Vector2i.ZERO if rung == "Global" else extent
|
||||
var key_extent: Vector2i = extent
|
||||
return "%s:%s:%d,%d:%d,%d:%d" % [
|
||||
body_id, rung, key_center.x, key_center.y, key_extent.x, key_extent.y, min_wl_m
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user