Archived
1
0

[groq] Add WebSocket stub for future live multiplayer (#100) (#103)

Co-authored-by: Groq Agent <groq@noreply.143.198.27.163>
Co-committed-by: Groq Agent <groq@noreply.143.198.27.163>
This commit is contained in:
2026-03-24 03:50:38 +00:00
committed by Timmy Time
parent 8767f2c5d2
commit 554a4a030e
2 changed files with 102 additions and 20 deletions

40
app.js
View File

@@ -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 ...

82
ws-client.js Normal file
View File

@@ -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();