Add win/lose game-ending flow
Removing all 3 locked files while the timer is still running now marks
the session WON immediately (checked right after every successful rm)
and broadcasts a "game_finished" signal over Mercure so every
connected player gets redirected together, not just the one who
removed the last file. A new /won/{session} route + won.html.twig
mirrors the existing lost flow (victory narrative + the same feedback
form).
The existing timer-expiry path already set LOST but always redirected
to lostUrl regardless of actual status; it now picks won/lost based on
the status the server reports.
Also fixes a pre-existing bug on the lost page (and would-be bug on
the new won page): PlayerService::GetCurrentlyActiveAsPlayer() only
matches players in READY/PLAYING sessions, so by the time a session
has ended it always returned null there, silently breaking the
feedback form. Both pages now look the player up directly via
PlayerRepository instead.
Added a navigatingAway flag so the page's "confirm before leaving"
prompt doesn't block our own win/lose redirects.
This commit is contained in:
+27
-4
@@ -3,8 +3,14 @@ import './styles/game1.css';
|
||||
|
||||
let sequenceFinished = false;
|
||||
let stillPlayingSound = true;
|
||||
let navigatingAway = false;
|
||||
|
||||
function subscribeToMercure(mercurePublicUrl, topic, myScreen) {
|
||||
function goTo(url) {
|
||||
navigatingAway = true;
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
function subscribeToMercure(mercurePublicUrl, topic, myScreen, wonUrl, lostUrl) {
|
||||
try {
|
||||
const url = mercurePublicUrl + '?topic=' + encodeURIComponent(topic);
|
||||
const es = new EventSource(url);
|
||||
@@ -14,6 +20,14 @@ function subscribeToMercure(mercurePublicUrl, topic, myScreen) {
|
||||
const data = JSON.parse(event.data);
|
||||
console.log('[Mercure][game1] Update:', data);
|
||||
|
||||
if (data && !Array.isArray(data) && data.type === 'game_finished') {
|
||||
const destination = data.status === 'won' ? wonUrl : lostUrl;
|
||||
if (destination) {
|
||||
goTo(destination);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// data is [sendTo, message, messageType?] - messageType defaults to 'mainframe' (green)
|
||||
if (Array.isArray(data) && data.length >= 2) {
|
||||
const sendTo = parseInt(data[0]);
|
||||
@@ -249,8 +263,11 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
// Look for config injected by Twig in the page
|
||||
const cfgEl = document.getElementById('mercure-config');
|
||||
|
||||
// Prevent/warn on page reload
|
||||
// Prevent/warn on page reload, except for our own win/lose redirects
|
||||
window.addEventListener('beforeunload', (event) => {
|
||||
if (navigatingAway) {
|
||||
return;
|
||||
}
|
||||
// Standard way to trigger the browser's confirmation dialog
|
||||
event.preventDefault();
|
||||
// Included for compatibility with older browsers
|
||||
@@ -269,6 +286,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
const apiEchoUrl = cfgEl.dataset.apiEchoUrl;
|
||||
const apiCheckFinishedUrl = cfgEl.dataset.apiCheckFinishedUrl;
|
||||
const lostUrl = cfgEl.dataset.lostUrl;
|
||||
const wonUrl = cfgEl.dataset.wonUrl;
|
||||
const lockLockedAt = cfgEl.dataset.lockLockedAt;
|
||||
const lockRevealAt = cfgEl.dataset.lockRevealAt;
|
||||
const lockUnlockAt = cfgEl.dataset.lockUnlockAt;
|
||||
@@ -280,7 +298,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
}
|
||||
|
||||
if (mercurePublicUrl && topic) {
|
||||
subscribeToMercure(mercurePublicUrl, topic, screen);
|
||||
subscribeToMercure(mercurePublicUrl, topic, screen, wonUrl, lostUrl);
|
||||
} else {
|
||||
console.warn('[Mercure][game1] Missing data attributes on #mercure-config');
|
||||
}
|
||||
@@ -302,7 +320,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
try {
|
||||
const response = await fetchJson(apiCheckFinishedUrl, { method: 'POST' });
|
||||
if (response && response.finished) {
|
||||
window.location.href = lostUrl;
|
||||
goTo(response.status === 'won' && wonUrl ? wonUrl : lostUrl);
|
||||
return; // Stop the timer loop
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -424,6 +442,11 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
window.scrollTo(0, document.body.scrollHeight);
|
||||
}
|
||||
if (response && response.result) {
|
||||
if (response.result.gameWon === true && wonUrl) {
|
||||
goTo(wonUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.result.locked === true) {
|
||||
applyLock({
|
||||
lockedAt: response.result.lockedAt,
|
||||
|
||||
Reference in New Issue
Block a user