/* Game1 entry point built with Webpack Encore */ import './styles/game1.css'; let sequenceFinished = false; let stillPlayingSound = true; function subscribeToMercure(mercurePublicUrl, topic) { try { const url = mercurePublicUrl + '?topic=' + encodeURIComponent(topic); const es = new EventSource(url); es.onmessage = (event) => { try { const data = JSON.parse(event.data); console.log('[Mercure][game1] Update:', data); // data is [sendTo, message] if (Array.isArray(data) && data.length >= 2) { const messageContainer = document.getElementById('message-container'); if (messageContainer) { const msgEl = document.createElement('div'); msgEl.className = 'message'; msgEl.textContent = data[1]; msgEl.style.color = '#0F0'; // Green for incoming messages msgEl.style.marginBottom = '10px'; messageContainer.appendChild(msgEl); window.scrollTo(0, document.body.scrollHeight); if(stillPlayingSound) playSound(); console.log('[Mercure][game1] sequenceFinished status:', sequenceFinished); if (sequenceFinished) { flashRed(); } } } } catch (e) { console.log('[Mercure][game1] Raw event:', event.data); } }; es.onerror = (err) => { console.warn('[Mercure][game1] EventSource error:', err); }; console.log('[Mercure][game1] Subscribed to', url); } catch (e) { console.error('[Mercure][game1] Failed to subscribe:', e); } } function playSound() { const sound = document.getElementById('message-sound'); if (sound) { sound.currentTime = 0; sound.play().catch(e => console.warn('[Audio] Playback failed:', e)); } } function flashRed() { console.log('[Game1] Triggering flashRed'); const body = document.body; body.classList.remove('flash-red'); void body.offsetWidth; // Trigger reflow to restart animation body.classList.add('flash-red'); // Also remove it after animation finishes so it's clean for inspection setTimeout(() => { body.classList.remove('flash-red'); console.log('[Game1] Removed flash-red class'); }, 150); } async function fetchJson(url, options = {}) { const opts = { ...options }; const headers = new Headers(opts.headers || {}); headers.set('Accept', 'application/json'); if (opts.body !== undefined && typeof opts.body !== 'string') { headers.set('Content-Type', 'application/json'); opts.body = JSON.stringify(opts.body); } // Useful convention for server-side checks if (!headers.has('X-Requested-With')) { headers.set('X-Requested-With', 'XMLHttpRequest'); } opts.headers = headers; const res = await fetch(url, opts); const text = await res.text(); let data; try { data = text ? JSON.parse(text) : null; } catch (e) { data = text; } if (!res.ok) { const err = new Error('HTTP ' + res.status + ' ' + res.statusText); console.error('[API][game1]', err, data); throw err; } return data; } document.addEventListener('DOMContentLoaded', async () => { // Simple boot log so you can verify it in the browser console // and confirm this specific bundle is loaded on the Game Hub page. console.log('Game1 bundle loaded'); // Example: add a CSS class to so page-specific styles can apply document.body.classList.add('game1-page'); // Look for config injected by Twig in the page const cfgEl = document.getElementById('mercure-config'); // Prevent/warn on page reload window.addEventListener('beforeunload', (event) => { // Standard way to trigger the browser's confirmation dialog event.preventDefault(); // Included for compatibility with older browsers event.returnValue = ''; }); if (!cfgEl) { console.warn('[Mercure][game1] #mercure-config element not found on page'); return; } const mercurePublicUrl = cfgEl.dataset.mercurePublicUrl; const topic = cfgEl.dataset.topic; const apiPingUrl = cfgEl.dataset.apiPingUrl; const apiEchoUrl = cfgEl.dataset.apiEchoUrl; if (mercurePublicUrl && topic) { subscribeToMercure(mercurePublicUrl, topic); } else { console.warn('[Mercure][game1] Missing data attributes on #mercure-config'); } // Demo API calls try { if (apiPingUrl) { const ping = await fetchJson(apiPingUrl); console.log('[API][game1] ping →', ping); } else { console.warn('[API][game1] data-api-ping-url missing'); } if (apiEchoUrl) { const echo = await fetchJson(apiEchoUrl, { method: 'POST', body: { message: 'from game1.js', ts: new Date().toISOString() }, }); console.log('[API][game1] echo →', echo); } else { console.warn('[API][game1] data-api-echo-url missing'); } } catch (e) { console.error('[API][game1] Request failed:', e); } // Add messages to message-container const messageContainer = document.getElementById('message-container'); if (messageContainer) { let messages = [ ['System initializing...', 500], ['Connection established.', 200], ['Welcome agent to the mainframe.', 1000], ['Scanning...', 3000], ['Virus detected.', 500], ['Starting Mainframe help modus...', 2000], ['Help modus activated.', 500], ['Blocking virus activated', 0] ]; let currentMessageIndex = 0; const printNextMessage = () => { if (currentMessageIndex < messages.length) { const msg = messages[currentMessageIndex]; const msgEl = document.createElement('div'); let extraClass = ''; if(msg[2]) extraClass = msg[2]; msgEl.className = 'message ' + extraClass; msgEl.textContent = msg[0]; msgEl.style.marginBottom = '10px'; messageContainer.appendChild(msgEl); window.scrollTo(0, document.body.scrollHeight); playSound(); currentMessageIndex++; setTimeout(printNextMessage, msg[1]); if (sequenceFinished) { flashRed(); } } else { // After it has printed a set of messages, it has to start a timer of 2 seconds console.log('[Game1] All messages printed. Starting 2s timer to expand message-container height...'); setTimeout(() => { messageContainer.style.height = '400vh'; const inputField = document.getElementById('input-message'); inputField.disabled = false; // Add event listener for Enter key inputField.addEventListener('keypress', async (e) => { if (e.key === 'Enter') { stillPlayingSound = false; sequenceFinished = false; const message = inputField.value.trim(); const msgEl = document.createElement('div'); msgEl.className = 'message'; msgEl.textContent = message; msgEl.style.marginBottom = '10px'; messageContainer.appendChild(msgEl); if (message && apiEchoUrl) { inputField.value = ''; try { const response = await fetchJson(apiEchoUrl, { method: 'POST', body: { message, ts: new Date().toISOString() }, }); console.log('[API][game1] message sent →', response); if (response && response.result && Array.isArray(response.result.result)) { response.result.result.forEach(text => { const msgEl = document.createElement('div'); msgEl.className = 'message'; msgEl.textContent = text; msgEl.style.marginBottom = '10px'; messageContainer.appendChild(msgEl); }); window.scrollTo(0, document.body.scrollHeight); } } catch (err) { console.error('[API][game1] Failed to send message:', err); } } } }); console.log('[Game1] message-container height changed to 400vh and input enabled'); sequenceFinished = true; console.log('[Game1] sequenceFinished is now TRUE'); }, 2000); } }; printNextMessage(); } });