server for my chess game
use guard clauses
| -rw-r--r-- | src/game.js | 28 | ||||
| -rw-r--r-- | src/index.js | 144 | ||||
| -rw-r--r-- | src/utils.js | 15 |
3 files changed, 98 insertions, 89 deletions
diff --git a/src/game.js b/src/game.js index 7189c66..47d61bd 100644 --- a/src/game.js +++ b/src/game.js @@ -60,13 +60,14 @@ export class Game { clean_clients(set_is_alive = true) { function remove_client(c, wss, removal_func) { - if (c) { - if (c.is_alive === false) { - removal_func(c); - c.terminate(); - wss.clients.delete(c); - } else if (set_is_alive) c.is_alive = false; // becomes true on next ping + if (!c) return; + if (c.is_alive === true && set_is_alive) { + c.is_alive = false; + return; } + removal_func(c); + c.terminate(); + wss.clients.delete(c); } this.spectators.forEach((spec) => { @@ -94,15 +95,12 @@ export class Game { send_signal_packet(data, ws, header) { let us = this.color_of(ws); - if (us !== undefined) { - let sendto = this.get_ws(flip_color(us)); - if (sendto) { - sendto.send_packet(data, header); - send_group_packet(data, header, this.spectators); // give it to the specs - return true; - } - } else console.warn(`could not find client in game '${this.gamecode}'`); - return false; + if (us === undefined) return false; + let sendto = this.get_ws(flip_color(us)); + if (!sendto) return false; + sendto.send_packet(data, header); + send_group_packet(data, header, this.spectators); // give it to the specs + return true; } reset_game() { diff --git a/src/index.js b/src/index.js index 676eb11..c64cf8d 100644 --- a/src/index.js +++ b/src/index.js @@ -8,7 +8,7 @@ const { putVar, getVar } = utils; import { command } from "./pg.js"; import { self_ping } from "./ping.js"; import { Game } from "./game.js"; -import { flip_color } from "./utils.js"; +import { flip_color, fail } from "./utils.js"; const HEADERS = { relay: "R", @@ -179,102 +179,98 @@ function handle_joinrequest(data, ws) { game.get_ws(us).send_packet(game.get_info(them), HEADERS.info); } + if (fail(!data.id, ws, "NO_ID", HEADERS.joinrequest)) return; + if (fail(!data.gamecode, ws, "NO_GAMECODE", HEADERS.joinrequest)) return; const game = games[data.gamecode]; - if (data.id) { - if (data.gamecode !== undefined) { - if (game !== undefined) { - if (game.players < 2) { - // hoster is waiting for someone to join - - const joiner_idx = game.add_client(ws, data); - ws.send_packet({ idx: joiner_idx }, HEADERS.joinrequest); // tell them what team they are - game.send_group_packet(game.pgn, HEADERS.loadpgn); // hoster doesnt send a joinrequest, so tell it to load pgn too - send_info(); - console.log(`'${data.name}' joined '${data.gamecode}'`); - } else { - let color = game.color_of(data.name, data.country, data.id); - if (color != undefined) { - // someone is trying to rejoin - console.log(`'${data.name}' rejoined '${data.gamecode}' as ${color}`); - ws.send_packet({ idx: color == "w" ? 0 : 1 }, HEADERS.joinrequest); - game.add_client(ws, data, color == "w"); - ws.send_packet(game.pgn, HEADERS.loadpgn); // pass them the pgn - send_info(true); // and send them their opponents info - } else { - const message = `rejected join to '${data.gamecode}' (by '${data.name}'): game full / id(${data.id}) not included in ${game.ids}`; - console.warn(message); - ws.send_packet({ err: "FULL" }, HEADERS.joinrequest); - } - } - } else ws.send_packet({ err: "NOT_EXIST" }, HEADERS.joinrequest); - } else ws.send_packet({ err: "NO_GAMECODE" }, HEADERS.joinrequest); - } else ws.send_packet({ err: "NO_ID" }, HEADERS.joinrequest); + if (fail(game === undefined, ws, "NOT_EXIST", HEADERS.joinrequest)) return; + + if (game.players < 2) { + // hoster is waiting for someone to join + const joiner_idx = game.add_client(ws, data); + ws.send_packet({ idx: joiner_idx }, HEADERS.joinrequest); // tell them what team they are + game.send_group_packet(game.pgn, HEADERS.loadpgn); // hoster doesnt send a joinrequest, so tell it to load pgn too + send_info(); + console.log(`'${data.name}' joined '${data.gamecode}'`); + } else { + let color = game.color_of(data.name, data.country, data.id); + + if (fail(color === undefined, ws, "FULL", HEADERS.joinrequest)) { + console.warn( + `rejected join to '${data.gamecode}' (by '${data.name}'): game full / id(${data.id}) not included in ${game.ids}` + ); + return; + } + // someone is trying to rejoin + console.log(`'${data.name}' rejoined '${data.gamecode}' as ${color}`); + ws.send_packet({ idx: color == "w" ? 0 : 1 }, HEADERS.joinrequest); + game.add_client(ws, data, color == "w"); + ws.send_packet(game.pgn, HEADERS.loadpgn); // pass them the pgn + send_info(true); // and send them their opponents info + } } function handle_hostrequest(data, ws) { - if (data.id !== undefined) { - if (data.gamecode !== undefined) { - delete_game_if_empty(games[data.gamecode]); // see if its dead - if (games[data.gamecode] === undefined) { - if (data.team == undefined) data.team = true; - games[data.gamecode] = new Game(data, ws, wss); - ws.send_packet({ idx: Number(!data.team) }, HEADERS.hostrequest); - console.log(`'${data.name}' hosted '${data.gamecode}'`); - } else if (games[data.gamecode].players < 2) - ws.send_packet({ err: "ALREADY_EXISTS_EMPTY" }, HEADERS.hostrequest); - else ws.send_packet({ err: "ALREADY_EXISTS" }, HEADERS.hostrequest); - } else ws.send_packet({ err: "NO_GAMECODE" }, HEADERS.hostrequest); - } else ws.send_packet({ err: "NO_ID" }, HEADERS.hostrequest); + if (fail(data.id === undefined, ws, "NO_ID", HEADERS.hostrequest)) return; // fail conds + if (fail(data.gamecode === undefined, ws, "NO_GAMECODE", HEADERS.hostrequest)) return; + + const g = games[data.gamecode]; + delete_game_if_empty(g); // see if its dead + + if (fail(!!g, ws, g && g.players < 2 ? "ALREADY_EXISTS_EMPTY" : "ALREADY_EXISTS", HEADERS.hostrequest)) return; + + if (data.team == undefined) data.team = true; + games[data.gamecode] = new Game(data, ws, wss); + ws.send_packet({ idx: Number(!data.team) }, HEADERS.hostrequest); + console.log(`'${data.name}' hosted '${data.gamecode}'`); } function handle_move(data, ws) { const gc = ws.gamecode; - if (games.hasOwnProperty(gc) && games[gc].validate_move(data.move) && signal_other(data, ws, HEADERS.move)) { - games[gc].move(data.move); - const player = games[gc].get_info(games[gc].game.turn).name; - console.log(`'${player}' made move '${data.move}' on '${gc}'`); - } + if (!(games.hasOwnProperty(gc) && games[gc].validate_move(data.move) && signal_other(data, ws, HEADERS.move))) + return; + games[gc].move(data.move); + const player = games[gc].get_info(games[gc].game.turn).name; + console.log(`'${player}' made move '${data.move}' on '${gc}'`); } function handle_undo(data, ws) { - if (signal_other(data, ws, HEADERS.undo) && data.accepted === true) { - games[ws.gamecode].undo(); - if (data.two === true) games[ws.gamecode].undo(); // do it again - } + if (!signal_other(data, ws, HEADERS.undo) && data.accepted !== true) return; + + games[ws.gamecode].undo(); + if (data.two === true) games[ws.gamecode].undo(); // do it again } function handle_rematch(data, ws) { - if (signal_other(data, ws, HEADERS.rematch)) { - // check if its a request, and if the request is accepted - if (data.accepted === true) games[ws.gamecode].reset_game(); // reset if it is - } + if (!signal_other(data, ws, HEADERS.rematch)) return; + + // check if its a request, and if the request is accepted + if (data.accepted === true) games[ws.gamecode].reset_game(); // reset if it is } function handle_spectate(data, ws) { - if (games.hasOwnProperty(data.gamecode)) { - const game = games[data.gamecode]; - game.add_spectator(ws); - const packet = { - white: game.infos.get(0), - black: game.infos.get(1), - pgn: game.pgn, - }; // spectator starter kit - // provides white info, black info, and pgn - ws.send_packet(packet, HEADERS.spectate); - } else ws.send_packet({ err: "NOT_EXIST" }, HEADERS.spectate); + if (fail(!games.hasOwnProperty(data.gamecode), ws, "NOT_EXIST", HEADERS.spectate)) return; + + const game = games[data.gamecode]; + game.add_spectator(ws); + const packet = { + white: game.infos.get(0), + black: game.infos.get(1), + pgn: game.pgn, + }; // spectator starter kit + // provides white info, black info, and pgn + ws.send_packet(packet, HEADERS.spectate); } // relays to both clients function dual_relay(data, ws, header = HEADERS.relay) { - if (games.hasOwnProperty(ws.gamecode)) { - games[ws.gamecode].send_group_packet(data, header); - return true; - } else console.warn(`game '${ws.gamecode}' does not exist`); - return false; + if (!games.hasOwnProperty(ws.gamecode)) return false; + + games[ws.gamecode].send_group_packet(data, header); + return true; } // relays to the other client function signal_other(data, ws, header = HEADERS.signal) { - if (games.hasOwnProperty(ws.gamecode)) return games[ws.gamecode].send_signal_packet(data, ws, header); - return false; + if (!games.hasOwnProperty(ws.gamecode)) return false; + return games[ws.gamecode].send_signal_packet(data, ws, header); } diff --git a/src/utils.js b/src/utils.js index f5a6688..6924fe7 100644 --- a/src/utils.js +++ b/src/utils.js @@ -16,3 +16,18 @@ export function pick(o, ...props) { if (o === undefined) return undefined; return Object.assign({}, ...props.map((prop) => ({ [prop]: o[prop] }))); } + +/** + * Sends a error message on condition + * + * @param {Boolean} when When to fail + * @param {WebSocket} ws The websocket to send the error message to + * @param {String} err The error message + * @param {String} header The header used + * @return {Boolean} `when` + * @exports + */ +export function fail(when, ws, err, header) { + if (when) ws.send_packet({ err: err }, header); + return when; +} |