feat(bridge): protocol 11 — the map (phase 14)
Four verbs (PLAN.md §30.2), all outside EventsEnabled because none of them changes the world: - map.info: the map key, the picture's source (the Rust+ cache, a render kept on disk, or none), its size, SHA-256 and slice count, the game's own grid, and the monuments the in-game map shows. The cache is read by reflection by name only, never enumerated (it holds the Rust+ secret). The hash is computed on the thread pool. - map.fetch: one 512 KiB base64 slice, encoded on the thread pool, refused `stale` when the key or hash moved. - map.render: the admin fallback (D109). Answers `accepted` at once and renders on a later frame, keeping the result in data/RunicGateway/map.jpg beside its key so a restart within the map does not render again. - map.live: every layer at once (world events, event-owned zones/crates/NPCs, players and sleepers, TCs and player vending machines as positions only). The sets are kept by OnEntitySpawned/OnEntityKill and seeded by one sweep at OnServerInitialized. MapMaxSleepers/MapMaxBases bound the two layers. Also fixes Grid() (D119): it used a 146.3 m cell, but the game fits whole cells to the world (20 x 150 m on a 3000 map), so rows could be one off. It now asks MapHelper.PositionToString, the in-game map's own labeller. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in: