enum Message { Farewell, Welcome, Attendee, Guest, Dropout, Pilgrim, } interface Player { socket: WebSocket, x: number, y: number, others: Array, } declare global { interface Array { remove(item: T): void; swapRemove(item: T): void; } } Array.prototype.remove = function (item) { const index = this.indexOf(item); if (index > -1) this.splice(index, 1); } Array.prototype.swapRemove = function (item) { const last = this.pop(); const index = this.indexOf(item); if (last !== undefined && index > -1) this.splice(index, 1, last); } const players = new Array(); let idCounter = 0; Deno.serve({ port: 80 }, (request, info) => { if (request.headers.get("upgrade") != "websocket") return new Response(null, { status: 501 }); const { socket, response } = Deno.upgradeWebSocket(request, { idleTimeout: 0 }); const { hostname, port } = info.remoteAddr; const player = { socket, x: Math.floor(Math.random()*0x10000), y: Math.floor(Math.random()*0x10000), others: players.slice(), }; const bytesRecv = new Uint8Array(new ArrayBuffer(4)); let bytesRecvCount = 0; if (players.length > 64) { socket.addEventListener("open", () => { socket.close(); console.log(`${hostname}:${port} denied, server over capacity`); }); return response; } players.push(player); const id = idCounter++; socket.binaryType = "arraybuffer"; socket.addEventListener("open", () => { console.log(`${hostname}:${port} connected as player ${id}`); const { x, y } = player; socket.send(new Uint8Array([Message.Welcome, x>>8, x&0xff, y>>8, y&0xff])); for (const other of player.others) { socket.send(new Uint8Array([Message.Attendee, other.x>>8, other.x&0xff, other.y>>8, other.y&0xff])); other.socket.send(new Uint8Array([Message.Guest, x>>8, x&0xff, y>>8, y&0xff])); other.others.push(player); } }); socket.addEventListener("message", (event) => { if (typeof(event.data) == "string") return; const bytes = new Uint8Array(event.data); for (const byte of bytes) { bytesRecv[bytesRecvCount++] = byte; if (bytesRecvCount !== bytesRecv.byteLength) continue; bytesRecvCount = 0; const x = bytesRecv[0]<<8 | bytesRecv[1]; const y = bytesRecv[2]<<8 | bytesRecv[3]; player.x = x; player.y = y; for (const other of player.others) other.socket.send(new Uint8Array([Message.Pilgrim, other.others.indexOf(player), x>>8, x&0xff, y>>8, y&0xff])); } }); socket.addEventListener("close", () => { for (const other of player.others) { other.socket.send(new Uint8Array([Message.Dropout, other.others.indexOf(player)])); other.others.swapRemove(player); } players.remove(player); console.log(`Player ${id} disconnected`); }); return response; });