diff --git a/server/routes/games.js b/server/routes/games.js index 9b627d6..7dc3922 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -103,10 +103,7 @@ router.get("/:id", (req, res/*, next*/) => { console.log("GET games/" + req.params.id); if (req.params.id in games) { const game = games[req.params.id]; - return res.status(200).send(Object.assign({}, game, { - timestamp: Date.now(), - activePlayer: req.session.activePlayer - })); + return sendGame(res, req, game) } else { const error = `Game not found: ${req.params.id}`; return res.status(404).send(error); @@ -119,6 +116,7 @@ router.put("/:id", (req, res/*, next*/) => { const game = games[req.params.id], changes = req.body; + console.log(req.session.id, req.session.activePlayer); console.log(JSON.stringify(changes, null, 2)); for (let change in changes) { @@ -152,16 +150,21 @@ router.put("/:id", (req, res/*, next*/) => { break; } } - return res.status(200).send(Object.assign({}, game, { - timestamp: Date.now(), - activePlayer: req.session.activePlayer - })); + return sendGame(res, req, game); } else { const error = `Game not found: ${req.params.id}`; return res.status(404).send(error); } }); +const sendGame = (res, req, game) => { + return res.status(200).send(Object.assign({}, game, { + timestamp: Date.now(), + activePlayer: (req.session && req.session.activePlayer) ? + req.session.activePlayer : null + })); +} + router.post("/", (req, res/*, next*/) => { console.log("POST games/"); const game = { @@ -186,8 +189,8 @@ router.post("/", (req, res/*, next*/) => { wheat: 19, longestRoad: null, largestArmy: null, - chat: [ { from: "R", date: Date.now(), message: "Hello, world!" } ], - id: crypto.randomBytes(20).toString('hex') + chat: [ { from: "R", date: Date.now(), message: "Server initialized!" } ], + id: crypto.randomBytes(8).toString('hex') }; [ "tiles", "pips", "borders" ].forEach((field) => { @@ -208,10 +211,7 @@ router.post("/", (req, res/*, next*/) => { games[game.id] = game; console.log(`New game created: ${game.id}`); - return res.status(200).send(Object.assign({}, game, { - timestamp: Date.now(), - activePlayer: req.session.activePlayer - })); + return sendGame(res, req, game); }); diff --git a/sessions.db b/sessions.db index 8dd904d..e646316 100644 Binary files a/sessions.db and b/sessions.db differ diff --git a/src/Board.css b/src/Board.css index 02c8e00..c7050ba 100755 --- a/src/Board.css +++ b/src/Board.css @@ -42,11 +42,21 @@ filter: brightness(150%); } +.Game { + display: inline-flex; + flex-direction: column; + width: 20em; + opacity: 0.7; + z-index: 100; + overflow: hidden; +} + +.Game > *:not(:last-child) { + margin-bottom: 0.5em; +} + .Chat { padding: 0.5em; - width: 30vmax; - display: inline-block; - opacity: 0.7; } .Chat > * { @@ -54,15 +64,12 @@ } .Chat > :first-child { - height: 10vh; + max-height: 30vh; overflow-y: scroll; } .Players { padding: 0.5em; - width: 30vmax; - display: inline-block; - opacity: 0.7; } #ChatList { diff --git a/src/Board.js b/src/Board.js index 4c600bf..51ea891 100755 --- a/src/Board.js +++ b/src/Board.js @@ -210,13 +210,17 @@ class Resource extends React.Component { const Chat = ({ game, promoteGameState }) => { const chatInput = (event) => { - console.log(event.target.value); }; const chatKeyPress = (event) => { if (event.key == "Enter") { console.log(`Send: ${event.target.value}`); - promoteGameState({ chat: { player: game.activePlayer, message: event.target.value }}); + promoteGameState({ + chat: { + player: game.activePlayer, + message: event.target.value + } + }); event.target.value = ""; } }; @@ -227,8 +231,7 @@ const Chat = ({ game, promoteGameState }) => { const chatList = document.getElementById("ChatList"); chatList.scrollTop = chatList.scrollHeight - chatList.offsetHeight; }) - console.log(JSON.stringify(game, null, 2)); - + const timeDelta = game.timestamp - Date.now(); const messages = game.chat.map((item, index) => { @@ -242,7 +245,11 @@ const Chat = ({ game, promoteGameState }) => { ); }); - + + useEffect(() => { + document.querySelector(".chatInput").focus(); + }); + return ( @@ -250,6 +257,7 @@ const Chat = ({ game, promoteGameState }) => { input && input.focus()} onChange={chatInput} onKeyPress={chatKeyPress} label={()} variant="outlined"/> @@ -278,25 +286,27 @@ const Players = ({ game, promoteGameState }) => { const change = { players: {} }; /* Joining: selected != "", activePlayer == "", and name != "" */ - if (selected && !game.activePlayer && name != "") { + if (selected && !game.activePlayer && name) { change.players[selected] = { name: name } promoteGameState(change) return; } /* Leaving: selected = "", name = "", activePlayer != "" */ - if (!selected && game.activePlayer != "") { + if (!selected && game.activePlayer) { change.players[game.activePlayer] = { name: "" } promoteGameState(change) + return; } /* Updating name: selected != "", activePlayer != "", name != "", name != activePlayer.name*/ - if (selected != "" && - game.activePlayer != "" && - name != "" && + if (selected && + game.activePlayer && + name && game.players[game.activePlayer].name != name) { change.players[game.activePlayer] = { name: name } promoteGameState(change) + return; } }); @@ -325,7 +335,7 @@ const Players = ({ game, promoteGameState }) => { onChange={nameInput} onKeyPress={nameKeyPress} inputRef={input => input && input.focus()} - disabled={name != item.name} + disabled={(name != item.name) ? true: false} label="Name" variant="outlined" autoFocus/> } @@ -334,7 +344,7 @@ const Players = ({ game, promoteGameState }) => { } toggleSelected(key)}/> )); @@ -372,10 +382,13 @@ class Board extends React.Component { this.randomize = this.randomize.bind(this); this.throwDice = this.throwDice.bind(this); this.promoteGameState = this.promoteGameState.bind(this); + this.loadGame = this.loadGame.bind(this); this.mouse = { x: 0, y: 0 }; this.radius = 0.317; + this.loadTimer = null; + this.game = null; this.pips = []; this.tiles = []; @@ -433,15 +446,56 @@ class Board extends React.Component { this.borders = this.game.borders.map((file) => { return Border(this, file); }); + + this.loadTimer = window.setTimeout(this.loadGame, 1000); }).catch((error) => { console.error(error); alert(error); + }) + } + + loadGame() { + if (this.loadTimer) { + window.clearTimeout(this.loadTimer); + this.loadTimer = null; + } + + if (!this.state.game) { + return; + } + + window.fetch(`api/v1/games/${this.state.game.id}`, { + method: "GET", + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + } + }).then((res) => { + if (res.status > 400) { + console.log(res); + throw `Unable to load state`; + } + return res.json(); + }).then((game) => { + console.log (`Game state loaded.`); + this.setState({ game: game }); + }).catch((error) => { + console.error(error); + alert(error); + }).then(() => { + this.loadTimer = window.setTimeout(this.loadGame, 1000); }); } promoteGameState(change) { console.log("Requesting state change: ", change); + if (this.loadTimer) { + window.clearTimeout(this.loadTimer); + this.loadTimer = null; + } + window.fetch(`api/v1/games/${this.state.game.id}`, { method: "PUT", cache: 'no-cache', @@ -453,14 +507,19 @@ class Board extends React.Component { }).then((res) => { if (res.status > 400) { console.error(res); - alert(`Unable to change state`); + throw `Unable to change state`; } return res.json(); }).then((game) => { console.log (`Game state changed.`); this.setState({ game: game }); - }); - } + }).catch((error) => { + console.error(error); + alert(error); + }).then(() => { + this.loadTimer = window.setTimeout(this.loadGame, 1000); + }); +} randomize() { //this.borders = shuffle(this.borders); @@ -1013,10 +1072,10 @@ class Board extends React.Component { this.canvas = el}>
this.cards = el}> { game && - <> - +
- + +
}
In hand