ScribblaZ Opcodes

The shared OP table is the wire contract; the Nakama handler validates and authoritatively turns client intent into game state.

FieldValue
Shared tablesrc/lib/gameState.ts:6-35
Server routerserver/match_handler.ts:961-1086
Client transportsrc/ScribblaZGame.svelte:126-153
Client projectionsrc/lib/ScribblaZController.svelte.ts:102-269
Settings side channelSETTINGS_OPCODE = 50 in src/lib/protocol.ts:3-5

Docs: Hub · Architecture · Game design · Runbook · Verification · Nakama Multiplayer · Games Catalog

Shared opcode table

Payload shapes below describe the current source contract. “Client location” names the call site for outbound traffic or the receive handler for inbound traffic; “server location” names the routing/emission location.

#OpcodeDirectionPayloadClient locationServer location
1DRAW_STROKEC→S{ points, color, width, groupId? }send ScribblaZGame.svelte:248-251route/validate match_handler.ts:985-994, :459-509
2DRAW_FILLC→S{ x, y, color }send ScribblaZGame.svelte:254-257route/validate match_handler.ts:985-994, :459-509
3DRAW_SHAPEC→S`{ shape: ‘line''box''circle’, points, color, width, filled }`
4DRAW_CLEARC→S{}send ScribblaZGame.svelte:260-263route/validate match_handler.ts:985-994, :459-509
5DRAW_UNDOC→S{}send ScribblaZGame.svelte:265-268route/validate match_handler.ts:985-994, :459-509
22DRAW_REDOC→S{}send ScribblaZGame.svelte:271-273route/validate match_handler.ts:985-994, :459-509
6CHOOSE_WORDC→S{ hashId }, legacy { index: 1..3 }send ScribblaZGame.svelte:282-291resolve/start match_handler.ts:997-1016
7SEND_GUESSC→S{ text }send ScribblaZGame.svelte:294-296route/score/chat match_handler.ts:1019-1023, :511-618
8TOGGLE_READYC→S{}send ScribblaZGame.svelte:331-333route match_handler.ts:1026-1032
9REQUEST_STARTC→S{}send ScribblaZGame.svelte:335-338start/reset route match_handler.ts:1034-1041
10GAME_STATES→C{ phase, round, totalRounds, drawerId, drawerName, creatorId, creatorDisplayName, players, strokes, hint, msRemaining, totalMs, scores, settings, isDelta? }receive ScribblaZController.svelte.ts:104-140emit match_handler.ts:790, :897-910, :1029, :1070
11ROUND_STARTS→C{ round, totalRounds, drawerId, drawerName, timeLimitMs, phase }receive ScribblaZController.svelte.ts:148-168; root UI ScribblaZGame.svelte:163-171emit match_handler.ts:655-662, :677-684
12WORD_OPTIONSS→C{ words: hashIds[], plaintexts: string[] }receive ScribblaZGame.svelte:172-177emit match_handler.ts:650-653; resync :1072-1077
13HINT_UPDATES→C{ hint, revealed, word? }receive ScribblaZController.svelte.ts:176-182emit match_handler.ts:686-695, :899-905, :1078-1084, :1125-1133
14DRAW_RELAYS→C{ op, data }receive ScribblaZController.svelte.ts:184-200emit match_handler.ts:508
15GUESS_RESULTS→C{ playerId, correct, displayName }receive ScribblaZController.svelte.ts:203-217; bridge mirror ScribblaZGame.svelte:198-206emit match_handler.ts:564-568
16PLAYER_SCOREDS→C{ playerId, delta, total }receive ScribblaZController.svelte.ts:256-265emit match_handler.ts:569-585
17ROUND_ENDS→C{ word, scores }receive ScribblaZController.svelte.ts:219-225; private-save call ScribblaZGame.svelte:178-187emit match_handler.ts:718-721
18GAME_ENDS→C{ winnerId, finalScores, top3 }receive ScribblaZController.svelte.ts:228-232emit match_handler.ts:742-746
19CHAT_MSGS→C{ playerId, displayName, text, nearMiss }receive ScribblaZController.svelte.ts:235-245; bridge mirror ScribblaZGame.svelte:188-197emit match_handler.ts:541-546, :613-618, :937-942, :1049-1054
20TIMER_SYNCS→C{ msRemaining }receive ScribblaZController.svelte.ts:248-253emit match_handler.ts:1137-1141
21REQUEST_SYNCC→S, S→C state{ lastStrokeIndex } request; response is GAME_STATE plus settings and role secretsend ScribblaZGame.svelte:431-464; receives resulting state in controller :104-140route/respond match_handler.ts:1060-1085
23VOTE_KICKC→S{ targetId }No root sender is present in the inspected current source; shared declaration gameState.ts:34host route/kick match_handler.ts:1043-1057

Settings side channel

SETTINGS_OPCODE is 50, not an OP member. src/lib/protocol.ts:3-5 records why: its former value 5 collided with OP.DRAW_UNDO = 5. The root sends host custom-word settings through this side channel (ScribblaZGame.svelte:310-328); the server accepts it only from the creator during waiting and broadcasts normalized shared settings plus GAME_STATE (match_handler.ts:970-982). The controller receives it at ScribblaZController.svelte.ts:143-145.

Synchronization notes

GAME_STATE is a full projection unless isDelta is set. For a valid lastStrokeIndex, REQUEST_SYNC sends only later strokes and marks the response isDelta; the controller appends those events (match_handler.ts:1060-1068; ScribblaZController.svelte.ts:116-120). Word-pick resync and its drawer-only option re-send are visible in the current handler (match_handler.ts:1072-1077) but require end-to-end verification.

Ask Docs

AI assistant to help answer questions about the documentation. Answers are read-only and cite docs/source.

Hi! How can I help you with the documentation today? Answers are read-only and cite docs/source.

Ctrl+Enter to send