X-Git-Url: https://git.auder.net/?p=xogo.git;a=blobdiff_plain;f=server.js;h=72d285c12e489e04554056a197b7ed3319f80705;hp=37a343ec87f06b922bc615feadeeeeb67c3d5077;hb=b4ae3ff62916d54d56778f63ef0231bfb5761142;hpb=3c61449b830db29c95d82cdacc4dae710cc705a8 diff --git a/server.js b/server.js index 37a343e..72d285c 100644 --- a/server.js +++ b/server.js @@ -1,7 +1,9 @@ const params = require("./parameters.js"); const WebSocket = require("ws"); -const wss = new WebSocket.Server( - {port: params.socket_port, path: params.socket_path}); +const wss = new WebSocket.Server({ + port: params.socket_port, + path: params.socket_path +}); let challenges = {}; //variantName --> socketId, name let games = {}; //gameId --> gameInfo (vname, fen, players, options, time) @@ -14,10 +16,11 @@ function send(sid, code, data) { const socket = sockets[sid]; // If a player deletes local infos and then tries to resume a game, // sockets[oppSid] will probably not exist anymore: - if (socket) socket.send(JSON.stringify(Object.assign({ code: code }, data))); + if (socket) + socket.send(JSON.stringify(Object.assign({ code: code }, data))); } -function launchGame(vname, players, options) { +function initializeGame(vname, players, options) { const gid = Crypto.randomBytes(randstrSize).toString("hex").slice(0, randstrSize); games[gid] = { @@ -26,28 +29,20 @@ function launchGame(vname, players, options) { options: options, time: Date.now() }; - if (players.every(p => p)) { - const gameInfo = Object.assign( - // Provide seed so that both players initialize with same FEN - {seed: Math.floor(Math.random() * 1984), gid: gid}, - games[gid]); - for (const p of players) { - send(p.sid, - "gamestart", - Object.assign({randvar: p.randvar}, gameInfo)); - } - } - else { - // Incomplete players array: do not start game yet - send(sid, "gamecreated", {gid: gid}); - // If nobody joins within 5 minutes, delete game - setTimeout( - () => { - if (games[gid] && games[gid].players.some(p => !p)) - delete games[gid]; - }, - 5 * 60000 - ); + return gid; +} + +// Provide seed in case of, so that both players initialize with same FEN +function launchGame(gid) { + const gameInfo = Object.assign( + {seed: Math.floor(Math.random() * 1984), gid: gid}, + games[gid] + ); + // players array is supposed to be full: + for (const p of games[gid].players) { + send(p.sid, + "gamestart", + Object.assign({randvar: p.randvar}, gameInfo)); } } @@ -87,14 +82,17 @@ wss.on("connection", (socket, req) => { } if (opponent) { delete challenges[choice]; - if (choice == "_random") choice = getRandomVariant(); + if (choice == "_random") + choice = getRandomVariant(); // Launch game let players = [ {sid: sid, name: obj.name, randvar: randvar}, opponent ]; - if (Math.random() < 0.5) players = players.reverse(); - launchGame(choice, players, {}); //empty options => default + if (Math.random() < 0.5) + players = players.reverse(); + // Empty options = default + launchGame( initializeGame(choice, players, {}) ); } else // Place challenge and wait. 'randvar' indicate if we play anything @@ -106,32 +104,37 @@ wss.on("connection", (socket, req) => { games[obj.gid].fen = obj.fen; break; // Send back game informations - case "getgame": { - if (!games[obj.gid]) send(sid, "nogame"); - else send(sid, "gameinfo", games[obj.gid]); + case "getgame": + if (!games[obj.gid]) + send(sid, "nogame"); + else + send(sid, "gameinfo", games[obj.gid]); break; - } // Cancel challenge case "cancelseek": delete challenges[obj.vname]; break; // Receive rematch case "rematch": - if (!games[obj.gid]) send(sid, "closerematch"); + if (!games[obj.gid]) + send(sid, "closerematch"); else { const myIndex = (games[obj.gid].players[0].sid == sid ? 0 : 1); - if (!games[obj.gid].rematch) games[obj.gid].rematch = [0, 0]; + if (!games[obj.gid].rematch) + games[obj.gid].rematch = [0, 0]; games[obj.gid].rematch[myIndex] = !obj.random ? 1 : 2; if (games[obj.gid].rematch[1-myIndex]) { // Launch new game, colors reversed let vname = games[obj.gid].vname; const allrand = games[obj.gid].rematch.every(r => r == 2); - if (allrand) vname = getRandomVariant(); + if (allrand) + vname = getRandomVariant(); games[obj.gid].players.forEach(p => p.randvar = allrand ? true : false); - launchGame(vname, - games[obj.gid].players.reverse(), - games[obj.gid].options); + const gid = initializeGame(vname, + games[obj.gid].players.reverse(), + games[obj.gid].options); + launchGame(gid); } } break; @@ -154,23 +157,32 @@ wss.on("connection", (socket, req) => { ) { players = players.reverse(); } - launchGame(obj.vname, players, obj.options); + // Incomplete players array: do not start game yet + const gid = initializeGame(obj.vname, players, obj.options); + send(sid, "gamecreated", {gid: gid}); + // If nobody joins within 3 minutes, delete game + setTimeout( + () => { + if (games[gid] && games[gid].players.some(p => !p)) + delete games[gid]; + }, + 3 * 60000 + ); break; } // Join game vs. friend case "joingame": - if (!games[obj.gid]) send(sid, "jointoolate"); + if (!games[obj.gid]) + send(sid, "jointoolate"); else { - // Join a game (started by some other player) const emptySlot = games[obj.gid].players.findIndex(p => !p); - if (emptySlot < 0) send(sid, "jointoolate"); - games[obj.gid].players[emptySlot] = {sid: sid, name: obj.name}; - const gameInfo = Object.assign( - // Provide seed so that both players initialize with same FEN - {seed: Math.floor(Math.random()*1984), gid: obj.gid}, - games[obj.gid]); - for (const p of games[obj.gid].players) - send(p.sid, "gamestart", gameInfo); + if (emptySlot < 0) + send(sid, "jointoolate"); + else { + // Join a game (started by some other player) + games[obj.gid].players[emptySlot] = {sid: sid, name: obj.name}; + launchGame(obj.gid); + } } break; // Relay a move + update games object @@ -202,7 +214,7 @@ wss.on("connection", (socket, req) => { } } for (let g of Object.values(games)) { - const myIndex = g.players.findIndex(p => p.sid == sid); + const myIndex = g.players.findIndex(p => p && p.sid == sid); if (myIndex >= 0) { if (g.rematch && g.rematch[myIndex] > 0) g.rematch[myIndex] = 0; break; //only one game per player @@ -213,7 +225,8 @@ wss.on("connection", (socket, req) => { const heartbeat = setInterval(() => { wss.clients.forEach((ws) => { - if (ws.isAlive === false) return ws.terminate(); + if (ws.isAlive === false) + return ws.terminate(); ws.isAlive = false; ws.ping(); }); @@ -224,7 +237,8 @@ const dayInMillisecs = 24 * 60 * 60 * 1000; const killOldGames = setInterval(() => { const now = Date.now(); Object.keys(games).forEach(gid => { - if (now - games[gid].time >= dayInMillisecs) delete games[gid]; + if (now - games[gid].time >= dayInMillisecs) + delete games[gid]; }); }, dayInMillisecs);