WebSocket Message Formats
Outgoing Messages (Client → Server)
1. Game Action
Message Type: move
Message Format:
{
type: "move",
token: string, // Authentication token
userName: string, // Player name
content: {
moveType: number, // ActionTypeCode enum value
timestamp: number, // Unix timestamp (ms)
...data // Additional data (varies by action)
},
refreshToken?: string // If token refresh time has come
}
2. Terminate Action (Game End/Play Again)
Message Type: play_again_request, play_again_response, leave_table
Message Format:
{
type: string, // "play_again_request" | "play_again_response" | "leave_table"
token: string, // Authentication token
userName: string, // Player name
content: {
moveType?: number, // ActionTypeCode (only for leave_table)
accepted?: boolean, // For play_again_response (true/false)
timestamp?: number // Unix timestamp (ms)
},
refreshToken?: string // If token refresh time has come
}
Example - Play Again Request:
{
"type": "play_again_request",
"token": "abc123",
"userName": "Player1",
"content": {}
}
Example - Play Again Response (Accept):
{
"type": "play_again_response",
"token": "abc123",
"userName": "Player2",
"content": {
"accepted": true
}
}
Example - Play Again Response (Reject):
{
"type": "play_again_response",
"token": "abc123",
"userName": "Player2",
"content": {
"accepted": false
}
}
Example - Leave Table:
{
"type": "leave_table",
"token": "abc123",
"userName": "Player1",
"content": {
"moveType": 2,
"timestamp": 1704067200000
}
}
3. Timer Status Request
Message Type: get_timer_status
{
"type": "get_timer_status",
"token": "abc123",
"userName": "Player1",
"content": {}
}
Incoming Messages (Server → Client)
1. Game State
Message Type: gameState or endRound
{
"type": "gameState",
"gameState": {
"roomId": "room-123",
"players": [
{
"uniqueId": "player-1",
"userId": "user-1",
"name": "Player 1",
"tileBag": [
{
"uniqueID": "tile-1",
"number": 1,
"color": 1
}
],
"discardPile": [],
"isConnected": true,
"openSeries": [],
"penalties": [],
"penaltyTotal": 0,
"seriesCount": 0,
"seriesType": "None",
"lastAction": "StartGame",
"playedHand": false,
"hasDrawnThisTurn": false,
"isFinisher": false,
"isWinner": false,
"currentTotalSetPoints": 0,
"remainingTilesScore": 0,
"undoActions": false,
"LastDrawnFromDiscard": null
}
],
"turn": "player-1",
"indicatorTile": {
"uniqueID": "indicator-1",
"number": 5,
"color": 1
},
"okeyTile": {
"uniqueID": "okey-1",
"number": 5,
"color": 1,
"isOkey": true
},
"tileBag": [],
"maxSeriesNumber": 0,
"currentTurn": "player-1",
"turnStartTime": 1704067200000,
"createdAt": 1704067200000,
"gamePhase": "in_progress",
"winnerId": "",
"remainingTiles": "100",
"isTie": false
}
}
2. Token (Authentication Token)
Message Type: Token
{
"type": "Token",
"token": "new-access-token",
"refreshToken": "new-refresh-token"
}
3. Error
Message Type: error
{
"type": "error",
"content": "Action failed: Invalid move"
}
4. Message (Information)
Message Type: message
{
"type": "message",
"content": "Your turn!"
}
5. System Message
Message Type: system or System
{
"type": "system",
"content": "{\"message\": \"Game starting in 3 seconds\"}"
}
6. User List (Player List)
Message Type: userlist
{
"type": "userlist",
"users": [
{
"id": "user-1",
"name": "Player 1"
},
{
"id": "user-2",
"name": "Player 2"
}
]
}
7. Countdown
Message Type: countdown
{
"type": "countdown",
"content": "{\"count\": 3, \"message\": \"Game starting in 3 seconds\"}"
}
8. Turn Timer Update
Message Type: turn_timer_update
{
"type": "turn_timer_update",
"player_id": "player-1",
"data": {
"remaining_time": 25.5
}
}
9. Turn Timer Start
Message Type: turn_timer_start
{
"type": "turn_timer_start",
"player_id": "player-1",
"data": {
"duration": 30
}
}
10. Turn Timer Expired
Message Type: turn_timer_expired
{
"type": "turn_timer_expired",
"player_id": "player-1"
}
11. Turn Timer Status
Message Type: turn_timer_status
{
"type": "turn_timer_status",
"data": {
"status": {
"current_turn": "player-1",
"turn_duration": "30",
"timers": {
"0": {
"player_name": "Player 1",
"remaining_time": "25.5",
"elapsed_time": "4.5",
"is_active": "true",
"is_expired": "false"
}
},
"game_state": { ... }
}
}
}
12. State Recovery
Message Type: state_recovery
{
"type": "state_recovery",
"current_state": {
// In gameState format
}
}
13. Action State
Message Type: Any message may contain an actionState field
{
"type": "gameState",
"actionState": {
"type": 7,
"actionDefinition": "DiscardTile",
"actionMessage": "Tile discarded successfully"
},
"gameState": { ... }
}
14. Play Again Notification
Message Type: playAgainNotification
{
"type": "playAgainNotification",
"from": "player-1",
"content": {
"requestingPlayerId": "player-1",
"requestingPlayerName": "Player 1",
"expiresAt": 1704067300000,
"timeoutSeconds": 30
}
}
Description:
- When a player clicks the "Play Again" button, this message is sent to all other players
expiresAt: Request expiration time (Unix timestamp, ms)timeoutSeconds: Total timeout duration (30 seconds)
15. Play Again Request Sent
Message Type: playAgainRequestSent
{
"type": "playAgainRequestSent",
"data": "Play again request sent successfully"
}
Description:
- Notifies the requesting player that the request was sent successfully
16. Play Again Accepted
Message Type: playAgainAccepted
{
"type": "playAgainAccepted",
"data": {
"accepted": true
}
}
Description:
- When a player accepts the request, this message is sent to all players
- New game starts
17. Play Again Rejected
Message Type: playAgainRejected
{
"type": "playAgainRejected",
"data": {
"accepted": false
}
}
Description:
- When a player rejects the request, this message is sent to all players
- Game ends and players return to lobby
18. Play Again Result
Message Type: playAgainResult
{
"type": "playAgainResult",
"data": {
"type": "playAgainResult",
"from": "player-2",
"content": {
"accepted": true,
"respondingPlayerId": "player-2",
"reason": ""
}
}
}
Description:
- Sent when all player responses are collected
- If
accepted: false, game ends and players return to lobby
19. Game End Timeout
Message Type: gameEndTimeout
{
"type": "gameEndTimeout"
}
Description:
- Sent when the 30-second game end timeout expires
- If no player has sent a "Play Again" request or all players haven't responded
- Automatically return to lobby
20. Close Connection
Message Type: Close_Connection
{
"type": "Close_Connection"
}