From f7de130321fccb42bc77bdc2616c393308a1bdfc Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Fri, 28 Jan 2022 13:24:55 -0800 Subject: [PATCH] Chat and login are working much better Signed-off-by: James Ketrenos --- README.md | 1 + client/src/Board.js | 55 ++++++++++++---------- server/routes/games.js | 102 +++++++++++++++++++++++++++++++---------- 3 files changed, 110 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 0dc241a..77c6b35 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,7 @@ Chat is available at all times by registered players ## Lobby + * Register session+name * Register session with color * Unregister player+name from color diff --git a/client/src/Board.js b/client/src/Board.js index 7fb23de..9e5a0c2 100755 --- a/client/src/Board.js +++ b/client/src/Board.js @@ -209,7 +209,7 @@ const Chat = ({ board, promoteGameState }) => { console.log(`Send: ${event.target.value}`); promoteGameState({ chat: { - player: board.game.activePlayer, + player: board.game.activePlayer ? board.game.activePlayer : undefined, message: event.target.value } }); @@ -226,6 +226,8 @@ const Chat = ({ board, promoteGameState }) => { //const timeDelta = game.timestamp - Date.now(); const messages = board.game.chat.map((item, index) => { + /* If the date is in the future, set it to now */ + item.date = item.date > Date.now() ? Date.now() : item.date; return ( @@ -236,14 +238,13 @@ const Chat = ({ board, promoteGameState }) => { ); }); - console.log(board.game); return ( { messages } )} variant="outlined"/> @@ -267,15 +268,15 @@ const Action = ({ board }) => { } return ( - <> - { board.game.state == 'lobby' && - - - + { board.game.state == 'lobby' && <> + + + } + { board.game.state !== 'lobby' && <> + + } - } - ); } @@ -328,16 +329,21 @@ const Players = ({ board }) => { const players = []; for (let key in board.game.players) { const item = board.game.players[key]; - if (board.game.state != "lobby" && item.status == 'Not active') { + if (board.game.state !== "lobby" && item.status === 'Not active') { continue; } + item.lastActive = item.lastActive > Date.now() ? Date.now() : item.lastActive; players.push(( {key} - - { (!selected || selected === key) && + + { item.status + ' ' } + { item.status != 'Not active' && } + )} /> + { (item.status === 'Not active' || selected === key) && toggleSelected(key)}/> @@ -411,12 +417,19 @@ class Board extends React.Component { } imageLoaded(event) { - console.log(`Done loading ${event.target.src}`); + const image = event.target; + console.log(`Done loading ${image.src}`); + image.removeEventListener("load", this.imageLoaded); + image.removeEventListener("error", this.imageLoadError); window.requestAnimationFrame(this.drawFrame); } imageLoadError(event) { - this.setState({message: `Error loading ${event.target.src}`}); + const image = event.target; + console.log(`Error loading ${image.src}`); + image.removeEventListener("load", this.imageLoaded); + image.removeEventListener("error", this.imageLoadError); + this.setState({message: `Error loading ${image.src}`}); } setSelected(key) { @@ -1286,12 +1299,6 @@ class Board extends React.Component { this.updateSizeTimer = 0; } - for (let image in images) { - images[image].removeEventListener("load", this.imageLoaded); - images[image].removeEventListener("error", this.imageLoadError); - delete images[image]; - } - document.removeEventListener("keyup", this.keyUp); window.removeEventListener("mousemove", this.mouseMove); window.removeEventListener("touchmove", this.mouseMove); @@ -1306,10 +1313,12 @@ class Board extends React.Component {
this.cards = el}> { game &&
- + {game.activePlayer === "" && } - + { game.activePlayer !== "" && + + } { this.state.message != "" &&
{this.state.message}
}
} diff --git a/server/routes/games.js b/server/routes/games.js index b920b50..64d1b37 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -136,22 +136,34 @@ router.put("/:id/:action/:value?", (req, res) => { return res.status(404).send(error); } - const game = games[req.params.id]; + const game = games[req.params.id], + color = req.session && req.session.playerColor in game.players ? req.session.playerColor : undefined; + let player; let error; - + if (req.params.action == "player-name") { - if (!req.params.value) { + const name = req.params.value; + if (!name) { error = `No name provided`; } else { - req.session.playerName = req.params.value; - const color = req.session.playerColor; - if (color && game && color in game.players) { - game.players[color].name = req.session.playerName; - game.chat.push({ date: Date.now(), message: `${color} is no known as ${req.session.playerName}.` }); + if (color) { + error = `You cannot change your name while you are in game.`; + } else { + if (game) for (let key in game.players) { + if (game.players[key].name === name) { + error = `${name} is already taken by ${key}`; + } + } } } + if (!error) { + const old = req.session.playerName ? req.session.PlayerName : "Unnamed"; + req.session.playerName = name; + game.chat.push({ date: Date.now(), message: `${old} is no known as ${name}.` }); + } + return sendGame(res, req, game, error); } @@ -161,16 +173,16 @@ router.put("/:id/:action/:value?", (req, res) => { return sendGame(res, req, game, error); } - const selected = req.params.value; - let player; + const selected = req.params.value, + name = req.session.playerName; console.log(`player-selected: ${selected}`); - /* Deselect currentlyi active player for this session */ + /* Deselect currently active player for this session */ for (let key in game.players) { - if (key == req.session.playerColor && selected != key) { + if (key === color && selected !== key) { player = game.players[key]; - if (player.session == req.session.id) { + if (player.session === req.session.id) { player.session = ''; player.name = ''; player.status = 'Not active'; @@ -180,16 +192,46 @@ router.put("/:id/:action/:value?", (req, res) => { } } } + + /* Verify the player has a name set */ + if (!req.session.playerName) { + error = `You may only select a player when you have set your name.`; + } - if (selected in game.players) { + /* Verify this player's name is not already active in the game */ + if (!error) { + for (let key in game.players) { + player = game.players[key]; + if (key === color && selected !== key && player.name == name) { + error = `This name is already taken by ${key}`; + break; + } + } + } + + /* Verify selection is valid */ + if (!error && !(selected in game.players)) { + error = `An invalid player selection was attempted.`; + } + + /* Verify selection is not already taken */ + if (!error) { player = game.players[selected]; + if (player.session) { + error = `${player.name} already has ${selected}`; + } + } + + /* All good -- set this player to requested selection */ + if (!error) { player.session = req.session.id; player.name = req.session.playerName; - player.status = `Just joined`; + player.status = `Active`; + player.lastActive = Date.now(); req.session.playerColor = selected; game.chat.push({ date: Date.now(), message: `${selected} is now '${player.name}'.` }); - } - + } + return sendGame(res, req, game, error); } @@ -206,14 +248,19 @@ router.put("/:id/:action/:value?", (req, res) => { error = roll(game, player); break; case "shuffle": - if (game.state === "lobby") { + if (game.state !== "lobby") { + error = `Game no longer in lobby (${game.state}). Can not shuffle board.`; + } + if (!error && game.turns > 0) { + error = `Game already in progress (${game.turns} so far!) and cannot be shuffled.`; + } + if (!error) { shuffleBoard(game); const message = `${name} requested a new board.`; game.chat.push({ date: Date.now(), message: message }); console.log(message); - } else { - error = `Game no longer in lobby (${game.state}). Can not shuffle board.`; } + break case "state": const state = req.params.value ? req.params.value : "active"; if (state != game.state) { @@ -221,6 +268,7 @@ router.put("/:id/:action/:value?", (req, res) => { const message = `${name} set game state to ${state}.`; game.chat.push({ date: Date.now(), message: message }); } + break; } return sendGame(res, req, game, error); @@ -304,19 +352,22 @@ const sendGame = async (res, req, game, error) => { console.log(message); game.state = 'lobby'; } + const playerColor = (req.session && req.session.playerColor) ? req.session.playerColor : "", + playerName = (req.session && req.session.playerName) ? req.session.playerName : ""; + if (playerColor in game.players) { + game.players[playerColor].lastActive = Date.now(); + } + await writeFile(`games/${game.id}`, JSON.stringify(game, null, 2)) .catch((error) => { console.error(`Unable to write to games/${games.id}`); console.error(error); }); - const playerGame = Object.assign({}, game, { timestamp: Date.now(), status: error ? error : "success", - activePlayerName: (req.session && req.session.playerName) ? - req.session.playerName : "", - activePlayer: (req.session && req.session.playerColor) ? - req.session.playerColor : null + activePlayerName: playerName, + activePlayer: playerColor }); if (game.id == 'b3c4bd15efe212a2') { // console.log(req.session); @@ -335,6 +386,7 @@ router.post("/:id?", (req, res/*, next*/) => { const game = { startTime: Date.now(), + turns: 0, state: "lobby", /* lobby, in-game, finished */ tiles: [], pips: [],