Server Dashboard
Total Rooms
0
Online Players
0
Waiting
0
Playing
0
Active Rooms
CodeTypeStatusPlayersTimeMapCreatedAction
Players
NameUser IDItemStatus
Select a room
API Documentation
Base URL
-WebSocket
-
Room Management
5 endpoints
POST
/api/rooms/quickplay
Find available room or create new one
Request Body
{
"userId": "user-123",
"name": "PlayerName",
"skin": "character_1"
}Response 200
{
"roomId": "ABC123",
"type": "public"
}
POST
/api/rooms/public
Create a public room
Request Body
{
"timeLimit": 90,
"maxPlayers": 4
}Response 200
{
"roomId": "XYZ789",
"type": "public"
}
POST
/api/rooms/private
Create a private room
Request Body
{
"timeLimit": 90,
"maxPlayers": 4
}Response 200
{
"roomId": "ABC123",
"type": "private"
}
GET
/api/rooms/list
List all public rooms
Response 200
{
"count": 2,
"rooms": [
{
"roomId": "ABC123",
"map": "track_1",
"playerCount": 3,
"maxPlayers": 5,
"status": "waiting",
"suspended": false,
"type": "public",
"timeLimit": 90,
"createdAt": 1706612345
}
]
}
GET
/api/rooms/{roomId}
Get room details
Parameters
roomIdstringRoom code (e.g. ABC123)
Response 200
{
"id": "ABC123",
"type": "public",
"status": "waiting",
"map": "track_1",
"maxPlayers": 5,
"timeLimit": 90,
"timeLeft": 90,
"players": {},
"boosters": {},
"traps": {}
}
History & Stats
3 endpoints
GET
/api/history/room/{roomId}
Get game history for a room
Parameters
roomIdstringRoom code
Response 200
{
"roomId": "ABC123",
"map": "track_1",
"type": "public",
"duration": 85,
"playerCount": 4,
"winners": [
{"userId": "u1", "name": "Player1", "position": 1, "time": 45}
]
}
GET
/api/history/user/{userId}
Get user's game history
Parameters
userIdstringUser ID
limitintMax results (default 10)
Response 200
{
"history": [
{"roomId": "ABC123", "map": "track_1", "duration": 85, "playerCount": 4}
]
}
GET
/api/stats
Get global game statistics
Response 200
{
"total_games": 150,
"avg_duration": 72.5,
"by_time_limit": {"60": 30, "90": 80, "180": 40}
}
Response Examples
Full Data Samples
Room Waiting (with Players)
Room yang sedang menunggu pemain join
{
"id": "123456",
"type": "public",
"status": "waiting",
"map": "track_1",
"maxPlayers": 5,
"timeLimit": 90,
"isFull": false,
"players": [
{
"id": "player-uuid-1",
"userId": "user-123",
"name": "SpeedRacer",
"skin": "ninja_red",
"isReady": false,
"position": {"x": 0, "y": 0, "z": 0}
},
{
"id": "player-uuid-2",
"userId": "user-456",
"name": "TurboKing",
"skin": "robot_blue",
"isReady": false,
"position": {"x": 0, "y": 0, "z": 0}
}
]
}
Room Full (Waiting All Ready)
Room penuh, menunggu semua player ready
{
"id": "123456",
"type": "public",
"status": "full",
"map": "track_1",
"maxPlayers": 5,
"timeLimit": 90,
"isFull": true,
"players": [
{"id": "p1", "userId": "u1", "name": "Player1", "skin": "skin1", "isReady": true},
{"id": "p2", "userId": "u2", "name": "Player2", "skin": "skin2", "isReady": true},
{"id": "p3", "userId": "u3", "name": "Player3", "skin": "skin3", "isReady": false},
{"id": "p4", "userId": "u4", "name": "Player4", "skin": "skin4", "isReady": true},
{"id": "p5", "userId": "u5", "name": "Player5", "skin": "skin5", "isReady": false}
]
}
Room Playing (Active Game)
Room yang sedang bermain dengan item boxes, player holding items, dan traps
{
"id": "XYZ789",
"type": "public",
"status": "playing",
"map": "track_1",
"maxPlayers": 5,
"timeLimit": 90,
"timeLeft": 45,
"createdAt": "2026-01-30T15:30:00+07:00",
"startedAt": "2026-01-30T15:31:00+07:00",
"players": {
"player-uuid-1": {
"id": "player-uuid-1",
"userId": "user-123",
"name": "SpeedRacer",
"skin": "ninja_red",
"isReady": true,
"isFinished": false,
"finishTime": 0,
"finishPosition": 0,
"heldItem": {
"type": "bomb",
"obtainedAt": "2026-01-30T15:31:30+07:00"
},
"position": {"x": 125.5, "y": 2.0, "z": 340.8}
},
"player-uuid-2": {
"id": "player-uuid-2",
"userId": "user-456",
"name": "TurboKing",
"skin": "robot_blue",
"isReady": true,
"isFinished": true,
"finishTime": 42,
"finishPosition": 1,
"heldItem": null,
"position": {"x": 500.0, "y": 0, "z": 1000.0}
},
"player-uuid-3": {
"id": "player-uuid-3",
"userId": "user-789",
"name": "NitroBlast",
"skin": "alien_green",
"isReady": true,
"isFinished": false,
"finishTime": 0,
"finishPosition": 0,
"heldItem": {
"type": "shield",
"obtainedAt": "2026-01-30T15:32:00+07:00"
},
"position": {"x": 89.2, "y": 1.5, "z": 280.3}
}
},
"boosters": {
"box-uuid-1": {
"id": "box-uuid-1",
"type": "speed_boost",
"position": {"x": 50.0, "y": 0, "z": 100.0},
"taken": true,
"takenBy": "player-uuid-1"
},
"box-uuid-2": {
"id": "box-uuid-2",
"type": "lightning",
"position": {"x": 150.0, "y": 0, "z": 300.0},
"taken": false,
"takenBy": ""
},
"box-uuid-3": {
"id": "box-uuid-3",
"type": "freeze",
"position": {"x": 250.0, "y": 0, "z": 500.0},
"taken": false,
"takenBy": ""
}
},
"traps": {
"trap-uuid-1": {
"id": "trap-uuid-1",
"type": "bomb",
"placedBy": "player-uuid-2",
"position": {"x": 180.5, "y": 0, "z": 420.3},
"radius": 8.0,
"active": true,
"createdAt": "2026-01-30T15:32:15+07:00"
},
"trap-uuid-2": {
"id": "trap-uuid-2",
"type": "freeze",
"placedBy": "player-uuid-1",
"position": {"x": 95.0, "y": 0, "z": 200.0},
"radius": 5.0,
"active": false,
"triggeredBy": "player-uuid-3",
"createdAt": "2026-01-30T15:31:45+07:00"
}
}
}
Room Ended (Game Finished)
Room yang sudah selesai dengan hasil akhir
{
"id": "DEF456",
"type": "public",
"status": "ended",
"map": "track_1",
"maxPlayers": 5,
"timeLimit": 90,
"timeLeft": 0,
"createdAt": "2026-01-30T15:00:00+07:00",
"startedAt": "2026-01-30T15:01:00+07:00",
"endedAt": "2026-01-30T15:02:30+07:00",
"players": {
"player-uuid-1": {
"id": "player-uuid-1",
"userId": "user-123",
"name": "SpeedRacer",
"isFinished": true,
"finishTime": 45,
"finishPosition": 1,
"heldItem": null
},
"player-uuid-2": {
"id": "player-uuid-2",
"userId": "user-456",
"name": "TurboKing",
"isFinished": true,
"finishTime": 52,
"finishPosition": 2,
"heldItem": null
},
"player-uuid-3": {
"id": "player-uuid-3",
"userId": "user-789",
"name": "NitroBlast",
"isFinished": true,
"finishTime": 68,
"finishPosition": 3,
"heldItem": null
}
},
"boosters": {},
"traps": {}
}
Game Start Event
Event yang dikirim server saat semua player ready
{
"type": "game_start",
"payload": {
"roomId": "123456",
"status": "playing",
"timeLimit": 90,
"timeLeft": 90,
"players": [
{"id": "p1", "userId": "user-123", "name": "SpeedRacer", "skin": "ninja_red", "isReady": true},
{"id": "p2", "userId": "user-456", "name": "TurboKing", "skin": "robot_blue", "isReady": true}
],
"boosters": [
{"id": "box-1", "type": "bomb", "position": {"x": 50, "y": 0, "z": 100}, "taken": false},
{"id": "box-2", "type": "shield", "position": {"x": 150, "y": 0, "z": 300}, "taken": false}
],
"traps": [],
"finishedIds": []
}
}
Countdown Event
Countdown 5,4,3,2,1 sebelum timer mulai
{"type":"countdown","payload":{"countdown":5}}
{"type":"countdown","payload":{"countdown":4}}
{"type":"countdown","payload":{"countdown":3}}
{"type":"countdown","payload":{"countdown":2}}
{"type":"countdown","payload":{"countdown":1}}
// After countdown done, timer_update starts
{"type":"timer_update","payload":{"timeLeft":90}}
Game End Event
Game selesai saat 1 player finish atau time up; posisi sisanya diisi by distance
{
"type": "game_end",
"payload": {
"roomId": "ABC123",
"finishedPlayers": ["player-uuid-1"],
"winners": [
{"userId": "user-123", "name": "SpeedRacer", "position": 1, "time": 45},
{"userId": "user-456", "name": "TurboKing", "position": 2, "time": 180},
{"userId": "user-789", "name": "NitroBlast", "position": 3, "time": 180}
]
}
}
WebSocket Events
Client & Server
Connect to: wss://gameapi.copod.my.id/ws/{roomId}
Game Flow
1. POST /api/rooms/quickplay (userId, name, skin) → get roomId
2. Connect WebSocket → send player_joined (userId; optional name/skin)
3. Server broadcasts room_update (status: waiting)
4. Public room full → status changes to "full"
5. Client moves to game layout
6. Each client sends set_ready (userId)
7. Public: full + all ready, Private: all joined ready (min 2) → game_start
8. Server sends countdown (5,4,3,2,1)
9. Countdown done → timer_update starts
Room Status
waiting Room menunggu player join
full Room penuh, menunggu semua ready
Game sedang berjalan
ended Game selesai
Private room bisa start dari status waiting jika semua player yang sudah join ready (min 2).
Client → Server
player_joined
{"type":"player_joined","payload":{"userId":"user-123","name":"PlayerName","skin":"skin_1"}}Untuk private join bisa kirim name/skin di siniset_ready
{"type":"set_ready","payload":{"userId":"user-123"}}position_update
{"type":"position_update","payload":{"userId":"x","x":943,"y":861,"animName":"Diam","isMirror":0,"isCrouch":0,"timestamp":1700000000000}}falldown
{"type":"falldown","payload":{"userId":"user-123"}}doublejump
{"type":"doublejump","payload":{"userId":"user-123"}}item_taken
{"type":"item_taken","payload":{"userId":"x","itemType":"BOMB","itemId":1}}item_used
{"type":"item_used","payload":{"userId":"x","itemType":"HURRICANE","itemId":1,"x":100,"y":200,"direction":"LEFT"}}tornadoHit
{"type":"tornadoHit","payload":{"userId":"user-123"}}player_finish
{"type":"player_finish","payload":{"userId":"user-123"}}kick_player
{"type":"kick_player","payload":{"userId":"user-456","reason":"afk"}}Direct custom event: langsung direlay ke semua player/spectatorcustom_broadcast
{"type":"custom_broadcast","payload":{"eventType":"kick_player","payload":{"userId":"user-456","reason":"afk"},"excludeSelf":false,"mySelf":false}}Wrapper custom relay, support excludeSelf & mySelf (self-only)custom_broadcast (ping self-only)
{"type":"custom_broadcast","payload":{"eventType":"ping","payload":{"clientTimestamp":1700000000000},"mySelf":true}}Response event: ping dengan serverTimestamp + latencyMsServer → Client
room_updateBroadcast on join/leave/ready
game_startAuto-start (public: full+ready, private: joined+ready min 2)
countdown
{"type":"countdown","payload":{"timeLeft":5}}timer_update
{"type":"timer_update","payload":{"timeLeft":85}}game_suspended
{"type":"game_suspended","payload":{"roomId":"ABC123","timeLeft":80}}game_resumed
{"type":"game_resumed","payload":{"roomId":"ABC123","timeLeft":80}}onplayerChange
{"type":"onplayerChange","payload":{"players":[{"userId":"x","x":943,"y":861,"animName":"Diam","isMirror":0,"isCrouch":0,"timestamp":1700000000000}]}}getFallDown
{"type":"getFallDown","payload":{"userId":"user-123"}}getPlayerDoubleJump
{"type":"getPlayerDoubleJump","payload":{"userId":"user-123"}}getItem
{"type":"getItem","payload":{"userId":"x","itemType":"BOMB","itemId":1}}trap_placed
{"type":"trap_placed","payload":{"userId":"x","itemType":"BOMB","itemId":1,"x":100,"y":200,"direction":"LEFT"}}trap_hit
{"type":"trap_hit","payload":{"userId":"x","itemType":"TRAP","itemId":1}}getTornadoHit
{"type":"getTornadoHit","payload":{"userId":"user-123"}}playerFinish
{"type":"playerFinish","payload":{"userId":"x","position":1,"time":45}}game_endGame ended with winners list
Item Types
TRAPBOMBLIGHTINGHURRICANE
Response
Game History
Game List
Loading game history...
RoomMapDurationPlayersWinnersDate
Loading game history...
Map Pool
Add New Map
Room baru akan random map dari daftar ini.
Map NameCreatedAction
No maps found
Admin Management
UserUsernameCreatedLast LoginAction