Add player position tracking relay + rendering (Phase 7b)

Relays the mod's throttled player_positions roster over a new
/ws/players/:serverId gateway (Redis pub/sub + snapshot key so a
tab connecting between mod flushes isn't empty), gated per-server
by a new playerPositionsVisible admin toggle independent of the
mod's own tracking config. Frontend renders the roster as map
markers with a show/hide toggle and online count. Covered by unit
tests (players.test.ts, ws-gateway.test.ts, admin.test.ts) and a
new e2e spec that plays the real mod WS protocol from inside a
browser context.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015tKdPZt78zbPUZMXWzKEKt
This commit is contained in:
2026-08-09 20:07:11 +02:00
parent cc3860ce08
commit 826233e10c
16 changed files with 444 additions and 16 deletions
+27 -12
View File
@@ -90,17 +90,29 @@ the resulting token. Once the mod connects and sends its initial chunk backfill,
`/admin` (linked from the map page's header) manages the server registry: register new servers
(generates their token — never admin-supplied, so it can't collide with or be guessed from
anything else), and edit `authMode`, `anonymousChatAllowed`, and `waypointFormat` per server.
It's gated behind a single shared secret, not a per-account role (this is a single-operator
backend) — set `MCMAPPER_ADMIN_TOKEN` in `api/`'s untracked `.env` (see `api/.env.example`),
restart `api`, then enter that same value into the panel's unlock prompt. Leaving it unset
disables every `/api/admin/*` route (401), it does not default to open. The token is remembered
in the browser's `localStorage` after unlocking, same pattern as the player-facing session token
(see `api/src/link.ts`'s doc comment).
anything else), and edit `authMode`, `anonymousChatAllowed`, `waypointFormat`, and
`playerPositionsVisible` per server. It's gated behind a single shared secret, not a per-account
role (this is a single-operator backend) — set `MCMAPPER_ADMIN_TOKEN` in `api/`'s untracked
`.env` (see `api/.env.example`), restart `api`, then enter that same value into the panel's
unlock prompt. Leaving it unset disables every `/api/admin/*` route (401), it does not default to
open. The token is remembered in the browser's `localStorage` after unlocking, same pattern as
the player-facing session token (see `api/src/link.ts`'s doc comment).
Settings not exposed here yet (which map types render, dimension filtering, player-position
visibility) don't have underlying features built for them either — no point in a knob nothing
reads. They'll gain admin UI alongside the feature that needs them.
Settings not exposed here yet (which map types render, dimension filtering) don't have underlying
features built for them either — no point in a knob nothing reads. They'll gain admin UI
alongside the feature that needs them.
### Player positions (Phase 7b)
The mod sends a throttled roster of online players (`player_positions` over `/ws`, see
`api/src/ws-gateway.ts`'s doc comment) — its own `playerTrackingEnabled`/
`playerPositionIntervalTicks` config decides whether/how often it sends this at all. The backend
relays it to any browser subscribed on `/ws/players/:serverId` (`api/src/players-gateway.ts`),
gated per-server on the admin panel's `playerPositionsVisible` toggle (default on) — an
independent, backend-side "should we show it" decision from the mod's own config. Not persisted
(no meaningful history for a live position), just the latest roster in Redis (`api/src/players.ts`)
so a browser tab that connects between mod flushes doesn't sit empty. The map renders players as
map markers with a `show`/hide toggle and an online count, right above the region-export panel.
## Running tests
@@ -153,8 +165,11 @@ fixed `MCMAPPER_ADMIN_TOKEN` for `tests/admin.spec.ts` to use — see `config.ts
UI flows most worth a real click-through: the marker click-to-place/edit popup
(`tests/markers.spec.ts`, including that a marker created while linked shows up in a second
browser context with the same session — the cross-device sync claim), the region-select drag +
glTF export (`tests/region-export.spec.ts`, including a real triggered file download), and the
admin panel's token gate + server register/edit/delete round trip (`tests/admin.spec.ts`).
glTF export (`tests/region-export.spec.ts`, including a real triggered file download), the
admin panel's token gate + server register/edit/delete round trip (`tests/admin.spec.ts`), and
the player-position relay (`tests/players.spec.ts` — simulates a mod connection over the real
`/ws` protocol from inside the browser context and confirms a subscribed tab renders the roster,
respects the `show` toggle, and clears markers on an empty roster).
## Attribution