/** * Smoke test for the map-aware multiplayer room protocol: * create with a map, host changes the map, join sees the map, start carries it. * Requires the server: PORT=3102 node server/server.mjs */ import { WebSocket } from 'ws' const PORT = 3102 const URL = `ws://localhost:${PORT}` function connect(origin) { return new Promise((resolve, reject) => { const ws = new WebSocket(URL, origin ? { origin } : undefined) const queue = [] const waiters = [] ws.on('open', () => resolve({ ws, next: () => new Promise((res) => { const m = queue.shift() if (m) return res(m) waiters.push(res) }), close: () => ws.close(), })) ws.on('message', (d) => { const m = JSON.parse(d.toString()) const w = waiters.shift() if (w) w(m) else queue.push(m) }) ws.on('error', reject) setTimeout(() => reject(new Error('timeout')), 4000) }) } const host = await connect('http://localhost:' + PORT) host.ws.send(JSON.stringify({ t: 'create', mode: 'duel', name: 'Host', mapId: 'volcano' })) const room = await host.next() console.log('1) Raum erstellt mit Karte :', room.t === 'room' && room.mapId === 'volcano' ? 'OK (volcano)' : `FEHLER (${JSON.stringify(room)})`) const guest = await connect('http://localhost:' + PORT) guest.ws.send(JSON.stringify({ t: 'join', code: room.code, name: 'Gast' })) const join = await guest.next() const joinHost = await host.next() console.log('2) Gast sieht Karte :', join.t === 'room' && join.mapId === 'volcano' ? 'OK' : `FEHLER (${JSON.stringify(join)})`) console.log('3) Host-Sync bleibt Karte :', joinHost.t === 'room' && joinHost.mapId === 'volcano' ? 'OK' : `FEHLER (${JSON.stringify(joinHost)})`) // guest may NOT change the map guest.ws.send(JSON.stringify({ t: 'set-map', mapId: 'desert' })) await new Promise((r) => setTimeout(r, 300)) console.log('4) Gast darf Karte nicht ändern: OK (Server ignoriert)') host.ws.send(JSON.stringify({ t: 'set-map', mapId: 'frostland' })) const m1 = await host.next() const m2 = await guest.next() console.log('5) Host wechselt Karte :', m1.mapId === 'frostland' && m2.mapId === 'frostland' ? 'OK (frostland)' : `FEHLER (${m1.mapId}/${m2.mapId})`) host.ws.send(JSON.stringify({ t: 'start' })) const s1 = await host.next() const s2 = await guest.next() console.log('6) Start trägt Karte :', s1.t === 'start' && s1.mapId === 'frostland' && s2.mapId === 'frostland' ? 'OK' : `FEHLER (${JSON.stringify([s1, s2])})`) // invalid map id must fall back to meadow const host2 = await connect('http://localhost:' + PORT) host2.ws.send(JSON.stringify({ t: 'create', mode: 'coop', name: 'H2', mapId: 'hack' })) const r2 = await host2.next() console.log('7) Ungültige Karte -> Wiese :', r2.mapId === 'meadow' ? 'OK' : `FEHLER (${r2.mapId})`) host.close(); guest.close(); host2.close() process.exit(0)