const WebSocket = require('ws'); const url = require('url'); const uuid = require('node-uuid'); const jsDir = `${__dirname}/server`; const Game = require(`${jsDir}/game.js`); const wss = new WebSocket.Server({ port: 8080 }); const DEBUG = true; const G = new Game(); // Global, for now. Is there a need for an instance? Ben 052220 const Server = { games: {}, messageOne: (ws, message) => { DEBUG && console.log(`Sending to only ${ws.id}:`); DEBUG && console.log(message); ws.send(JSON.stringify(message)); }, messageOthers: (ws, message) => { DEBUG && console.log(`Sending to other client(s):`); DEBUG && console.log(message); wss.clients.forEach((client) => { if (client !== ws && client.readyState === WebSocket.OPEN) { client.send(JSON.stringify(message)); } }); }, messageAll: (message) => { DEBUG && console.log(`Sending to all ${wss.clients.size} client(s):`); DEBUG && console.log(message); wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(JSON.stringify(message)); } }); }, onDisconnect: (ws) => { DEBUG && console.log("Disconnected:"); DEBUG && console.log(ws.id); G.removePlayer(ws.id); Server.messageOthers(ws, { type: 'players', body: G.getPlayers() }); }, onConnect: (ws, req) => { ws.id = uuid.v4(); ws.on('message', Server.onMessage.bind(null, ws)); ws.on('close', Server.onDisconnect.bind(null, ws)); const query = url.parse(req.url, true).query; const santizedName = (query.name || 'Unknown').replace(/[^\w ]/g, ''); DEBUG && console.log("Connected:"); DEBUG && console.log (`${santizedName} ${ws.id} via ${req.url}`); G.addPlayer(ws.id, santizedName); Server.messageAll({ type: 'players', body: G.getPlayers() }); Server.messageOne(ws, { type: 'walls', body: G.getWalls()}); Server.messageOne(ws, { type: 'robots', body: G.getRobots()}); Server.messageOne(ws, { type: 'winstate', body: G.getWinState()}); Server.messageOne(ws, { type: 'connected', body: ws.id}); }, onMessage: (ws, json) => { const message = JSON.parse(json); DEBUG && console.log('Received message: '); DEBUG && console.log(message); if (!message.type) { DEBUG && console.warn("Unprocessable message: ") DEBUG && console.warn(message); return; } switch (message.type) { case 'guess': const santizedGuess = message.rawBody.moves * 1; santizedGuess && Server.messageAll({ type: 'guess', guess: santizedGuess, id: ws.id }); G.onGuess(santizedGuess).then(Server.messageAll.bind(null, { type: 'solve', id: ws.id })); break; // case 'move': // const sanitizedRobotId = message.rawBody.id.replace(/[^0-9a-zA-Z]/g, ''); // const sanitizedI = message.rawBody.i * 1; // const sanitizedJ = message.rawBody.j * 1; // const body = { // i: sanitizedI, // j: sanitizedJ, // id: sanitizedRobotId // }; // Server.messageOthers(ws, { type: 'move', body }); // break; case 'robots': Server.messageAll({ type: 'robots', body: G.getRobots()}); break; case 'skip': Server.messageAll({ type: 'start' }); break; case 'start': Server.messageAll({ type: 'start' }); break; case 'stop': Server.messageAll({ type: 'stop' }); break; case 'walls': Server.messageAll({ type: 'walls', body: G.getWalls()}); break; default: console.warn("Unknown message type: ", message.head.type) } }, }; wss.on('connection', Server.onConnect); console.log("Websocket server listening on :8080");