chore: initial commit — CS2 Simulator
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
// WebSocket client for real-time features
|
||||
const WS = {
|
||||
_ws: null,
|
||||
_reconnectTimer: null,
|
||||
_listeners: {},
|
||||
_connected: false,
|
||||
|
||||
connect() {
|
||||
if (this._ws && this._ws.readyState === WebSocket.OPEN) return;
|
||||
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const url = `${protocol}//${window.location.host}/ws`;
|
||||
|
||||
try {
|
||||
this._ws = new WebSocket(url);
|
||||
} catch (e) {
|
||||
console.warn('WS connection failed, retrying in 5s');
|
||||
this._scheduleReconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
this._ws.onopen = () => {
|
||||
this._connected = true;
|
||||
this._emit('connected');
|
||||
};
|
||||
|
||||
this._ws.onclose = () => {
|
||||
this._connected = false;
|
||||
this._emit('disconnected');
|
||||
this._scheduleReconnect();
|
||||
};
|
||||
|
||||
this._ws.onerror = () => {
|
||||
this._emit('error');
|
||||
};
|
||||
|
||||
this._ws.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
this._emit(data.type, data);
|
||||
} catch (e) {
|
||||
// ignore non-JSON messages
|
||||
}
|
||||
};
|
||||
|
||||
// Keepalive ping every 30s
|
||||
this._pingInterval = setInterval(() => {
|
||||
if (this._ws && this._ws.readyState === WebSocket.OPEN) {
|
||||
this._ws.send(JSON.stringify({ type: 'ping' }));
|
||||
}
|
||||
}, 30000);
|
||||
},
|
||||
|
||||
disconnect() {
|
||||
if (this._pingInterval) clearInterval(this._pingInterval);
|
||||
if (this._reconnectTimer) clearTimeout(this._reconnectTimer);
|
||||
if (this._ws) {
|
||||
this._ws.onclose = null;
|
||||
this._ws.close();
|
||||
this._ws = null;
|
||||
}
|
||||
this._connected = false;
|
||||
},
|
||||
|
||||
_scheduleReconnect() {
|
||||
if (this._reconnectTimer) return;
|
||||
this._reconnectTimer = setTimeout(() => {
|
||||
this._reconnectTimer = null;
|
||||
this.connect();
|
||||
}, 5000);
|
||||
},
|
||||
|
||||
on(event, callback) {
|
||||
if (!this._listeners[event]) this._listeners[event] = [];
|
||||
this._listeners[event].push(callback);
|
||||
return () => {
|
||||
this._listeners[event] = this._listeners[event].filter(cb => cb !== callback);
|
||||
};
|
||||
},
|
||||
|
||||
_emit(event, data) {
|
||||
(this._listeners[event] || []).forEach(cb => cb(data));
|
||||
// Also emit all for catch-all listeners
|
||||
(this._listeners['*'] || []).forEach(cb => cb(event, data));
|
||||
},
|
||||
|
||||
isConnected() {
|
||||
return this._connected;
|
||||
}
|
||||
};
|
||||
|
||||
// Auto-connect on page load
|
||||
document.addEventListener('DOMContentLoaded', () => WS.connect());
|
||||
Reference in New Issue
Block a user