Commit 6517bd2d authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: eliminate jsonb double-encoding that broke multiplayer sync

The root cause: PHP's json_encode() was used on jsonb fields before
passing to SupabaseClient->insert/update, which json_encodes the entire
payload. This double-encoded game_state into a JSON string scalar.

When the match_heartbeat RPC did `jsonb_string || jsonb_object`,
PostgreSQL created an array instead of merging, corrupting game_state.
The polling logic then couldn't find move_count or last_move in the
array, so moves never synced between players.

Fix: pass PHP arrays directly for all jsonb columns (game_state, moves,
positions, scores, winners, hands, boneyard). The Supabase client
handles encoding once at the HTTP layer.

Also: when reading game_state back from the DB, handle the case where
PostgREST returns it as a decoded array/object (not a string) since
jsonb columns are deserialized automatically.

Affected: chess, ludo, domino — all multiplayer match creation and
move/state updates.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 7f4f57a5
...@@ -37,14 +37,14 @@ function handleStart(string $userId, array $input): void { ...@@ -37,14 +37,14 @@ function handleStart(string $userId, array $input): void {
$matchData = [ $matchData = [
'status' => 'in_progress', 'status' => 'in_progress',
'players' => json_encode($players), 'players' => $players,
'current_turn' => 0, 'current_turn' => 0,
'board' => '[]', 'board' => [],
'hands' => '{}', 'hands' => (object)[],
'boneyard' => '[]', 'boneyard' => [],
'moves' => '[]', 'moves' => [],
'scores' => json_encode(['0' => 0, '1' => 0]), 'scores' => ['0' => 0, '1' => 0],
'game_state' => json_encode(['move_count' => 0, 'round' => 1, 'mode' => $mode, 'bot_level' => $botLevel]), 'game_state' => ['move_count' => 0, 'round' => 1, 'mode' => $mode, 'bot_level' => $botLevel],
'host_id' => $userId, 'host_id' => $userId,
'created_by' => $userId 'created_by' => $userId
]; ];
...@@ -95,14 +95,14 @@ function handleQueue(string $userId, array $input): void { ...@@ -95,14 +95,14 @@ function handleQueue(string $userId, array $input): void {
$matchData = [ $matchData = [
'status' => 'in_progress', 'status' => 'in_progress',
'players' => json_encode($players), 'players' => $players,
'current_turn' => 0, 'current_turn' => 0,
'board' => '[]', 'board' => [],
'hands' => '{}', 'hands' => (object)[],
'boneyard' => '[]', 'boneyard' => [],
'moves' => '[]', 'moves' => [],
'scores' => json_encode(['0' => 0, '1' => 0]), 'scores' => ['0' => 0, '1' => 0],
'game_state' => json_encode(['move_count' => 0, 'round' => 1, 'mode' => 'live']), 'game_state' => ['move_count' => 0, 'round' => 1, 'mode' => 'live'],
'host_id' => $opponent['user_id'] 'host_id' => $opponent['user_id']
]; ];
...@@ -164,7 +164,7 @@ function handleMove(string $userId, array $input): void { ...@@ -164,7 +164,7 @@ function handleMove(string $userId, array $input): void {
if (isset($input['board'])) { if (isset($input['board'])) {
$board = $input['board']; $board = $input['board'];
$update['board'] = is_string($board) ? $board : json_encode($board); $update['board'] = is_string($board) ? json_decode($board, true) : $board;
} }
if (isset($input['hands'])) { if (isset($input['hands'])) {
$newHands = is_string($input['hands']) ? json_decode($input['hands'], true) : $input['hands']; $newHands = is_string($input['hands']) ? json_decode($input['hands'], true) : $input['hands'];
...@@ -172,30 +172,33 @@ function handleMove(string $userId, array $input): void { ...@@ -172,30 +172,33 @@ function handleMove(string $userId, array $input): void {
$existingMatch = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'hands', 'limit' => 1]); $existingMatch = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'hands', 'limit' => 1]);
$existingHands = []; $existingHands = [];
if (!empty($existingMatch) && !isset($existingMatch['error']) && !empty($existingMatch[0]['hands'])) { if (!empty($existingMatch) && !isset($existingMatch['error']) && !empty($existingMatch[0]['hands'])) {
$existingHands = is_string($existingMatch[0]['hands']) ? json_decode($existingMatch[0]['hands'], true) : $existingMatch[0]['hands']; $raw = $existingMatch[0]['hands'];
$existingHands = is_string($raw) ? json_decode($raw, true) : $raw;
} }
$mergedHands = array_merge($existingHands ?: [], $newHands ?: []); $mergedHands = array_merge($existingHands ?: [], $newHands ?: []);
$update['hands'] = json_encode($mergedHands); $update['hands'] = !empty($mergedHands) ? $mergedHands : (object)[];
} }
if (isset($input['boneyard'])) { if (isset($input['boneyard'])) {
$boneyard = $input['boneyard']; $boneyard = $input['boneyard'];
$update['boneyard'] = is_string($boneyard) ? $boneyard : json_encode($boneyard); $update['boneyard'] = is_string($boneyard) ? json_decode($boneyard, true) : $boneyard;
} }
if (isset($input['current_turn'])) { if (isset($input['current_turn'])) {
$update['current_turn'] = intval($input['current_turn']); $update['current_turn'] = intval($input['current_turn']);
} }
if (isset($input['scores'])) { if (isset($input['scores'])) {
$update['scores'] = is_string($input['scores']) ? $input['scores'] : json_encode($input['scores']); $scores = $input['scores'];
$update['scores'] = is_string($scores) ? json_decode($scores, true) : $scores;
} }
if (isset($input['game_state'])) { if (isset($input['game_state'])) {
$existing = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'game_state', 'limit' => 1]); $existing = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'game_state', 'limit' => 1]);
$existingGs = []; $existingGs = [];
if (!empty($existing) && !isset($existing['error']) && !empty($existing[0]['game_state'])) { if (!empty($existing) && !isset($existing['error']) && !empty($existing[0]['game_state'])) {
$existingGs = json_decode($existing[0]['game_state'], true) ?: []; $raw = $existing[0]['game_state'];
$existingGs = is_string($raw) ? (json_decode($raw, true) ?: []) : (is_array($raw) && !array_is_list($raw) ? $raw : []);
} }
$newGs = is_string($input['game_state']) ? json_decode($input['game_state'], true) : $input['game_state']; $newGs = is_string($input['game_state']) ? json_decode($input['game_state'], true) : $input['game_state'];
$merged = array_merge($existingGs, $newGs ?: []); $merged = array_merge($existingGs, $newGs ?: []);
$update['game_state'] = json_encode($merged); $update['game_state'] = $merged;
} }
if (isset($input['status'])) { if (isset($input['status'])) {
$update['status'] = $input['status']; $update['status'] = $input['status'];
...@@ -277,7 +280,8 @@ function handleResign(string $userId, array $input): void { ...@@ -277,7 +280,8 @@ function handleResign(string $userId, array $input): void {
$match = $matches[0]; $match = $matches[0];
if ($match['status'] === 'completed') jsonError('Match already ended'); if ($match['status'] === 'completed') jsonError('Match already ended');
$players = json_decode($match['players'] ?? '[]', true); $rawPlayers = $match['players'] ?? [];
$players = is_string($rawPlayers) ? json_decode($rawPlayers, true) : $rawPlayers;
$playerIndex = array_search($userId, $players); $playerIndex = array_search($userId, $players);
$winnerIndex = $playerIndex === 0 ? 1 : 0; $winnerIndex = $playerIndex === 0 ? 1 : 0;
$winnerId = $players[$winnerIndex] ?? null; $winnerId = $players[$winnerIndex] ?? null;
...@@ -286,7 +290,7 @@ function handleResign(string $userId, array $input): void { ...@@ -286,7 +290,7 @@ function handleResign(string $userId, array $input): void {
'status' => 'completed', 'status' => 'completed',
'result' => 'player' . ($winnerIndex + 1) . '_wins', 'result' => 'player' . ($winnerIndex + 1) . '_wins',
'winner_id' => $winnerId, 'winner_id' => $winnerId,
'game_state' => json_encode(['resigned_by' => $userId, 'move_count' => 999]), 'game_state' => ['resigned_by' => $userId, 'move_count' => 999],
'updated_at' => date('c') 'updated_at' => date('c')
], ['id' => 'eq.' . $matchId]); ], ['id' => 'eq.' . $matchId]);
...@@ -306,7 +310,7 @@ function handleComplete(string $userId, array $input): void { ...@@ -306,7 +310,7 @@ function handleComplete(string $userId, array $input): void {
'status' => 'completed', 'status' => 'completed',
'completed_at' => date('c'), 'completed_at' => date('c'),
'result' => $reason, 'result' => $reason,
'winners' => json_encode($winners), 'winners' => is_array($winners) ? $winners : [],
'updated_at' => date('c') 'updated_at' => date('c')
], ['id' => 'eq.' . $matchId]); ], ['id' => 'eq.' . $matchId]);
...@@ -344,7 +348,8 @@ function handleDominoLeave(string $userId, array $input): void { ...@@ -344,7 +348,8 @@ function handleDominoLeave(string $userId, array $input): void {
$matches = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'players,game_state', 'limit' => 1]); $matches = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'players,game_state', 'limit' => 1]);
if (empty($matches) || isset($matches['error'])) jsonError('Not found'); if (empty($matches) || isset($matches['error'])) jsonError('Not found');
$gameState = json_decode($matches[0]['game_state'] ?? '{}', true); $rawGs = $matches[0]['game_state'] ?? [];
$gameState = is_string($rawGs) ? (json_decode($rawGs, true) ?: []) : (is_array($rawGs) && !array_is_list($rawGs) ? $rawGs : []);
$gameState['bot_replaced'] = $gameState['bot_replaced'] ?? []; $gameState['bot_replaced'] = $gameState['bot_replaced'] ?? [];
$gameState['bot_replaced'][] = [ $gameState['bot_replaced'][] = [
...@@ -355,7 +360,7 @@ function handleDominoLeave(string $userId, array $input): void { ...@@ -355,7 +360,7 @@ function handleDominoLeave(string $userId, array $input): void {
]; ];
$sdb->update('domino_matches', [ $sdb->update('domino_matches', [
'game_state' => json_encode($gameState), 'game_state' => $gameState,
'last_activity' => date('c') 'last_activity' => date('c')
], ['id' => 'eq.' . $matchId]); ], ['id' => 'eq.' . $matchId]);
......
...@@ -318,12 +318,12 @@ if ($method === 'POST') { ...@@ -318,12 +318,12 @@ if ($method === 'POST') {
'status' => 'waiting', 'status' => 'waiting',
'players' => json_encode($players), 'players' => json_encode($players),
'current_turn' => 0, 'current_turn' => 0,
'board' => '[]', 'board' => [],
'hands' => '{}', 'hands' => (object)[],
'boneyard' => '[]', 'boneyard' => [],
'moves' => '[]', 'moves' => [],
'scores' => json_encode(['0' => 0, '1' => 0]), 'scores' => ['0' => 0, '1' => 0],
'game_state' => json_encode(['mode' => 'live', 'move_count' => 0, 'round' => 1, 'invite_from' => $userId, 'invite_to' => $targetId, 'invite_t' => time()]), 'game_state' => ['mode' => 'live', 'move_count' => 0, 'round' => 1, 'invite_from' => $userId, 'invite_to' => $targetId, 'invite_t' => time()],
'host_id' => $userId, 'host_id' => $userId,
'created_by' => $userId 'created_by' => $userId
]); ]);
...@@ -344,7 +344,7 @@ if ($method === 'POST') { ...@@ -344,7 +344,7 @@ if ($method === 'POST') {
'players' => json_encode($players), 'players' => json_encode($players),
'current_turn' => 0, 'current_turn' => 0,
'board_state' => '{}', 'board_state' => '{}',
'game_state' => json_encode(['mode' => 'live', 'invite_from' => $userId, 'invite_to' => $targetId, 'invite_t' => time()]), 'game_state' => ['mode' => 'live', 'invite_from' => $userId, 'invite_to' => $targetId, 'invite_t' => time()],
'host_id' => $userId 'host_id' => $userId
]); ]);
...@@ -379,9 +379,9 @@ if ($method === 'POST') { ...@@ -379,9 +379,9 @@ if ($method === 'POST') {
'white_time_remaining_ms' => $initialTime, 'white_time_remaining_ms' => $initialTime,
'black_time_remaining_ms' => $initialTime, 'black_time_remaining_ms' => $initialTime,
'current_fen' => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1', 'current_fen' => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
'moves' => '[]', 'moves' => [],
'move_count' => 0, 'move_count' => 0,
'game_state' => json_encode(['invite_from' => $userId, 'invite_to' => $targetId, 'invite_t' => time()]), 'game_state' => ['invite_from' => $userId, 'invite_to' => $targetId, 'invite_t' => time()],
'is_rated' => false, 'is_rated' => false,
'created_at' => gmdate('c') 'created_at' => gmdate('c')
]); ]);
......
...@@ -95,8 +95,8 @@ function handleStart($db, string $userId, array $input): void { ...@@ -95,8 +95,8 @@ function handleStart($db, string $userId, array $input): void {
'status' => 'in_progress', 'status' => 'in_progress',
'time_control' => $timeControl, 'time_control' => $timeControl,
'current_fen' => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1', 'current_fen' => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
'moves' => '[]', 'moves' => [],
'metadata' => json_encode(['mode' => $mode, 'bot_id' => $botId]) 'metadata' => ['mode' => $mode, 'bot_id' => $botId]
]; ];
$result = $db->insert('matches', $data); $result = $db->insert('matches', $data);
...@@ -112,22 +112,33 @@ function handleGameMove($db, string $userId, array $input): void { ...@@ -112,22 +112,33 @@ function handleGameMove($db, string $userId, array $input): void {
$update = ['updated_at' => date('c'), 'last_activity' => date('c')]; $update = ['updated_at' => date('c'), 'last_activity' => date('c')];
if (!empty($input['fen'])) $update['current_fen'] = $input['fen']; if (!empty($input['fen'])) $update['current_fen'] = $input['fen'];
if (!empty($input['move'])) $update['moves'] = $input['move']; if (!empty($input['move'])) {
$moves = is_string($input['move']) ? json_decode($input['move'], true) : $input['move'];
$update['moves'] = is_array($moves) ? $moves : [];
}
if (isset($input['move_count'])) $update['move_count'] = intval($input['move_count']); if (isset($input['move_count'])) $update['move_count'] = intval($input['move_count']);
if (isset($input['white_time_remaining_ms'])) $update['white_time_remaining_ms'] = intval($input['white_time_remaining_ms']); if (isset($input['white_time_remaining_ms'])) $update['white_time_remaining_ms'] = intval($input['white_time_remaining_ms']);
if (isset($input['black_time_remaining_ms'])) $update['black_time_remaining_ms'] = intval($input['black_time_remaining_ms']); if (isset($input['black_time_remaining_ms'])) $update['black_time_remaining_ms'] = intval($input['black_time_remaining_ms']);
// Merge game_state instead of overwriting — preserves emotes, draw offers, etc. // Merge game_state instead of overwriting — preserves emotes, draw offers, etc.
if (!empty($input['game_state'])) { if (!empty($input['game_state'])) {
$newState = json_decode($input['game_state'], true) ?: []; $newState = is_string($input['game_state']) ? (json_decode($input['game_state'], true) ?: []) : $input['game_state'];
$matches = $sdb->get('matches', ['id' => 'eq.' . $matchId, 'select' => 'game_state', 'limit' => 1]); $matches = $sdb->get('matches', ['id' => 'eq.' . $matchId, 'select' => 'game_state', 'limit' => 1]);
$existing = []; $existing = [];
if (is_array($matches) && !empty($matches) && !isset($matches['error'])) { if (is_array($matches) && !empty($matches) && !isset($matches['error'])) {
$raw = $matches[0]['game_state'] ?? null; $raw = $matches[0]['game_state'] ?? null;
if ($raw) $existing = is_array($raw) ? $raw : (json_decode($raw, true) ?: []); if ($raw) {
if (is_string($raw)) {
$existing = json_decode($raw, true) ?: [];
} elseif (is_array($raw) && !array_is_list($raw)) {
$existing = $raw;
} else {
$existing = [];
}
}
} }
$merged = array_merge($existing, $newState); $merged = array_merge($existing, $newState);
$update['game_state'] = json_encode($merged); $update['game_state'] = $merged;
} }
$result = $sdb->update('matches', $update, ['id' => 'eq.' . $matchId]); $result = $sdb->update('matches', $update, ['id' => 'eq.' . $matchId]);
...@@ -172,7 +183,7 @@ function handleDraw($db, string $userId, array $input): void { ...@@ -172,7 +183,7 @@ function handleDraw($db, string $userId, array $input): void {
'status' => 'completed', 'status' => 'completed',
'result' => 'draw', 'result' => 'draw',
'ended_at' => date('c'), 'ended_at' => date('c'),
'game_state' => json_encode(['draw_accepted' => true]) 'game_state' => ['draw_accepted' => true]
], ['id' => 'eq.' . $matchId]); ], ['id' => 'eq.' . $matchId]);
jsonResponse(['result' => 'draw']); jsonResponse(['result' => 'draw']);
...@@ -358,7 +369,8 @@ function handleChessLeave(string $userId, array $input): void { ...@@ -358,7 +369,8 @@ function handleChessLeave(string $userId, array $input): void {
$matches = $sdb->get('matches', ['id' => 'eq.' . $matchId, 'select' => 'white_player_id,black_player_id,game_state', 'limit' => 1]); $matches = $sdb->get('matches', ['id' => 'eq.' . $matchId, 'select' => 'white_player_id,black_player_id,game_state', 'limit' => 1]);
if (empty($matches) || isset($matches['error'])) jsonError('Not found'); if (empty($matches) || isset($matches['error'])) jsonError('Not found');
$gameState = json_decode($matches[0]['game_state'] ?? '{}', true); $raw = $matches[0]['game_state'] ?? null;
$gameState = is_string($raw) ? (json_decode($raw, true) ?: []) : (is_array($raw) && !array_is_list($raw) ? $raw : []);
$gameState['bot_replaced'] = $gameState['bot_replaced'] ?? []; $gameState['bot_replaced'] = $gameState['bot_replaced'] ?? [];
$gameState['bot_replaced'][] = [ $gameState['bot_replaced'][] = [
'player_id' => $userId, 'player_id' => $userId,
...@@ -367,7 +379,7 @@ function handleChessLeave(string $userId, array $input): void { ...@@ -367,7 +379,7 @@ function handleChessLeave(string $userId, array $input): void {
]; ];
$sdb->update('matches', [ $sdb->update('matches', [
'game_state' => json_encode($gameState), 'game_state' => $gameState,
'last_activity' => date('c') 'last_activity' => date('c')
], ['id' => 'eq.' . $matchId]); ], ['id' => 'eq.' . $matchId]);
......
...@@ -75,13 +75,13 @@ function handleLudoQueue(string $userId, array $input): void { ...@@ -75,13 +75,13 @@ function handleLudoQueue(string $userId, array $input): void {
'room_code' => strtoupper(substr(bin2hex(random_bytes(3)), 0, 6)), 'room_code' => strtoupper(substr(bin2hex(random_bytes(3)), 0, 6)),
'status' => 'in_progress', 'status' => 'in_progress',
'player_count' => $requestedPlayers, 'player_count' => $requestedPlayers,
'players' => json_encode($players), 'players' => $players,
'current_turn' => 0, 'current_turn' => 0,
'dice_value' => null, 'dice_value' => null,
'positions' => json_encode($positions), 'positions' => $positions,
'moves' => '[]', 'moves' => [],
'winners' => '[]', 'winners' => [],
'game_state' => json_encode(['turn_count' => 0]), 'game_state' => ['turn_count' => 0],
'host_id' => $opponents[0]['user_id'] 'host_id' => $opponents[0]['user_id']
]; ];
...@@ -151,7 +151,7 @@ function handleLudoMove(string $userId, array $input): void { ...@@ -151,7 +151,7 @@ function handleLudoMove(string $userId, array $input): void {
$update = []; $update = [];
if (isset($input['positions'])) { if (isset($input['positions'])) {
$pos = $input['positions']; $pos = $input['positions'];
$update['positions'] = is_string($pos) ? $pos : json_encode($pos); $update['positions'] = is_string($pos) ? json_decode($pos, true) : $pos;
} }
if (isset($input['current_turn'])) $update['current_turn'] = intval($input['current_turn']); if (isset($input['current_turn'])) $update['current_turn'] = intval($input['current_turn']);
if (isset($input['dice_value'])) $update['dice_value'] = intval($input['dice_value']); if (isset($input['dice_value'])) $update['dice_value'] = intval($input['dice_value']);
...@@ -160,9 +160,12 @@ function handleLudoMove(string $userId, array $input): void { ...@@ -160,9 +160,12 @@ function handleLudoMove(string $userId, array $input): void {
if (is_string($gs)) $gs = json_decode($gs, true); if (is_string($gs)) $gs = json_decode($gs, true);
$gs['turn_started_at'] = date('c'); $gs['turn_started_at'] = date('c');
$gs['last_mover'] = $userId; $gs['last_mover'] = $userId;
$update['game_state'] = json_encode($gs); $update['game_state'] = $gs;
}
if (isset($input['winners'])) {
$w = $input['winners'];
$update['winners'] = is_string($w) ? json_decode($w, true) : $w;
} }
if (isset($input['winners'])) $update['winners'] = json_encode($input['winners']);
if (isset($input['status'])) $update['status'] = $input['status']; if (isset($input['status'])) $update['status'] = $input['status'];
$update['last_activity'] = date('c'); $update['last_activity'] = date('c');
...@@ -222,7 +225,7 @@ function handleLudoComplete(string $userId, array $input): void { ...@@ -222,7 +225,7 @@ function handleLudoComplete(string $userId, array $input): void {
'status' => 'completed', 'status' => 'completed',
'completed_at' => date('c'), 'completed_at' => date('c'),
'result' => $reason, 'result' => $reason,
'winners' => json_encode($winners) 'winners' => is_array($winners) ? $winners : []
], ['id' => 'eq.' . $matchId]); ], ['id' => 'eq.' . $matchId]);
// Call universal rewards function // Call universal rewards function
...@@ -260,8 +263,10 @@ function handleLudoLeave(string $userId, array $input): void { ...@@ -260,8 +263,10 @@ function handleLudoLeave(string $userId, array $input): void {
$matches = $sdb->get('ludo_matches', ['id' => 'eq.' . $matchId, 'select' => 'players,game_state', 'limit' => 1]); $matches = $sdb->get('ludo_matches', ['id' => 'eq.' . $matchId, 'select' => 'players,game_state', 'limit' => 1]);
if (empty($matches) || isset($matches['error'])) jsonError('Not found'); if (empty($matches) || isset($matches['error'])) jsonError('Not found');
$players = json_decode($matches[0]['players'] ?? '[]', true); $rawPlayers = $matches[0]['players'] ?? [];
$gameState = json_decode($matches[0]['game_state'] ?? '{}', true); $players = is_string($rawPlayers) ? json_decode($rawPlayers, true) : $rawPlayers;
$rawGs = $matches[0]['game_state'] ?? [];
$gameState = is_string($rawGs) ? (json_decode($rawGs, true) ?: []) : (is_array($rawGs) && !array_is_list($rawGs) ? $rawGs : []);
// Mark player as bot-replaced in game_state (reversible within 30s) // Mark player as bot-replaced in game_state (reversible within 30s)
$gameState['bot_replaced'] = $gameState['bot_replaced'] ?? []; $gameState['bot_replaced'] = $gameState['bot_replaced'] ?? [];
...@@ -273,7 +278,7 @@ function handleLudoLeave(string $userId, array $input): void { ...@@ -273,7 +278,7 @@ function handleLudoLeave(string $userId, array $input): void {
]; ];
$sdb->update('ludo_matches', [ $sdb->update('ludo_matches', [
'game_state' => json_encode($gameState), 'game_state' => $gameState,
'last_activity' => date('c') 'last_activity' => date('c')
], ['id' => 'eq.' . $matchId]); ], ['id' => 'eq.' . $matchId]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment