arena: spectator-styled watchers + ac-arena CLI for end-to-end testing
Visuals:
- isGuestHandle() — handles starting with guest_ or swarm_ are treated as
watchers, rendered as translucent gray bodies (alpha 0.35 instead of 0.9)
and 1×1 dim minimap dots, so the visual prominence is reserved for
people who claimed a real handle.
- HUD splits the live count into "players" (named) and "watchers" (anon).
tools/ac-arena.mjs — single-file Node CLI for testing the multiplayer
loop without a browser. Uses Node 22 native WebSocket so no extra deps.
node tools/ac-arena.mjs swarm --count=4 --duration=30
node tools/ac-arena.mjs watch --duration=30
`swarm` opens N WS-only fake players that send arena:hello + arena:cmd
at 30Hz with random walk movement; useful for load-testing arena-manager
and confirming the server's WS receiveCmd path works (it does — verified
3 clients × 30Hz, both directions, no drops).
`watch` is a passive probe that prints arena roster + per-second snap
counts; useful as a no-browser sanity check that snaps are flowing.
The swarm runs over WS only because Node has no WebRTC. That's actually
useful as a diagnostic split — if WS works but the browser still has
the drop-cmd problem, the issue is the geckos UDP transport, not the
server arena logic.