Lobby: maps, map editor and tokens

DM map library (upload re-encoded with Pillow), map editor with prepared
enemies/NPCs, map on the lobby table with personal pan/zoom, draggable
tokens (players move their own, DM all), full/player view, live sync via
the WebSocket.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJhXuLD2Z6hv3Wqeq9UL9K
This commit is contained in:
Claude
2026-10-23 13:59:21 +00:00
parent 162d8c9224
commit e8755582d5
8 changed files with 679 additions and 9 deletions
+14 -1
View File
@@ -110,6 +110,14 @@ The lobby page is built for desktop with three columns: the **character sheet**
- **Colours**: every player has a different colour (lobby menu -> Your colour); the DM is gold.
- **Lobby menu** (top right): join code, rename, remove players, colour, switch character, leave or delete the lobby.
### Maps and tokens
- **Library** (DM, left column -> *Lobby actions*): upload PNG, JPEG or WebP (up to 12 MB, 30 maps per DM). The server checks and re-encodes every image as WebP (max 4096 px per side) into `db/maps/`. Images are only served to logged-in members of a lobby that shows the map.
- **Map editor** (*Edit*): set the grid (pixels per square) and place enemies and NPCs in advance: add tokens, drag them, name, size (in squares), colour, *Hidden from players*, duplicate, remove. Save writes them into the map preset.
- **Show on table**: puts the map on the lobby table (dice still fall on top of it). The prepared tokens are copied into the lobby, so moving them during play never changes the preset. Every player gets a token of their own, which they **drag from the tray onto the map**; players can only move their own token, the DM moves everything and can rename, resize, hide or remove NPC tokens in play (*+ NPC* adds one).
- **Pan and zoom** are personal: drag the background, mouse wheel or pinch, buttons at the bottom right, *Grid* toggles the grid. Moves are synced live over the WebSocket.
- **Full view / Player view** (DM): player view hides what the players cannot see (currently hidden tokens).
Players only see a short card of the other players, never their sheets. Guessing join codes is rate limited. Deleting a character takes it out of the lobbies (the player can pick another); deleting a lobby does not delete characters.
## API
@@ -129,7 +137,12 @@ All `/api/*` routes except `/api/auth/me`, `/api/auth/register` and `/api/auth/l
| POST | `/api/lobbies/join` | Join with `{code, character_id}` |
| GET / PUT / DELETE | `/api/lobbies/{id}` | Members and cards (DM sees all ids) / rename / delete (DM only) |
| POST | `/api/lobbies/{id}/code` | New join code (DM only) |
| WebSocket | `/api/lobbies/{id}/ws` | Live notes `{t: messages / lobby / sheet}` for lobby members (cookie login, same origin) |
| GET / POST | `/api/maps` | The DM's map library / upload (raw image body, `?name=`) |
| GET / PUT / DELETE | `/api/maps/{id}` | Map with prepared tokens (name, grid, tokens) / change / delete |
| GET / PUT | `/api/lobbies/{id}/map` | Map and tokens on the table (hidden tokens only for the DM) / DM: show map (`map_id`, null clears) |
| GET | `/api/lobbies/{id}/map/image` | The map image |
| POST / PUT / DELETE | `/api/lobbies/{id}/tokens[/{tid}]` | Add NPC token (DM) / move (own token or DM) and edit (DM) / remove (DM) |
| WebSocket | `/api/lobbies/{id}/ws` | Live notes `{t: messages / lobby / sheet / map}` for lobby members (cookie login, same origin) |
| GET / POST | `/api/lobbies/{id}/messages` | Chat and event log (`?after=<id>` to poll) / send, optional `to` = whisper |
| POST | `/api/lobbies/{id}/rolls` | Roll `{sides, count, to?, manual?, mode?}` (d4-d20, d100; up to 10 dice). `manual` = results of real dice, `mode` (DM only) = `hidden`/`mystery`/`public` |
| POST | `/api/lobbies/{id}/checks` | d100 check `{kind: skill\|attr, id, manual?}` for the caller's lobby character |