60 lines
1.7 KiB
JavaScript
60 lines
1.7 KiB
JavaScript
import { ClientMessage, ServerMessage } from './protocol.js';
|
||
|
||
export class Network {
|
||
constructor() {
|
||
const proto = location.protocol === 'https:' ? 'wss' : 'ws';
|
||
this.socket = new WebSocket(`${proto}://${location.host}/ws`);
|
||
this.handlers = new Map();
|
||
|
||
this.socket.addEventListener('open', () => this._emit('_open'));
|
||
this.socket.addEventListener('close', () => this._emit('_close'));
|
||
this.socket.addEventListener('message', (event) => {
|
||
const msg = JSON.parse(event.data);
|
||
this._emit(msg.type, msg.payload);
|
||
});
|
||
|
||
// NAT-таблицы на промежуточных роутерах гаснут раньше, чем серверный
|
||
// idleTimeout (300с) — application-ping раз в 25с держит соединение живым
|
||
// и на случай обрыва держим интервал заметно меньше таймаута.
|
||
setInterval(() => {
|
||
if (this.socket.readyState === WebSocket.OPEN) {
|
||
this.send(ClientMessage.PING);
|
||
}
|
||
}, 25000);
|
||
}
|
||
|
||
on(type, handler) {
|
||
this.handlers.set(type, handler);
|
||
}
|
||
|
||
_emit(type, payload) {
|
||
this.handlers.get(type)?.(payload);
|
||
}
|
||
|
||
send(type, payload = {}) {
|
||
this.socket.send(JSON.stringify({ type, payload }));
|
||
}
|
||
|
||
hello(nickname) {
|
||
this.send(ClientMessage.HELLO, { nickname });
|
||
}
|
||
|
||
listRooms() {
|
||
this.send(ClientMessage.LOBBY_LIST_ROOMS);
|
||
}
|
||
|
||
createRoom(mode) {
|
||
this.send(ClientMessage.LOBBY_CREATE_ROOM, { mode });
|
||
}
|
||
|
||
joinRoom(roomId) {
|
||
this.send(ClientMessage.LOBBY_JOIN_ROOM, { room_id: roomId });
|
||
}
|
||
|
||
leaveRoom() {
|
||
this.send(ClientMessage.LOBBY_LEAVE_ROOM);
|
||
}
|
||
}
|
||
|
||
export { ServerMessage };
|