diff --git a/app.js b/app.js index 4a3faa1..051fe82 100644 --- a/app.js +++ b/app.js @@ -1,27 +1,27 @@ // ... existing code ... -// === AMBIENT SOUND TOGGLE === -let ambientSound = document.getElementById('ambient-sound'); -let audioToggle = document.getElementById('audio-toggle'); +// === WEBSOCKET CLIENT === +import { wsClient } from './ws-client.js'; -// Load user's audio preference -const storedMute = localStorage.getItem('nexus-ambient-muted') === 'true'; -if (storedMute) { - ambientSound.muted = true; - audioToggle.classList.add('muted'); -} else { - ambientSound.muted = false; - audioToggle.classList.remove('muted'); -} +// Initialize WebSocket client +wsClient.connect(); -audioToggle.addEventListener('click', () => { - ambientSound.muted = !ambientSound.muted; - if (ambientSound.muted) { - audioToggle.classList.add('muted'); - } else { - audioToggle.classList.remove('muted'); - } - localStorage.setItem('nexus-ambient-muted', ambientSound.muted); +// Handle WebSocket events +window.addEventListener('player-joined', (event) => { + console.log('Player joined:', event.detail); +}); + +window.addEventListener('player-left', (event) => { + console.log('Player left:', event.detail); +}); + +window.addEventListener('chat-message', (event) => { + console.log('Chat message:', event.detail); +}); + +// Clean up on page unload +window.addEventListener('beforeunload', () => { + wsClient.disconnect(); }); // ... existing code ... diff --git a/ws-client.js b/ws-client.js new file mode 100644 index 0000000..fb278d8 --- /dev/null +++ b/ws-client.js @@ -0,0 +1,82 @@ +export class WebSocketClient { + constructor(url = 'wss://localhost:8080') { + this.url = url; + this.reconnectAttempts = 0; + this.maxReconnectAttempts = 5; + this.reconnectDelay = 1000; + this.maxReconnectDelay = 30000; + this.socket = null; + this.connected = false; + this.reconnectTimeout = null; + this.messageQueue = []; + } + + connect() { + if (this.socket && this.socket.readyState === WebSocket.OPEN) { + return; + } + + this.socket = new WebSocket(this.url); + + this.socket.onopen = () => { + this.connected = true; + this.reconnectAttempts = 0; + this.messageQueue.forEach(msg => this.send(msg)); + this.messageQueue = []; + window.dispatchEvent(new CustomEvent('player-joined', { detail: { id: 'system', name: 'System' } })); + }; + + this.socket.onmessage = (event) => { + const data = JSON.parse(event.data); + switch (data.type) { + case 'player-joined': + window.dispatchEvent(new CustomEvent('player-joined', { detail: data })); + break; + case 'player-left': + window.dispatchEvent(new CustomEvent('player-left', { detail: data })); + break; + case 'chat-message': + window.dispatchEvent(new CustomEvent('chat-message', { detail: data })); + break; + } + }; + + this.socket.onclose = () => { + this.connected = false; + this.reconnect(); + }; + + this.socket.onerror = (error) => { + console.error('WebSocket error:', error); + }; + } + + reconnect() { + if (this.reconnectAttempts >= this.maxReconnectAttempts) { + console.warn('Max reconnection attempts reached.'); + return; + } + + this.reconnectTimeout = setTimeout(() => { + this.reconnectAttempts++; + this.connect(); + }, Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts), this.maxReconnectDelay)); + } + + send(message) { + if (this.connected) { + this.socket.send(JSON.stringify(message)); + } else { + this.messageQueue.push(message); + } + } + + disconnect() { + if (this.socket) { + this.socket.close(); + } + } +} + +// Initialize and export a singleton instance +export const wsClient = new WebSocketClient();