Repository navigation
WebSocket and API Reference
chdvg edited this page May 20, 2026
·
1 revision
| Method | Route | Purpose |
|---|---|---|
GET |
/ |
DM control panel (requires auth cookie) |
GET |
/map-builder |
Map Builder |
GET |
/remote/player |
Player screen |
GET |
/api/scenes |
Load all scenes |
POST |
/api/scenes |
Save all scenes |
GET |
/api/players |
Load player roster |
POST |
/api/players |
Save player roster |
GET |
/api/audio |
List audio files grouped by category |
GET |
/api/maps |
List map files |
POST |
/api/map-builder/save |
Export map PNG + save editable .map.json state |
GET |
/api/map-builder/states |
List maps with an editable state file |
GET |
/api/map-builder/state?name= |
Load editable state for a named map |
POST |
/api/overlay |
Push timed overlay { title, html, duration } to players |
POST |
/api/stopaudio |
Stop audio on all player screens |
POST |
/api/blackout |
Toggle blackout overlay on player screens |
POST |
/api/clear |
Dismiss open popups on players (scene image preserved) |
WS |
/ws |
Real-time sync channel |
The following routes always return 403:
/server.js/seeds/*/package.json
Connect at ws://<host>:3000/ws.
All messages are JSON-encoded strings: JSON.stringify({ action|type, ...payload }).
| Action | Payload | Effect |
|---|---|---|
show-scene-view |
Full scene view payload | Broadcast SHOW_SCENE_VIEW; clear tokens / drawing / fog / features |
update-tokens |
{ tokens[], mapKey } |
Store + broadcast UPDATE_TOKENS
|
update-drawing |
{ strokes[], mapKey } |
Store + broadcast UPDATE_DRAWING
|
update-fog |
{ fogKey, cells } |
Store per fogKey + broadcast UPDATE_FOG
|
set-fog-key |
{ fogKey } |
Update active fogKey; broadcast SET_FOG_KEY (runtime fog toggle) |
trigger-feature |
{ feature, allFeatures, mapKey, mapMeta } |
Store featureState + broadcast TRIGGER_FEATURE
|
reset-feature |
{ featureId, mapKey } |
Delete featureState + broadcast RESET_FEATURE
|
update-features |
{ features[], mapMeta } |
Store feature defs; update currentSceneView
|
lock-player |
{ name } |
Per-player movement lock |
unlock-player |
{ name } |
Per-player movement unlock |
lock-all |
— | Lock all players globally |
unlock-all |
— | Unlock all players globally |
blackout |
{ active } |
Toggle blackout; broadcast BLACKOUT
|
play-audio |
{ url, loop } |
Broadcast PLAY_AUDIO
|
stop-audio |
— | Broadcast STOP_AUDIO
|
send-overlay |
{ title, data, duration } |
Broadcast OVERLAY (popup on player screens) |
sync-all-tokens |
{ tokenState } |
Store full tokenState map for all maps; saveState()
|
trigger-attack |
{ attacker, targets[] } |
Broadcast ATTACK_ANIMATION
|
update-objects |
{ objects[], objectStates } |
Store + broadcast UPDATE_OBJECTS
|
object-interact |
{ objId, state } |
Update single object state + broadcast OBJECT_STATE_CHANGE
|
| Action | Payload | Effect |
|---|---|---|
player-login |
{ name, cls } |
Sets ws.playerName; sends PLAYER_LOGIN_OK or PLAYER_LOGIN_ERR
|
move-player-token |
{ id, x, y } |
Updates token position (ownership validated); auto-triggers features |
player-dice-roll |
{ die, result } |
To DM: PLAYER_DICE_ROLL; to other players: DICE_ROLL
|
request-sync |
— | Calls sendFullState(ws) — re-delivers all current state |
set-target |
{ target } |
Player sets their own combat target (mob label or '' to clear) |
| Type | Payload | Recipient |
|---|---|---|
SHOW_SCENE_VIEW |
{ image, audio, audioLoop, fogKey, fit, features, mapMeta } |
All |
UPDATE_FOG |
{ fogKey, cells } |
All |
SET_FOG_KEY |
{ fogKey } |
All |
UPDATE_DRAWING |
{ strokes[] } |
All |
UPDATE_TOKENS |
{ tokens[] } |
All |
CLEAR_SCENE |
— | All |
CLEAR |
— | All |
| Type | Payload | Recipient |
|---|---|---|
TRIGGER_FEATURE |
{ feature, allFeatures, mapKey, mapMeta } |
All |
RESET_FEATURE |
{ featureId, mapKey } |
All |
UPDATE_FEATURES |
{ features[] } |
All |
UPDATE_OBJECTS |
{ objects[], objectStates } |
All |
OBJECT_STATE_CHANGE |
{ objId, state } |
All |
| Type | Payload | Recipient |
|---|---|---|
PLAY_AUDIO |
{ url, loop } |
All |
STOP_AUDIO |
— | All |
| Type | Payload | Recipient |
|---|---|---|
PLAYER_LOGIN_OK |
{ name, cls } |
That player |
PLAYER_LOGIN_ERR |
{ reason } |
That player |
LOGGED_IN_PLAYERS |
{ players: [...names] } |
DM |
MOVEMENT_LOCK |
{ name, locked } |
All |
MOVEMENT_LOCK_ALL |
{ locked } |
All |
| Type | Payload | Recipient |
|---|---|---|
SET_TARGET |
{ player, target } |
All |
ATTACK_ANIMATION |
{ attacker, targets[] } |
All |
DICE_ROLL |
{ die, result } |
All players (anonymous) |
PLAYER_DICE_ROLL |
{ name, die, result } |
DM only |
| Type | Payload | Recipient |
|---|---|---|
OVERLAY |
{ title, data, duration } |
All |
BLACKOUT |
{ active } |
All |
DM_STATE_RESTORE |
Full state snapshot | DM on reconnect |
clients |
{ count, names[] } |
DM |
| Variable | Description |
|---|---|
currentSceneView |
Full SHOW_SCENE_VIEW payload; re-delivered on reconnect |
currentTokens / currentTokensMapKey
|
Active token array + map key |
currentDrawing / currentDrawingMapKey
|
Freehand strokes array |
currentFogStates |
fogKey → fog grid (cell array) |
currentFeatures / currentFeatureStates
|
Feature definitions + triggered states |
currentMapMeta |
{ cols, rows } for the active map grid |
allTokenStates |
mapKey → tokens array for all maps; persisted to data/state.json
|
loggedInPlayers |
Map of playerName → WebSocket |
lockedPlayers |
Set of locked player names |
allPlayersLocked |
Boolean — global movement lock |
clients |
Set of all WebSocket connections |
dmClients |
Set of authenticated DM WebSocket connections |
sendFullState(ws) re-delivers the complete scene state to a connecting client:
-
SHOW_SCENE_VIEW(current map, audio, fog key, features, map meta) -
UPDATE_FOG(active fog grid) -
UPDATE_TOKENS(current tokens) -
UPDATE_DRAWING(current strokes) -
UPDATE_FEATURES(feature definitions + triggered states) -
UPDATE_OBJECTS(object definitions + states) - All targeting state (
SET_TARGETfor each active target)
DMs additionally receive DM_STATE_RESTORE which includes allTokenStates so the full token map is merged into the DM's local state.