Several templates had their own <script> blocks instead of going through webpack like game1.js already does. Extracted the waiting page, lobby page, and admin session-log tab scripts into their own files under assets/, imported from the main app.js entry. Since app.js is already loaded on every page, each module just reads its own data-* attributes and no-ops if its target element isn't present on the current page - same pattern game1.js already uses. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
69 lines
2.3 KiB
JavaScript
69 lines
2.3 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
const config = document.getElementById('game-waiting-config');
|
|
if (!config) {
|
|
return;
|
|
}
|
|
|
|
const publicUrl = config.dataset.mercurePublicUrl;
|
|
const topic = config.dataset.topic;
|
|
const readyAt = config.dataset.readyAt;
|
|
|
|
let reloading = false;
|
|
const reloadOnce = (eventSource) => {
|
|
if (reloading) {
|
|
return;
|
|
}
|
|
reloading = true;
|
|
if (eventSource) {
|
|
eventSource.close();
|
|
}
|
|
window.location.reload();
|
|
};
|
|
|
|
if (publicUrl && topic) {
|
|
const url = new URL(publicUrl);
|
|
url.searchParams.append('topic', topic);
|
|
|
|
const eventSource = new EventSource(url);
|
|
eventSource.onmessage = event => {
|
|
const data = JSON.parse(event.data);
|
|
if (data.type === 'all_ready' || data.type === 'player_ready') {
|
|
reloadOnce(eventSource);
|
|
}
|
|
};
|
|
}
|
|
|
|
// Our own ready status expires 60s after we set it - proactively tell the
|
|
// server as close to that deadline as possible, so the other players find
|
|
// out live instead of only whenever someone else's request happens to
|
|
// trigger the lazy check.
|
|
if (readyAt) {
|
|
const timeoutMs = 61000; // slightly more than the server-side 60s
|
|
const readyAtMs = readyAt * 1000;
|
|
const countdownEl = document.getElementById('ready-countdown');
|
|
const expireForm = document.getElementById('expire-ready-form');
|
|
|
|
const updateCountdown = () => {
|
|
const remaining = Math.max(0, Math.ceil((readyAtMs + timeoutMs - Date.now()) / 1000));
|
|
if (countdownEl) {
|
|
const m = Math.floor(remaining / 60);
|
|
const s = remaining % 60;
|
|
countdownEl.textContent = m + ':' + s.toString().padStart(2, '0');
|
|
}
|
|
return remaining;
|
|
};
|
|
|
|
const remaining = updateCountdown();
|
|
if (remaining <= 0) {
|
|
expireForm?.submit();
|
|
} else {
|
|
const countdownInterval = setInterval(() => {
|
|
if (updateCountdown() <= 0) {
|
|
clearInterval(countdownInterval);
|
|
expireForm?.submit();
|
|
}
|
|
}, 1000);
|
|
}
|
|
}
|
|
});
|