Skip to main content

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"
}