Bring back 1-minute ready-status expiry with live per-player broadcasts
A player's own browser now starts a 60s timer the moment they check "ready" (with a visible countdown) and proactively tells the server when it's up via a new expire_ready action - idempotent, so it only actually clears the status if the deadline has genuinely passed. Everyone else finds out live through a Mercure player_ready broadcast that now carries which player and their new ready/not-ready state (previously the broadcast payload's `ready` flag was always false due to a stale-variable bug, though nothing consumed it yet). checkAllPlayersReady() still does the same expiry check server-side and broadcasts on anyone else's request in the meantime, so a stalled frontend timer doesn't leave a stale "ready" badge showing forever. This only affects the pre-PLAYING ready phase: checkAllPlayersReady() still flips the session to PLAYING and stops touching ready state the instant everyone is simultaneously ready, so the earlier fix (a reload should never send an already-started game back to the waiting room) is unaffected. Also fixed the ready checkbox itself: unchecking it submitted a POST without `toggle_ready` in the body (unchecked checkboxes aren't sent), so un-readying silently did nothing server-side. Added the standard hidden-fallback-input pattern to fix it.
This commit is contained in:
@@ -136,6 +136,11 @@ final class GameController extends AbstractController
|
||||
return $this->redirectToRoute('game', ['session' => $session->getId()]);
|
||||
}
|
||||
|
||||
if ($request->isMethod('POST') && $request->request->has('expire_ready')) {
|
||||
$dashboardService->expireOwnReadyIfDue($session, $user);
|
||||
return $this->redirectToRoute('game', ['session' => $session->getId()]);
|
||||
}
|
||||
|
||||
// Lazily pick up readiness changes from other players since our last request
|
||||
$dashboardService->checkAllPlayersReady($session);
|
||||
|
||||
@@ -154,17 +159,22 @@ final class GameController extends AbstractController
|
||||
|
||||
if ($session->getStatus() === SessionStatus::READY) {
|
||||
$isReady = false;
|
||||
$readyAt = null;
|
||||
if ($player) {
|
||||
$settingName = SessionSettingType::tryFrom('ReadyAtForPlayer' . $player->getScreen());
|
||||
if ($settingName) {
|
||||
$setting = $session->getSettings()->filter(fn(SessionSetting $s) => $s->getName() === $settingName && $s->getPlayer() === $player)->first();
|
||||
$isReady = $setting !== null;
|
||||
if ($setting) {
|
||||
$isReady = true;
|
||||
$readyAt = (int)$setting->getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('game/waiting.html.twig', [
|
||||
'session' => $session,
|
||||
'isReady' => $isReady,
|
||||
'readyAt' => $readyAt,
|
||||
'mercure_public_url' => $this->mercurePublicUrl,
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user