From 347d21e5ae44462e442bda75e723aad1f1d33b8b Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Sat, 12 Mar 2022 12:18:49 -0800 Subject: [PATCH] Fixed color not being set on initialization Signed-off-by: James Ketrenos --- client/src/Activities.js | 61 +++++++++++++++++++++++++++++----------- client/src/App.js | 6 ++-- client/src/Board.js | 56 ++++++++++++++++++++++-------------- client/src/Chat.js | 2 +- server/routes/games.js | 40 +++++++++++++++++--------- 5 files changed, 109 insertions(+), 56 deletions(-) diff --git a/client/src/Activities.js b/client/src/Activities.js index 5e9a7de..7a281d3 100644 --- a/client/src/Activities.js +++ b/client/src/Activities.js @@ -1,4 +1,5 @@ import React, { useState, useContext, useMemo, useEffect, useRef } from "react"; +import equal from "fast-deep-equal"; import "./Activities.css"; import { PlayerColor } from './PlayerColor.js'; import { Dice } from './Dice.js'; @@ -30,19 +31,7 @@ const Activity = ({ activity }) => { message = <>{dice[1]}{dice[5]}; } } else { - message = activity.message; /* - let start = activity.message; - while (start) { - const resource = start.match(/^(.*)(([0-9]+) (wood|sheep|wheat|stone|brick),?)(.*)$/); - if (resource) { - const count = resource[3] ? parseInt(resource[3]) : 1; - message = <>{resource[5]}{message}; - start = resource[1]; - } else { - message = <>{start}{message}; - start = ''; - } - }*/ + message = activity.message; } return <>{ display && @@ -57,6 +46,7 @@ const Activities = () => { const [activities, setActivities] = useState([]); const [turn, setTurn] = useState(); const [color, setColor] = useState(); + const [player, setPlayer] = useState(undefined); const [players, setPlayers] = useState({}); const [timestamp, setTimestamp] = useState(0); const [state, setState] = useState(''); @@ -65,23 +55,55 @@ const Activities = () => { 'activities', 'turn', 'players', 'timestamp', 'color', 'state' ], []); + const requestUpdate = (fields) => { + let request; + if (!Array.isArray(fields)) { + request = [ fields ]; + } else { + request = fields; + } + ws.send(JSON.stringify({ + type: 'get', + fields: request + })); + }; const onWsMessage = (event) => { const data = JSON.parse(event.data); switch (data.type) { case 'game-update': + const ignoring = [], processing = []; + for (let field in data.update) { + if (fields.indexOf(field) === -1) { + ignoring.push(field); + } else { + processing.push(field); + } + } + console.log(`activities - game update`, data.update); + console.log(`activities - ignoring ${ignoring.join(',')}`); + console.log(`activities - processing ${processing.join(',')}`); + if ('state' in data.update && data.update.state !== state) { + requestUpdate('turn'); setState(data.update.state); } if ('activities' in data.update - && data.update.activities.length !== activities.length) { + && !equal(data.update.activities, activities)) { setActivities(data.update.activities); } - if ('turn' in data.update) { + if ('turn' in data.update + && !equal(data.update.turn, turn)) { setTurn(data.update.turn); } - if ('players' in data.update) { + if ('players' in data.update + && !equal(data.update.players, players)) { setPlayers(data.update.players); + if ((color in data.update.players) + && !equal(player, data.update.players[color])) { + setPlayer(data.update.players[color]); + requestUpdate('turn'); + } } if ('timestamp' in data.update && data.update.timestamp !== timestamp) { @@ -89,6 +111,11 @@ const Activities = () => { } if ('color' in data.update && data.update.color !== color) { setColor(data.update.color); + if (players && (data.update.color in players) + && !equal(player, players[data.update.color])) { + setPlayer(player); + requestUpdate('turn'); + } } break; default: @@ -125,7 +152,7 @@ const Activities = () => { placeRoad = placement && turn && turn.actions && turn.actions.indexOf('place-road') !== -1, mustStealResource = turn && turn.actions && turn.actions.indexOf('steal-resource') !== -1, rollForOrder = (state === 'game-order'); - +console.log(`activities - `, state, turn); let discarders = [], mustDiscard = false; for (let key in players) { const player = players[key]; diff --git a/client/src/App.js b/client/src/App.js index a3f3cad..a94ab02 100755 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,4 +1,4 @@ -import React, { useState, useContext, useEffect, useRef } from "react"; +import React, { useState, useCallback, useEffect, useRef } from "react"; import { BrowserRouter as Router, Route, @@ -142,7 +142,7 @@ const Table = () => { } }; - const resetConnection = (function () { + const resetConnection = useCallback((function () { let timer = 0; function reset() { timer = 0; @@ -154,7 +154,7 @@ const Table = () => { } timer = setTimeout(reset, 5000); }; - })(); + })(), [setConnecting]); const onWsError = (event) => { console.error(`ws: error`, event); diff --git a/client/src/Board.js b/client/src/Board.js index f81e8be..375e61a 100644 --- a/client/src/Board.js +++ b/client/src/Board.js @@ -1,4 +1,5 @@ import React, { useEffect, useState, useContext, useRef, useMemo } from "react"; +import equal from "fast-deep-equal"; import { assetsPath, debounce } from "./Common.js"; import "./Board.css"; import { GlobalContext } from "./GlobalContext.js"; @@ -125,12 +126,15 @@ const Board = () => { } if ('turn' in data.update) { - setTurn(data.update.turn); + if (!equal(data.update.turn, turn)) { + console.log(`board - turn`, data.update.turn); + setTurn(data.update.turn); + } } if ('placement' in data.update) { - if (comparePlacements(data.update.placements, placements)) { - console.log(`placements`, data.update.placements); + if (!equal(data.update.placements, placements)) { + console.log(`board - placements`, data.update.placements); setPlacements(data.update.placements); } } @@ -572,7 +576,11 @@ const Board = () => { borderOrder, borders, pipOrder, pips, tileOrder, tiles ]); - if (turn) { + useEffect(() => { + if (!turn) { + return; + } + let nodes = document.querySelectorAll('.Active'); for (let i = 0; i < nodes.length; i++) { nodes[i].classList.remove('Active'); @@ -590,9 +598,13 @@ const Board = () => { nodes[i].classList.add('Active'); } } - } + }, [ turn ]); - if (placements) { + useEffect(() => { + if (!placements) { + return; + } + /* Set color and type based on placement data from the server */ placements.corners.forEach((corner, index) => { const el = document.querySelector(`.Corner[data-index="${index}"]`); @@ -673,23 +685,25 @@ const Board = () => { }); } } - } + }, [ placements, turn]); - let nodes = document.querySelectorAll(`.Pip.Robber`); - for (let i = 0; i < nodes.length; i++) { - nodes[i].classList.remove('Robber'); - [ 'Robert', 'Roberta', 'Velocirobber' ].forEach(robberName => - nodes[i].classList.remove(robberName) - ); - } + useEffect(() => { + let nodes = document.querySelectorAll(`.Pip.Robber`); + for (let i = 0; i < nodes.length; i++) { + nodes[i].classList.remove('Robber'); + [ 'Robert', 'Roberta', 'Velocirobber' ].forEach(robberName => + nodes[i].classList.remove(robberName) + ); + } - if (robber !== undefined) { - const el = document.querySelector(`.Pip[data-index="${robber}"]`); - if (el) { - el.classList.add('Robber'); - el.classList.add(robberName); - } - } + if (robber !== undefined) { + const el = document.querySelector(`.Pip[data-index="${robber}"]`); + if (el) { + el.classList.add('Robber'); + el.classList.add(robberName); + } + } + }, [ robber, robberName ]); const canAction = (action) => { return (turn && Array.isArray(turn.actions) && turn.actions.indexOf(action) !== -1); diff --git a/client/src/Chat.js b/client/src/Chat.js index d9ae417..db18fd9 100644 --- a/client/src/Chat.js +++ b/client/src/Chat.js @@ -28,7 +28,7 @@ const Chat = () => { switch (data.type) { case 'game-update': console.log(`chat - game update`); - if (data.update.chat) { + if (data.update.chat && data.update.chat.length !== chat.length) { console.log(`chat - game update - ${data.update.chat.length} lines`); setChat(data.update.chat); } diff --git a/server/routes/games.js b/server/routes/games.js index ddc2bd8..2661af2 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -19,7 +19,7 @@ const debug = { audio: false, get: true, set: true, - update: false + update: true }; let gameDB; @@ -496,7 +496,7 @@ const loadGame = async (id) => { if (game) { try { game = JSON.parse(game); - console.log(`Creating backup of games/${id}`); + console.log(`${info} Creating backup of games/${id}`); await writeFile(`games/${id}.bk`, JSON.stringify(game)); } catch (error) { console.log(`Attempting to load backup from games/${id}.bk`); @@ -804,7 +804,7 @@ const setPlayerName = (game, session, name) => { console.log(`${info}: ${name} has been reallocated to a new session.`); delete game.sessions[id]; } else { - return `${info}: ${name} is already taken and has been active in the last minute.`; + return `${name} is already taken and has been active in the last minute.`; } } } @@ -864,7 +864,7 @@ const setPlayerName = (game, session, name) => { sendUpdateToPlayer(session, { name: session.name, - color: undefined, + color: session.color, live: session.live, player: session.player }); @@ -2887,8 +2887,16 @@ const all = `[ all ]`; const info = `[ info ]`; const todo = `[ todo ]`; +const sendGameToPlayer = (game, session) => { + console.log(`${session.id}: -> sendGamePlayer:${getName(session)} - full game`); + session.ws.send(JSON.stringify({ + type: 'game-update', + update: getFilteredGameForPlayer(game, session) + })); +}; + const sendGameToPlayers = (game) => { - console.log(`${all}: -> ${game.id} sendGamePlayers - full game`); + console.log(`${all}: -> sendGamePlayers - full game`); for (let key in game.sessions) { const _session = game.sessions[key]; @@ -2904,10 +2912,10 @@ const sendGameToPlayers = (game) => { const sendUpdateToPlayers = async (game, update) => { if (debug.update) { - console.log(`[ all ]: -> ${game.id} sendUpdateToPlayers - `, update); + console.log(`[ all ]: -> sendUpdateToPlayers - `, update); } else { const keys = Object.getOwnPropertyNames(update); - console.log(`[ all ]: -> ${game.id} sendUpdateToPlayers - ${keys.join(',')}`); + console.log(`[ all ]: -> sendUpdateToPlayers - ${keys.join(',')}`); } const message = JSON.stringify({ type: 'game-update', @@ -2926,10 +2934,10 @@ const sendUpdateToPlayers = async (game, update) => { const sendUpdateToPlayer = async (session, update) => { if (debug.update) { - console.log(`${session.id}: -> sendUpdateToPlayer - `, update); + console.log(`${session.id}: -> sendUpdateToPlayer:${getName(session)} - `, update); } else { const keys = Object.getOwnPropertyNames(update); - console.log(`${session.id}: -> sendUpdateToPlayer - ${keys.join(',')}`); + console.log(`${session.id}: -> sendUpdateToPlayer:${getName(session)} - ${keys.join(',')}`); } const message = JSON.stringify({ type: 'game-update', @@ -3114,11 +3122,11 @@ router.ws("/ws/:id", async (ws, req) => { case 'game-update': console.log(`${short}:${id}:${getName(session)} - full game update.`); - sendUpdateToPlayer(session, getFilteredGameForPlayer(game, session)); + sendGameToPlayer(game, session); break; case 'player-name': - console.log(`${short}: <- ${id}:${getName(session)} - setPlayerName - ${data.name}`) + console.log(`${short}: <- player-name:${getName(session)} - setPlayerName - ${data.name}`) error = setPlayerName(game, session, data.name); if (error) { sendError(session, error); @@ -3128,7 +3136,7 @@ router.ws("/ws/:id", async (ws, req) => { break; case 'set': - console.log(`${short}: <- ${id}:${getName(session)} - ${data.type} ${data.field} = ${data.value}`); + console.log(`${short}: <- set:${getName(session)} ${data.field} = ${data.value}`); switch (data.field) { case 'state': warning = setGameState(game, session, data.value); @@ -3154,7 +3162,7 @@ router.ws("/ws/:id", async (ws, req) => { break; case 'get': - console.log(`${short}: <- ${id}:${getName(session)} - ${data.type} ${data.fields.join(',')}`); + console.log(`${short}: <- get:${getName(session)} ${data.fields.join(',')}`); update = {}; data.fields.forEach((field) => { switch (field) { @@ -3174,8 +3182,12 @@ router.ws("/ws/:id", async (ws, req) => { update.players = game.players; break; case 'color': + console.log(`${session.id}: -> Returning color as ${session.color} for ${session.name}`); update.color = session.color; break; + case 'timestamp': + update.timestamp = Date.now(); + break; default: if (field in game) { console.warn(`${short}: WARNING: Requested GET not-privatized/sanitized field: ${field}`); @@ -3498,7 +3510,7 @@ const getFilteredGameForPlayer = (game, session) => { } }); - console.log('${todo}: Move game win state to card play section'); + console.log(`${todo}: Move game win state to card play section`); if (!game.winner && (player.points >= 10 && session.color === key)) { game.winner = key; game.state = 'winner';