// net.js — WebSocket-Client: Verbindung, Reconnect, Protokoll (siehe Spec 9.2). // Kennt die 3D-Welt nicht — reicht Ereignisse per Callbacks nach oben. export class Net { /** * @param {object} handlers - onWelcome(id,users), onJoin(user), onLeave(id), * onUpdate(id,p,rot), onStatus(id,label), onHelp(id,on), onNet(text,color) */ constructor(handlers) { this.h = handlers; this.ws = null; this.myId = null; this.started = false; this.name = 'Gast'; this.role = 'student'; this.startPos = [0, 0, 8]; } connect(name, role, startPos) { this.name = name; this.role = role; if (startPos) this.startPos = [startPos.x, startPos.y, startPos.z]; this.started = true; this._open(); } _open() { const url = (location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '/ws'; this._net('verbinde …'); const ws = new WebSocket(url); this.ws = ws; ws.onopen = () => { this._net('verbunden', '#a6e3a1'); ws.send(JSON.stringify({ t: 'hello', name: this.name, role: this.role, p: this.startPos })); }; ws.onclose = () => { this._net('getrennt — reconnect …', '#f38ba8'); this.myId = null; setTimeout(() => { if (this.started) this._open(); }, 1500); }; ws.onerror = () => this._net('Fehler', '#f38ba8'); ws.onmessage = (ev) => this._recv(ev); } _recv(ev) { let m; try { m = JSON.parse(ev.data); } catch { return; } const h = this.h; switch (m.t) { case 'welcome': this.myId = m.id; h.onWelcome(m.id, m.users); break; case 'join': h.onJoin(m.user); break; case 'leave': h.onLeave(m.id); break; case 'update': h.onUpdate(m.id, m.p, m.rot); break; case 'status': h.onStatus(m.id, m.label); break; case 'help': h.onHelp(m.id, m.on); break; } } get connected() { return this.ws && this.ws.readyState === 1 && this.myId != null; } sendMove(p, rot, anim) { if (this.connected) this.ws.send(JSON.stringify({ t: 'move', p, rot, anim })); } sendHelp(on) { if (this.connected) this.ws.send(JSON.stringify({ t: 'help', on })); } sendStatus(label) { if (this.connected) this.ws.send(JSON.stringify({ t: 'status', label })); } _net(text, color) { if (this.h.onNet) this.h.onNet(text, color); } }