WebSocket STOMP Protocol
This document describes the reverse-engineered WebSocket protocol used by dicechess.com for real-time multiplayer lobbies and gameplay synchronization.
The game uses STOMP (Simple Text Oriented Messaging Protocol) over a WebSocket connection, typically managed via Java Spring Boot on the backend.
Connection Handshake
Section titled “Connection Handshake”The WebSocket connection is established by upgrading an HTTP connection to:
wss://dicechess.com/ws (or similar endpoint indicated in the headers).
Once connected to the WebSocket, the client must negotiate the STOMP connection by sending a CONNECT frame.
1. Client CONNECT
Section titled “1. Client CONNECT”The client passes the JWT auth token inside the Authorization header.
CONNECTAuthorization:<JWT_TOKEN>accept-version:1.2,1.1,1.0heart-beat:0,02. Server CONNECTED
Section titled “2. Server CONNECTED”The server responds with a CONNECTED frame confirming authentication and providing the authenticated user’s ID as the user-name.
CONNECTEDversion:1.2heart-beat:0,0user-name:<USER_ID>Lobby Protocol
Section titled “Lobby Protocol”To receive updates about lobby events (game creation, players joining, and active user stats), the client subscribes to public and user-specific topics.
Subscribing to Lobby updates
Section titled “Subscribing to Lobby updates”The client sends a SUBSCRIBE frame to /topic/lobby:
SUBSCRIBEid:sub-0destination:/topic/lobbyLobby Message Types
Section titled “Lobby Message Types”Messages received from /topic/lobby are JSON payloads.
1. CURRENT_GAMES
Section titled “1. CURRENT_GAMES”Sent immediately upon subscribing. Contains a list of all currently open lobby games waiting for a player.
{ "CURRENT_GAMES": [ { "id": "83df5eee-6109-11f1-a103-15657712aeb3", "created": 1780682892025, "creator": { "userId": 1837808, "name": "BSmith72", "avatar": "chessPieces_11", "country": "US", "rating": 1574.10, "x2Rating": 1532.72 }, "secondPlayer": null, "gameSetup": { "board": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", "dices": null, "timeLimit": 120, "timeBonus": 0, "betAmount": "3", "currency": "GOLD", "allowDoubling": false, "timeSetup": null, "tournamentId": null, "side": null, "botLevel": null, "isFriendGame": false }, "state": "OPEN" } ]}2. CHANGE_GAME
Section titled “2. CHANGE_GAME”Sent when a game lobby state transitions (e.g., a player joins or a game starts).
-
JOINING State:
{"CHANGE_GAME": {"creator": { "userId": 2010, "name": "Alehandro081", ... },"gameId": "8e177d82-6109-11f1-a103-bfc700bd1257","newState": "JOINING","secondPlayer": null,"lobbyVersion": 162191,"rematchedGameId": null}} -
PLAY State:
{"CHANGE_GAME": {"creator": { "userId": 163, "name": "Rabestro", ... },"gameId": "91498393-6109-11f1-a103-ef1e398a7dfc","newState": "PLAY","secondPlayer": { "userId": -43, "name": "DC Coach Master", "avatar": "bot_3", ... },"lobbyVersion": 162195,"rematchedGameId": null}}
3. REMOVE_GAME
Section titled “3. REMOVE_GAME”Sent when a game is started or cancelled, instructing the lobby UI to remove it from the open games list.
{ "REMOVE_GAME": "91498393-6109-11f1-a103-ef1e398a7dfc"}4. ACTIVITY_INFO
Section titled “4. ACTIVITY_INFO”A periodic heartbeat/status update containing current server load details.
{ "ACTIVITY_INFO": { "activeUsers": 91, "activeGames": 26, "build": 1780404316, "commitHash": "da6efbbc", "serverTime": 1780682908491 }}Game Lifecycle Protocol
Section titled “Game Lifecycle Protocol”When a game transitions to the PLAY state, the client subscribes to a specific game instance topic and swaps commands with the server.
Subscribing to Game instance
Section titled “Subscribing to Game instance”The client subscribes to a user-specific destination using the game’s UUID:
SUBSCRIBEid:sub-3destination:/user/topic/game/instance/<GAME_UUID>Client to Server Commands (SEND)
Section titled “Client to Server Commands (SEND)”All commands are sent to the /app/game/instance/<GAME_UUID> destination using the SEND frame.
1. UPDATE_STATE (Initialization)
Section titled “1. UPDATE_STATE (Initialization)”Sent when the client connects/re-connects to synchronise active game views and session configurations.
{ "type": "UPDATE_STATE", "gameId": "91498393-6109-11f1-a103-ef1e398a7dfc", "value": "{\"sessionId\":\"1ce9576b38ca29\",\"previousState\":\"\",\"debugInfo\":\"{\\\"url\\\":\\\"/game/91498393-6109-11f1-a103-ef1e398a7dfc\\\",\\\"username\\\":\\\"Rabestro\\\",\\\"userId\\\":163,\\\"sessionId\\\":\\\"1ce9576b38ca29\\\"}\"}"}2. UPDATE_TIMER
Section titled “2. UPDATE_TIMER”Sent occasionally to request/assert sync of game clocks.
{ "type": "UPDATE_TIMER", "gameId": "91498393-6109-11f1-a103-ef1e398a7dfc", "value": "{\"sessionId\":\"1ce9576b38ca29\"}"}3. THROW_DICES
Section titled “3. THROW_DICES”Requests rolling the dice at the start of a turn.
{ "type": "THROW_DICES", "gameId": "91498393-6109-11f1-a103-ef1e398a7dfc"}4. MOVE
Section titled “4. MOVE”Executes a single chess micro-move.
{ "type": "MOVE", "gameId": "91498393-6109-11f1-a103-ef1e398a7dfc", "value": "e7e5", "leftTime": 594960.75}value: The move coordinates in UCI format (e.g.e7e5,d8f6).leftTime: The client’s remaining time in milliseconds (float format).
Server to Client Messages (RECEIVE)
Section titled “Server to Client Messages (RECEIVE)”Messages from the game channel arrive at /user/topic/game/instance/<GAME_UUID> formatted with a message envelope that encapsulates a list of updates (messageList).
Envelope Structure
Section titled “Envelope Structure”{ "gameId": "91498393-6109-11f1-a103-ef1e398a7dfc", "players": [163], "messageList": [ { "gameMessageType": "UPDATE_STATE | TIMER | DICES | ANIMATIONS | START_TURN | CHAT | END_GAME | CHECKSUM", "messageNumber": 12, "message": { ... } } ], "currentTime": 1780682916010, "queue": "queue_game_gameserver_to_web"}messageNumber: Incremental ID sequence, allowing the client to process incoming events in exact order.
Internal Message Types (gameMessageType)
Section titled “Internal Message Types (gameMessageType)”1. UPDATE_STATE
Section titled “1. UPDATE_STATE”Provides a full snapshot of the board, timers, players, chat logs, and game status.
{ "gameMessageType": "UPDATE_STATE", "message": { "state": { "board": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", "currency": "GOLD", "allowDoubling": false, "players": { "163": { "side": "BLACK", "betAmount": 0, "canOffer": { ... }, "publicProfile": { ... } }, "-43": { "side": "WHITE", "betAmount": 0, "canOffer": { ... }, "publicProfile": { ... } } }, "capturedPieces": {}, "dices": [], "dicesToShow": [], "allowedMoves": [], "status": "ACTIVE", "turnParticipant": -43, "timerUserId": -43, "leftTime": { "163": 600000, "-43": 600000 }, "chat": [ ... ] } }}2. DICES
Section titled “2. DICES”Published in response to a THROW_DICES action. Details the rolled dice values, allowed moves, and turn index.
{ "gameMessageType": "DICES", "message": { "activePlayerId": 163, "dices": [ { "value": "q", "allowed": true, "used": false }, { "value": "p", "allowed": true, "used": false }, { "value": "n", "allowed": true, "used": false } ], "dicesToShow": [ { "value": "q", "allowed": false, "used": false }, { "value": "p", "allowed": true, "used": false }, { "value": "n", "allowed": true, "used": false } ], "allowedMoves": ["c7c5", "c7c6", "d7d5", "b8c6", "g8f6"], "throwCount": 2 }}dices: The physical raw dice values. Lowercase designates Black pieces (q,p,n), uppercase designates White (Q,P,N).dicesToShow: Dice values exposed in the UI. A die may be markedallowed: falseif no legal moves exist for that piece type.allowedMoves: UCI move strings currently legal for this specific dice throw state.
3. ANIMATIONS
Section titled “3. ANIMATIONS”Specifies piece animations for moves executed by a player.
{ "gameMessageType": "ANIMATIONS", "message": { "moves": ["e7e5"], "captures": [], "capturedPieces": {} }}4. TIMER
Section titled “4. TIMER”Clocks delta update, broadcast to ensure synchronization.
{ "gameMessageType": "TIMER", "message": { "timerPlayerId": 163, "leftTime": { "163": 600000, "-43": 607038 }, "leftFreeTime": { "163": 0, "-43": 0 }, "lastTimeCalculation": 1780682917505, "messageServerTime": 1780682917881, "timerDisabled": false }}5. START_TURN
Section titled “5. START_TURN”Signals that a player’s micro-turn has begun.
{ "gameMessageType": "START_TURN", "message": { "activePlayerId": -43, "await": 163, "board": "r1b1kbnr/pppp1ppp/2n2q2/4p3/8/2N5/PPPPPPPP/R1BQKBNR", "dicesToShow": [ { "value": "q", "allowed": false, "used": true }, { "value": "p", "allowed": false, "used": true }, { "value": "n", "allowed": false, "used": true } ] }}6. CHAT
Section titled “6. CHAT”Broadcasts system chat messages representing in-game logs (dice rolls, physical moves) and user-typed chat messages.
-
Dice Roll Chat representation:
{"gameMessageType": "CHAT","message": {"authorId": 163,"type": "DICES","text": "qpn","time": 1780682917882,"throwCount": 2}} -
Move Chat representation:
{"gameMessageType": "CHAT","message": {"authorId": 163,"type": "MOVE","move": { "movedPiece": "p", "capturedPiece": " ", "move": "e5", "isCastling": false },"text": "","time": 1780682922528}}
7. CHECKSUM
Section titled “7. CHECKSUM”An integrity validation hash containing a representation of the board state.
{ "gameMessageType": "CHECKSUM", "message": { "checksum": 1696035071 }}8. END_GAME
Section titled “8. END_GAME”Dispatched when the game ends, outlining final outcomes.
{ "gameMessageType": "END_GAME", "message": { "loseCondition": "KING_LOST", "playerStates": { "163": "WINNER", "-43": "LOSER" }, "prizes": { "163": [0, 0], "-43": [0, 0] }, "gameEndTime": 1780682934038, "playerLeftTimes": { "163": 597382, "-43": 613161 } }}