1
0

Lot of progress

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-01-27 00:11:15 -08:00
parent 71d125b3c2
commit a4c15e83d3
2 changed files with 178 additions and 114 deletions

View File

@ -13,7 +13,7 @@ import { deepOrange, lightBlue, red, grey } from '@material-ui/core/colors';
import Avatar from '@material-ui/core/Avatar';
import Switch from '@material-ui/core/Switch';
import Moment from 'react-moment';
//import moment from 'moment';
import moment from 'moment';
/* Start of withRouter polyfill */
// https://reactrouter.com/docs/en/v6/faq#what-happened-to-withrouter-i-need-it
@ -106,7 +106,7 @@ const Tiles = (board) => {
window.requestAnimationFrame(board.drawFrame);
});
image.addEventListener("error", (event) => {
alert(`Error loading ${file}`);
this.setState({message: `Error loading ${file}`});
});
image.src = `${assetsPath}/gfx/${file}`;
});
@ -123,7 +123,7 @@ const Pips = (board) => {
window.requestAnimationFrame(board.drawFrame);
});
image.addEventListener("error", (event) => {
alert(`Error loading ${file}`);
this.setState({message: `Error loading ${file}`});
});
image.src = `${assetsPath}/gfx/${file}`;
@ -141,7 +141,7 @@ const Border = (board, border) => {
window.requestAnimationFrame(board.drawFrame);
});
image.addEventListener("error", (event) => {
alert(`Error loading ${file}`);
board.setState({ message: `Error loading ${file}` });
});
image.src = `${assetsPath}/gfx/${file}`;
return border;
@ -154,31 +154,12 @@ const Table = (board) => {
window.requestAnimationFrame(board.drawFrame);
});
image.addEventListener("error", (event) => {
alert(`Error loading ${file}`);
board.setState({ message: `Error loading ${file}` });
});
image.src = `${assetsPath}/gfx/${file}`;
return image;
};
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
class Placard extends React.Component {
render() {
return (
@ -230,7 +211,7 @@ class Resource extends React.Component {
}
};
const Chat = ({ game, promoteGameState }) => {
const Chat = ({ board, promoteGameState }) => {
const chatInput = (event) => {
};
@ -239,7 +220,7 @@ const Chat = ({ game, promoteGameState }) => {
console.log(`Send: ${event.target.value}`);
promoteGameState({
chat: {
player: game.activePlayer,
player: board.game.activePlayer,
message: event.target.value
}
});
@ -256,7 +237,7 @@ const Chat = ({ game, promoteGameState }) => {
//const timeDelta = game.timestamp - Date.now();
const messages = game.chat.map((item, index) => {
const messages = board.game.chat.map((item, index) => {
//const timestamp = moment(item.date - timeDelta).fromNow();
return (
<ListItem key={`msg-${index}`}>
@ -278,7 +259,7 @@ const Chat = ({ game, promoteGameState }) => {
{ messages }
</List>
<TextField className="chatInput"
disabled={!game.activePlayer}
disabled={!board.game.activePlayer}
inputRef={input => input && input.focus()}
onChange={chatInput}
onKeyPress={chatKeyPress}
@ -287,18 +268,28 @@ const Chat = ({ game, promoteGameState }) => {
);
}
const Action = ({ game, promoteGameState }) => {
const actionClick = (event) => {
this.setGameState("active").then((state) => {
game.state = state;
const Action = ({ board }) => {
const startClick = (event) => {
board.setGameState("active").then((state) => {
board.game.state = state;
});
};
const newBoardClick = (event) => {
return board.shuffleBoard();
};
const rollClick = (event) => {
board.throwDice();
}
return (
<>
{ game.state == 'lobby' &&
{ board.game.state == 'lobby' &&
<Paper className="Action">
<Button onClick={actionClick}>Start game</Button>
<Button fullWidth onClick={startClick}>Start game</Button>
<Button fullWidth onClick={newBoardClick}>New board</Button>
<Button fullWidth onClick={rollClick}>Roll</Button>
</Paper>
}
</>
@ -307,7 +298,7 @@ const Action = ({ game, promoteGameState }) => {
/* This needs to take in a mechanism to declare the
* player's active item in the game */
const Players = ({ game, promoteGameState }) => {
const Players = ({ board, promoteGameState }) => {
const [selected, setSelected] = useState("");
const [name, setName] = useState("");
@ -325,26 +316,26 @@ const Players = ({ game, promoteGameState }) => {
useEffect(() => {
const change = { players: {} };
/* Joining: selected != "", activePlayer == "", and name != "" */
if (selected && !game.activePlayer && name) {
/* Joining: selected != "" and name != "" */
if (selected && name && !board.game.activePlayer) {
change.players[selected] = { name: name }
promoteGameState(change)
return;
}
/* Leaving: selected = "", name = "", activePlayer != "" */
if (!selected && game.activePlayer) {
change.players[game.activePlayer] = { name: "" }
/* Leaving: selected = "", name = "" */
if (!selected && board.game.activePlayer) {
change.players[board.game.activePlayer] = { name: "" }
promoteGameState(change)
return;
}
/* Updating name: selected != "", activePlayer != "", name != "", name != activePlayer.name*/
/* Updating name: selected != "", name != "", name != board.name*/
if (selected &&
game.activePlayer &&
board.player &&
name &&
game.players[game.activePlayer].name !== name) {
change.players[game.activePlayer] = { name: name }
board.game.players[board.game.activePlayer].name !== name) {
change.players[board.game.activePlayer] = { name: name }
promoteGameState(change)
return;
}
@ -362,8 +353,8 @@ const Players = ({ game, promoteGameState }) => {
const classes = useStyles();
const players = [];
for (let key in game.players) {
const item = game.players[key];
for (let key in board.game.players) {
const item = board.game.players[key];
players.push((
<ListItem key={`player-${key}`}>
<ListItemAvatar>
@ -409,7 +400,8 @@ class Board extends React.Component {
brick: 0,
stone: 0,
wheat: 0,
game: null
game: null,
message: ""
};
this.componentDidMount = this.componentDidMount.bind(this);
this.updateDimensions = this.updateDimensions.bind(this);
@ -419,13 +411,13 @@ class Board extends React.Component {
this.drawDie = this.drawDie.bind(this);
this.keyUp = this.keyUp.bind(this);
this.mouseMove = this.mouseMove.bind(this);
this.randomize = this.randomize.bind(this);
this.throwDice = this.throwDice.bind(this);
this.promoteGameState = this.promoteGameState.bind(this);
this.resetGameLoad = this.resetGameLoad.bind(this);
this.loadGame = this.loadGame.bind(this);
this.rollDice = this.rollDice.bind(this);
this.setGameState = this.setGameState.bind(this);
this.shuffleBoard = this.shuffleBoard.bind(this);
this.mouse = { x: 0, y: 0 };
this.radius = 0.317;
@ -448,6 +440,44 @@ class Board extends React.Component {
this.id = (props.router && props.router.params.id) ? props.router.params.id : 0;
}
shuffleBoard() {
if (this.loadTimer) {
window.clearTimeout(this.loadTimer);
this.loadTimer = null;
}
return window.fetch(`${base}/api/v1/games/${this.state.game.id}/shuffle`, {
method: "PUT",
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
}
}).then((res) => {
if (res.status >= 400) {
throw new Error(`Unable to shuffle!`);
}
return res.json();
}).then((game) => {
console.log (`Board shuffled!`);
this.game = game;
this.setState({ game: game, message: "" });
this.pips = Pips(this);
this.tiles = Tiles(this);
this.table = Table(this);
this.borders = this.game.borders.map((file) => {
return Border(this, file);
});
}).catch((error) => {
console.error(error);
this.setState({message: error.message});
}).then(() => {
this.resetGameLoad();
window.requestAnimationFrame(this.drawFrame);
});
}
rollDice() {
if (this.loadTimer) {
window.clearTimeout(this.loadTimer);
@ -462,7 +492,7 @@ class Board extends React.Component {
'Content-Type': 'application/json'
}
}).then((res) => {
if (res.status > 400) {
if (res.status >= 400) {
console.log(res);
throw new Error(`Unable to roll dice`);
}
@ -471,10 +501,10 @@ class Board extends React.Component {
console.log (`Dice rolled!`);
console.log(game.dice);
this.game = game;
this.setState({ game: { ...this.state.game, dice: game.dice }} );
this.setState({ game: { ...this.state.game, dice: game.dice }, message: ""} );
}).catch((error) => {
console.error(error);
alert(error);
this.setState({message: error.message});
}).then(() => {
this.resetGameLoad();
return this.game.dice;
@ -487,11 +517,12 @@ class Board extends React.Component {
this.loadTimer = null;
}
if (this.state.game) {
//return;
if (!this.state.game) {
console.error('Attempting to loadGame with no game set');
return;
}
window.fetch(`${base}/api/v1/games/${this.state.game.id}`, {
return window.fetch(`${base}/api/v1/games/${this.state.game.id}`, {
method: "GET",
cache: 'no-cache',
credentials: 'same-origin',
@ -499,17 +530,18 @@ class Board extends React.Component {
'Content-Type': 'application/json'
}
}).then((res) => {
if (res.status > 400) {
if (res.status >= 400) {
console.log(res);
throw new Error(`Unable to load state`);
}
return res.json();
}).then((game) => {
console.log (`Game state loaded.`);
this.setState({ game: game });
console.log (`Game ${game.id} loaded ${moment().format()}.`);
this.game = game;
this.setState({ game: game, message: "" });
}).catch((error) => {
console.error(error);
alert(error);
this.setState({message: error.message});
}).then(() => {
this.resetGameLoad();
});
@ -531,7 +563,7 @@ class Board extends React.Component {
this.loadTimer = null;
}
window.fetch(`${base}/api/v1/games/${this.state.game.id}`, {
return window.fetch(`${base}/api/v1/games/${this.state.game.id}`, {
method: "PUT",
cache: 'no-cache',
credentials: 'same-origin',
@ -540,44 +572,24 @@ class Board extends React.Component {
},
body: JSON.stringify(change)
}).then((res) => {
if (res.status > 400) {
if (res.status >= 400) {
console.error(res);
throw new Error(`Unable to change state`);
}
return res.json();
}).then((game) => {
console.log (`Game state changed.`);
this.setState({ game: game });
this.game = game;
this.setState({ game: game, message: "" });
}).catch((error) => {
console.error(error);
alert(error);
this.setState({message: error.message});
}).then(() => {
this.resetGameLoad();
});
}
randomize() {
//this.borders = shuffle(this.borders);
this.tiles = shuffle(this.tiles);
this.tiles.forEach((tile) => {
tile.roads = [];
tile.settlements = [];
tile.jitter = Math.random() - 0.5;
});
this.closest.tile = null;
window.requestAnimationFrame(this.drawFrame);
}
keyUp(event) {
if (event.keyCode === 78) { /* n */
this.randomize();
return;
}
if (event.keyCode === 32) { /* space */
this.throwDice();
return;
}
}
setGameState(state) {
@ -594,7 +606,7 @@ class Board extends React.Component {
'Content-Type': 'application/json'
}
}).then((res) => {
if (res.status > 400) {
if (res.status >= 400) {
console.log(res);
throw new Error(`Unable to set state to ${state}`);
}
@ -602,10 +614,10 @@ class Board extends React.Component {
}).then((game) => {
console.log (`Game state set to ${game.state}!`);
this.game = game;
this.setState({ game: { ...this.state.game, state: game.state }} );
this.setState({ game: { ...this.state.game, state: game.state }, message: ""} );
}).catch((error) => {
console.error(error);
alert(error);
this.setState({message: error.message});
}).then(() => {
this.resetGameLoad();
return this.game.state;
@ -754,11 +766,13 @@ class Board extends React.Component {
this.width = window.innerWidth;
this.height = height;
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.style.top = `${offset}px`;
this.canvas.style.width = `${this.width}px`;
this.canvas.style.height = `${this.height}px`;
if (this.canvas) {
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.style.top = `${offset}px`;
this.canvas.style.width = `${this.width}px`;
this.canvas.style.height = `${this.height}px`;
}
this.cards.style.top = `${offset}px`;
this.cards.style.width = `${this.width}px`;
this.cards.style.height = `${this.heigh}tpx`;
@ -1158,26 +1172,42 @@ class Board extends React.Component {
},
// body: JSON.stringify(data) // body data type must match "Content-Type" header
}).then((res) => {
if (res.status > 400) {
let message;
if (this.id) {
message = `Unable to find game ${this.id}. Starting new game.`;
} else {
message = `Starting new game.`;
}
console.log(message);
if (res.status < 400) {
return res;
}
let message;
if (!this.id) {
message = `Unable to create new game.`;
throw new Error(message);
}
message = `Unable to find game ${this.id}. Starting new game.`
console.log(message);
this.setState({ message: message });
params.url = `${base}/api/v1/games`;
params.method = "POST";
return window.fetch(params.url, {
method: params.method,
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
}
});
}).then((res) => {
return res.json();
}).then((game) => {
console.log (`Game ${game.id} loaded.`);
console.log (`Game ${game.id} loaded ${moment().format()}.`);
if (!this.id) {
history.push(`${gamesPath}/${game.id}`);
}
this.game = game;
this.setState({ game: game });
this.setState({ game: game, message: "" });
this.pips = Pips(this);
this.tiles = Tiles(this);
this.table = Table(this);
@ -1187,7 +1217,7 @@ class Board extends React.Component {
});
}).catch((error) => {
console.error(error);
alert(error);
this.setState({message: error.message});
}).then(() => {
this.resetGameLoad();
});
@ -1196,6 +1226,9 @@ class Board extends React.Component {
}
componentWillUnmount() {
if (this.loadTimer) {
clearTimeout(this.loadTimer);
}
if (this.updateSizeTimer) {
clearTimeout(this.updateSizeTimer);
this.updateSizeTimer = 0;
@ -1214,9 +1247,10 @@ class Board extends React.Component {
<div className="Cards" ref={el => this.cards = el}>
{ game &&
<div className="Game">
<Players game={game} promoteGameState={this.promoteGameState}/>
<Chat game={game} promoteGameState={this.promoteGameState}/>
<Action game={game} promoteGameState={this.promoteGameState}/>
<Players board={this} promoteGameState={this.promoteGameState}/>
<Chat board={this} promoteGameState={this.promoteGameState}/>
<Action board={this}/>
{ this.state.message != "" && <Paper><div style={{align:"left",fontSize:"8pt"}}>{this.state.message}</div></Paper> }
</div>
}
<div>In hand</div>

View File

@ -120,17 +120,45 @@ const roll = (game, player) => {
}
}
router.put("/:id/:action", (req, res) => {
router.put("/:id/:action/:value?", (req, res) => {
console.log(`PUT games/${req.params.id}/${req.params.action}`);
if (!req.params.action in games) {
const error = `Game not found: ${req.params.id}`;
return res.status(404).send(error);
}
const game = games[req.params.id];
if (!req.session.activePlayer || !req.session.activePlayer in game.players) {
const error = `Invalid player: ${req.session.activePlayer}`;
return res.status(404).send(error);
}
const player = game.players[req.session.activePlayer].name;
switch (req.params.action) {
case "roll":
roll(game, req.session.activePlayer);
roll(game, player);
break;
case "shuffle":
if (game.state === "lobby") {
shuffleBoard(game);
const message = `${player} requested a new board.`;
game.chat.push({ date: Date.now(), message: message });
console.log(message);
return sendGame(res, req, game);
} else {
const error = `Game no longer in lobby (${game.state}). Can not shuffle board.`;
return res.status(400).send(error)
}
case "state":
const state = req.params.value ? req.params.value : "active";
if (state != game.state) {
game.state = state;
const message = `${player} set game state to ${state}.`;
game.chat.push({ date: Date.now(), message: message });
}
return sendGame(res, req, game);
}
return sendGame(res, req, game);
@ -230,6 +258,14 @@ router.post("/", (req, res/*, next*/) => {
id: crypto.randomBytes(8).toString('hex')
};
games[game.id] = game;
req.session.activePlayer = null;
shuffleBoard(game);
console.log(`New game created: ${game.id}`);
return sendGame(res, req, game);
});
const shuffleBoard = (game) => {
[ "tiles", "pips", "borders" ].forEach((field) => {
game[field] = []
for (let i = 0; i < assetData[field].length; i++) {
@ -244,13 +280,7 @@ router.post("/", (req, res/*, next*/) => {
});
shuffle(game.developmentCards)
games[game.id] = game;
console.log(`New game created: ${game.id}`);
return sendGame(res, req, game);
});
}
/*
return gameDB.sequelize.query("SELECT " +