39001-vm/api/room_stream.php
2026-03-05 10:39:31 +00:00

100 lines
2.6 KiB
PHP

<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
session_start();
require_once __DIR__ . '/../includes/rooms.php';
ensure_rooms_schema();
$roomId = (int) ($_GET['room_id'] ?? 0);
if ($roomId <= 0) {
http_response_code(400);
header('Content-Type: application/json');
echo json_encode(['success' => false, 'error' => 'Missing room id']);
exit;
}
$sessionPlayer = get_session_player($roomId);
$playerToken = $sessionPlayer['token'] ?? null;
session_write_close();
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
header('X-Accel-Buffering: no');
@ini_set('zlib.output_compression', '0');
@ini_set('output_buffering', '0');
while (ob_get_level() > 0) {
@ob_end_flush();
}
ob_implicit_flush(true);
set_time_limit(0);
ignore_user_abort(true);
$startedAt = time();
$lastHash = '';
while (!connection_aborted()) {
$room = get_room($roomId);
if (!$room) {
echo "event: room_closed\n";
echo 'data: {"success":false,"error":"Room not found"}' . "\n\n";
flush();
break;
}
$state = $room['state'] ?? [];
$hasDynamicObjects = !empty($state['bombs']) || !empty($state['explosions']);
if ($room['status'] === 'playing' || $hasDynamicObjects) {
$room = update_room_tick($room);
save_room_state((int) $room['id'], $room['state'], (string) $room['status']);
}
$payload = [
'success' => true,
'room' => [
'id' => (int) $room['id'],
'name' => $room['name'],
'status' => $room['status'],
'max_players' => (int) $room['max_players'],
],
'state' => $room['state'],
'player_token' => $playerToken,
'server_time' => now_ms(),
];
$json = json_encode($payload, JSON_UNESCAPED_UNICODE);
if ($json === false) {
break;
}
$stateForHash = $payload['state'];
unset($stateForHash['last_tick']);
$hash = sha1(json_encode([
'room' => $payload['room'],
'state' => $stateForHash,
'player_token' => $payload['player_token'],
], JSON_UNESCAPED_UNICODE) ?: $json);
if ($hash !== $lastHash) {
$lastHash = $hash;
echo "event: state\n";
echo 'data: ' . $json . "\n\n";
flush();
} else {
echo "event: ping\n";
echo 'data: {"ts":' . now_ms() . "}\n\n";
flush();
}
usleep(($room['status'] === 'playing') ? 120000 : 350000);
if ((time() - $startedAt) >= 25) {
break;
}
}