1
0

Send back to lobby if < 2 players

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-01-27 18:23:41 -08:00
parent 7885c094e1
commit b57e771679
7 changed files with 87 additions and 126 deletions

View File

@ -1 +1,3 @@
PUBLIC_URL=/ketr.ketran
HOST=nuc.ketrenos.com
DANGEROUSLY_DISABLE_HOST_CHECK='true'

View File

@ -18,7 +18,7 @@
"web-vitals": "^2.1.2" "web-vitals": "^2.1.2"
}, },
"scripts": { "scripts": {
"start": "export $(cat ../.env | xargs) && react-scripts start", "start": "react-scripts start",
"build": "export $(cat ../.env | xargs) && react-scripts build", "build": "export $(cat ../.env | xargs) && react-scripts build",
"test": "export $(cat ../.env | xargs) && react-scripts test", "test": "export $(cat ../.env | xargs) && react-scripts test",
"eject": "export $(cat ../.env | xargs) && react-scripts eject" "eject": "export $(cat ../.env | xargs) && react-scripts eject"

View File

@ -227,13 +227,12 @@ const Chat = ({ board, promoteGameState }) => {
//const timeDelta = game.timestamp - Date.now(); //const timeDelta = game.timestamp - Date.now();
const messages = board.game.chat.map((item, index) => { const messages = board.game.chat.map((item, index) => {
//const timestamp = moment(item.date - timeDelta).fromNow();
return ( return (
<ListItem key={`msg-${index}`}> <ListItem key={`msg-${index}`}>
<ListItemAvatar> <ListItemAvatar>
<Avatar className={classes[item.from]}>{item.from}</Avatar> <Avatar className={classes[item.from]}>{item.from}</Avatar>
</ListItemAvatar> </ListItemAvatar>
<ListItemText primary={item.message} secondary={(<Moment fromNow interval={1000}/>)} /> <ListItemText primary={item.message} secondary={(<Moment fromNow date={item.date} interval={1000}/>)} />
</ListItem> </ListItem>
); );
}); });
@ -344,6 +343,10 @@ const Players = ({ board, promoteGameState }) => {
const players = []; const players = [];
for (let key in board.game.players) { for (let key in board.game.players) {
const item = board.game.players[key]; const item = board.game.players[key];
console.log(item);
if (board.game.state != "lobby" && item.status == 'Not active') {
continue;
}
players.push(( players.push((
<ListItem key={`player-${key}`}> <ListItem key={`player-${key}`}>
<ListItemAvatar> <ListItemAvatar>
@ -492,10 +495,12 @@ class Board extends React.Component {
} }
return res.json(); return res.json();
}).then((game) => { }).then((game) => {
console.log (`Dice rolled!`); let message = game.status != "success" ? game.status : "Dice rolled!"
console.log(game.dice); if (game.status != "success") {
game.dice = [];
}
this.updateGame(game); this.updateGame(game);
this.setState({ game: { ...this.state.game, dice: game.dice }, message: "Dice rolled!"} ); this.setState({ game: { ...this.state.game, dice: game.dice }, message: message } );
}).catch((error) => { }).catch((error) => {
console.error(error); console.error(error);
this.setState({message: error.message}); this.setState({message: error.message});
@ -1141,6 +1146,10 @@ class Board extends React.Component {
updateGame(game) { updateGame(game) {
this.game = game; this.game = game;
if (game.state === "invalid") {
return;
}
this.pips = Pips(this); this.pips = Pips(this);
this.tiles = Tiles(this); this.tiles = Tiles(this);
this.table = Table(this); this.table = Table(this);
@ -1251,7 +1260,7 @@ class Board extends React.Component {
return ( return (
<div className="Board" ref={el => this.el = el}> <div className="Board" ref={el => this.el = el}>
<canvas className="Display" ref={el => this.canvas = el}></canvas> <canvas className="Display" ref={el => this.canvas = el}></canvas>
<div className="Cards" ref={el => this.cards = el}> <div className="Cards" ref={el => this.cards = el}>
{ game && { game &&
<div className="Game"> <div className="Game">
<Players board={this} promoteGameState={this.promoteGameState}/> <Players board={this} promoteGameState={this.promoteGameState}/>
@ -1260,7 +1269,10 @@ class Board extends React.Component {
{ this.state.message != "" && <Paper><div style={{align:"left",fontSize:"8pt"}}>{this.state.message}</div></Paper> } { this.state.message != "" && <Paper><div style={{align:"left",fontSize:"8pt"}}>{this.state.message}</div></Paper> }
</div> </div>
} }
<div>In hand</div> {
game && game.state == "active" &&
<>
<div>In hand</div>
<div className="Hand"> <div className="Hand">
<Resource type="wood" count={this.state.wood}/> <Resource type="wood" count={this.state.wood}/>
<Resource type="wheat" count={this.state.wheat}/> <Resource type="wheat" count={this.state.wheat}/>
@ -1300,6 +1312,7 @@ class Board extends React.Component {
<div>Settlements remaining: 5</div> <div>Settlements remaining: 5</div>
</div> </div>
</div> </div>
</> }
</div> </div>
</div> </div>
); );

View File

@ -1,33 +0,0 @@
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: "./src/index.js",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
options: { presets: ["@babel/env"] }
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.(png|svg|jpg|md)$/,
use: [ "file-loader" ]
}
]
},
resolve: {
extensions: ["*", ".js", ".jsx"]
},
output: {
path: path.resolve(__dirname, "dist/"),
publicPath: "./dist/",
filename: "bundle.js"
}
};

View File

@ -1,41 +0,0 @@
const path = require("path");
const merge = require('webpack-merge')
const common = require('./webpack.common.js');
const webpack = require('webpack');
const config = require("config");
const base = config.get("basePath");
const proxy = {
}
console.log(`Using base: ${base}`);
proxy[`${base}/`] = {
target: "http://localhost:8930",
bypass: function(req, res, proxyOptions) {
if ((req.url.indexOf(`${base}/assets`) == 0) ||
(req.url.indexOf(`${base}/dist`) == 0)) {
return req.url.replace(base, "");
}
console.log(`Proxying to backend server: ${req.url}`);
return null;
}
};
/* https://webpack.js.org/configuration/dev-server/ */
module.exports = merge(common, {
mode: "development",
devServer: {
contentBase: path.join(__dirname, "/"),
port: 8930,
publicPath: `http://localhost:8930${base}/dist/`,
hotOnly: true,
disableHostCheck: true,
historyApiFallback: true,
proxy: proxy
},
plugins: [new webpack.HotModuleReplacementPlugin()]
});

View File

@ -1,8 +0,0 @@
const merge = require('webpack-merge')
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: "production",
devtool: 'source-map'
});

View File

@ -101,93 +101,109 @@ for (let i = 0; i < 5; i++) {
const games = {}; const games = {};
const roll = (game, player) => { const roll = (game, player) => {
if (player == 0) { let error;
console.log("No player active; roll has no action"); if (!player) {
return; error = "No player active; roll has no action";
console.log(error);
return error;
} }
const name = player.name;
switch (game.state) { switch (game.state) {
case "lobby": case "lobby":
if (game.players[player].order) { if (player.order) {
console.log(`Player ${player} already rolled for order.`); error = `Player ${name} already rolled for order.`;
return; console.log(error);
return error;
} }
game.dice = [ Math.ceil(Math.random() * 6) ]; game.dice = [ Math.ceil(Math.random() * 6) ];
game.players[player].order = game.dice[0]; player.order = game.dice[0];
const message = `${player} rolled ${game.dice[0]} for play order.`; const message = `${name} rolled ${game.dice[0]} for play order.`;
game.chat.push({ date: Date.now(), message: message }); game.chat.push({ date: Date.now(), message: message });
console.log(message); console.log(message);
return; return;
} }
error = `Invalid game state (${game.state}) in roll.`;
return error;
} }
router.put("/:id/:action/:value?", (req, res) => { router.put("/:id/:action/:value?", (req, res) => {
console.log(`PUT games/${req.params.id}/${req.params.action}`); console.log(`PUT games/${req.params.id}/${req.params.action}`);
if (!req.params.action in games) { if (!(req.params.id in games)) {
const error = `Game not found: ${req.params.id}`; const error = `Game not found: ${req.params.id}`;
return res.status(404).send(error); return res.status(404).send(error);
} }
const game = games[req.params.id]; const game = games[req.params.id];
if (!req.session.activePlayer || !req.session.activePlayer in game.players) { let error;
const error = `Invalid player: ${req.session.activePlayer}`;
return res.status(404).send(error); if (!req.session.activePlayer || !(req.session.activePlayer in game.players)) {
error = `Invalid player: ${req.session.activePlayer}`;
return sendGame(res, req, game, error);
} }
const player = game.players[req.session.activePlayer].name; const player = game.players[req.session.activePlayer],
name = player.name;
switch (req.params.action) { switch (req.params.action) {
case "roll": case "roll":
roll(game, player); error = roll(game, player);
break; break;
case "shuffle": case "shuffle":
if (game.state === "lobby") { if (game.state === "lobby") {
shuffleBoard(game); shuffleBoard(game);
const message = `${player} requested a new board.`; const message = `${name} requested a new board.`;
game.chat.push({ date: Date.now(), message: message }); game.chat.push({ date: Date.now(), message: message });
console.log(message); console.log(message);
return sendGame(res, req, game);
} else { } else {
const error = `Game no longer in lobby (${game.state}). Can not shuffle board.`; error = `Game no longer in lobby (${game.state}). Can not shuffle board.`;
return res.status(400).send(error)
} }
case "state": case "state":
const state = req.params.value ? req.params.value : "active"; const state = req.params.value ? req.params.value : "active";
if (state != game.state) { if (state != game.state) {
game.state = state; game.state = state;
const message = `${player} set game state to ${state}.`; const message = `${name} set game state to ${state}.`;
game.chat.push({ date: Date.now(), message: message }); game.chat.push({ date: Date.now(), message: message });
} }
return sendGame(res, req, game);
} }
return sendGame(res, req, game); return sendGame(res, req, game, error);
}) })
router.get("/:id", async (req, res/*, next*/) => { router.get("/:id", async (req, res/*, next*/) => {
console.log("GET games/" + req.params.id); const id = req.params.id;
let error; console.log("GET games/" + id);
if (req.params.id in games) { let error, game;
const game = games[req.params.id];
if (id in games) {
game = games[id];
return sendGame(res, req, game) return sendGame(res, req, game)
} }
if (/^.|\//.exec(req.params.id)) { if (/^\.|\//.exec(id)) {
error = `Requested game ID is invalid`; error = `Requested game ID is invalid`;
console.log(error, id);
return res.status(400).send(error); return res.status(400).send(error);
} }
const game = await readFile(`games/${req.params.id}`)
game = await readFile(`games/${id}`)
.catch(() => { .catch(() => {
return null; return;
}); });
if (!game) { if (!game) {
error = `Unable to load game: ${req.params.id}`; error = `Game ${id} not found -- returning invalid game state.`;
res.status(404).send(error); console.warn(error);
game = { id: id, state: 'invalid' };
} else { } else {
games[req.params.id] = game; game = JSON.parse(game);
return sendGame(game);
} }
games[id] = game;
return sendGame(res, req, game, error);
}); });
router.put("/:id", (req, res/*, next*/) => { router.put("/:id", (req, res/*, next*/) => {
@ -237,7 +253,18 @@ router.put("/:id", (req, res/*, next*/) => {
} }
}); });
const sendGame = async (res, req, game) => { const sendGame = async (res, req, game, error) => {
let active = 0;
for (let player in game.players) {
player = game.players[player];
active += ((player.status && player.status != 'Not active') ? 1 : 0);
}
if (active < 2 && game.state != 'lobby' && game.state != 'invalid') {
let message = "Insufficient players in game. Setting back to lobby."
game.chat.push({ date: Date.now(), message: message });
console.log(message);
game.state = 'lobby';
}
await writeFile(`games/${game.id}`, JSON.stringify(game, null, 2)) await writeFile(`games/${game.id}`, JSON.stringify(game, null, 2))
.catch((error) => { .catch((error) => {
console.error(`Unable to write to games/${games.id}`); console.error(`Unable to write to games/${games.id}`);
@ -246,6 +273,7 @@ const sendGame = async (res, req, game) => {
return res.status(200).send(Object.assign({}, game, { return res.status(200).send(Object.assign({}, game, {
timestamp: Date.now(), timestamp: Date.now(),
status: error ? error : "success",
activePlayer: (req.session && req.session.activePlayer) ? activePlayer: (req.session && req.session.activePlayer) ?
req.session.activePlayer : null req.session.activePlayer : null
})); }));