Added missing files
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
222ca2d3c3
commit
dce9297aab
28
client/src/Actions.css
Normal file
28
client/src/Actions.css
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
.Actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-shrink: 1;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
background-color: rgba(16, 16, 16, 0.25);
|
||||||
|
margin: 0.25rem 0.25rem 0.25rem 0;
|
||||||
|
padding: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Actions > div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Actions .PlayerName {
|
||||||
|
flex-grow: 1;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Actions button {
|
||||||
|
margin: 0.25em;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid black !important;
|
||||||
|
}
|
||||||
|
|
169
client/src/Actions.js
Normal file
169
client/src/Actions.js
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import React, { useState, useEffect, useContext, useRef, useMemo } from "react";
|
||||||
|
import "./Actions.css";
|
||||||
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import { PlayerName } from './PlayerName.js';
|
||||||
|
|
||||||
|
import { GlobalContext } from "./GlobalContext.js";
|
||||||
|
|
||||||
|
const Actions = () => {
|
||||||
|
const { ws, gameId, name } = useContext(GlobalContext);
|
||||||
|
const [state, setState] = useState('lobby');
|
||||||
|
const [color, setColor] = useState(undefined);
|
||||||
|
const [player, setPlayer] = useState(undefined);
|
||||||
|
const [turn, setTurn] = useState({});
|
||||||
|
const [active, setActive] = useState(0);
|
||||||
|
const [edit, setEdit] = useState(name);
|
||||||
|
|
||||||
|
const fields = useMemo(() => [
|
||||||
|
'state', 'turn', 'player', 'active', 'color'
|
||||||
|
], []);
|
||||||
|
|
||||||
|
const onWsMessage = (event) => {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
switch (data.type) {
|
||||||
|
case 'game-update':
|
||||||
|
if ('state' in data.update && data.update.state !== state) {
|
||||||
|
setState(data.update.state);
|
||||||
|
}
|
||||||
|
if ('color' in data.update && data.update.color !== color) {
|
||||||
|
setColor(data.update.color);
|
||||||
|
}
|
||||||
|
if ('name' in data.update && data.update.name !== edit) {
|
||||||
|
setEdit(data.update.name);
|
||||||
|
}
|
||||||
|
if ('player' in data.update) {
|
||||||
|
setPlayer(data.update.player);
|
||||||
|
}
|
||||||
|
if ('turn' in data.update) {
|
||||||
|
setTurn(data.update.turn);
|
||||||
|
}
|
||||||
|
if ('active' in data.update && data.update.active !== active) {
|
||||||
|
setActive(data.update.active);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const refWsMessage = useRef(onWsMessage);
|
||||||
|
|
||||||
|
useEffect(() => { refWsMessage.current = onWsMessage; });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ws) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cbMessage = e => refWsMessage.current(e);
|
||||||
|
ws.addEventListener('message', cbMessage);
|
||||||
|
return () => {
|
||||||
|
ws.removeEventListener('message', cbMessage);
|
||||||
|
}
|
||||||
|
}, [ws, refWsMessage]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ws) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: 'get',
|
||||||
|
fields
|
||||||
|
}));
|
||||||
|
}, [ws, fields]);
|
||||||
|
|
||||||
|
const sendMessage = (data) => {
|
||||||
|
ws.send(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
const buildClicked = (event) => {
|
||||||
|
alert(`This is a no-op currently; you can click the Build cost card.`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setName = (update) => {
|
||||||
|
if (!update) {
|
||||||
|
setEdit(name);
|
||||||
|
} else if (update !== name) {
|
||||||
|
sendMessage({ type: 'player-name', name: update });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeNameClick = (event) => {
|
||||||
|
setEdit("");
|
||||||
|
}
|
||||||
|
|
||||||
|
const discardClick = (event) => {
|
||||||
|
const nodes = document.querySelectorAll('.Hand .Resource.Selected'),
|
||||||
|
discarding = { wheat: 0, brick: 0, sheep: 0, stone: 0, wood: 0 };
|
||||||
|
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
discarding[nodes[i].getAttribute("data-type")]++;
|
||||||
|
nodes[i].classList.remove('Selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage({ type: 'discard', discarding });
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTableClick = (event) => {
|
||||||
|
sendMessage({ type: 'shuffle' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const tradeClick = (event) => {
|
||||||
|
sendMessage({ type: 'trade' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const rollClick = (event) => {
|
||||||
|
sendMessage({ type: 'roll' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const passClick = (event) => {
|
||||||
|
sendMessage({ type: 'pass' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const startClick = (event) => {
|
||||||
|
sendMessage({
|
||||||
|
type: 'set',
|
||||||
|
field: 'state',
|
||||||
|
value: 'game-order'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return (<Paper className="Actions"/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
const inLobby = state === 'lobby',
|
||||||
|
inGame = state === 'normal',
|
||||||
|
hasRolled = (turn && turn.roll) ? true : false,
|
||||||
|
isTurn = (turn && turn.color === color) ? true : false,
|
||||||
|
robberActions = (turn && turn.robberInAction),
|
||||||
|
haveResources = player ? player.haveResources : false,
|
||||||
|
placement = (state === 'initial-placement' || (turn && turn.active === 'road-building')),
|
||||||
|
placeRoad = placement && turn && turn.actions && turn.actions.indexOf('place-road') !== -1;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper className="Actions">
|
||||||
|
{ edit === "" && <PlayerName name={edit} setName={setName}/> }
|
||||||
|
<div>
|
||||||
|
{ name && inLobby && <>
|
||||||
|
<Button disabled={(color && active >= 2) ? false : true } onClick={startClick}>Start game</Button>
|
||||||
|
<Button disabled={color ? false : true} onClick={newTableClick}>New table</Button>
|
||||||
|
<Button disabled={color ? true : false} onClick={changeNameClick}>Change name</Button>
|
||||||
|
</> }
|
||||||
|
{ name && !inLobby && <>
|
||||||
|
<Button disabled={robberActions || !isTurn || hasRolled || !inGame} onClick={rollClick}>Roll Dice</Button>
|
||||||
|
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled || !haveResources} onClick={tradeClick}>Trade</Button>
|
||||||
|
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled || !haveResources} onClick={buildClicked}>Build</Button>
|
||||||
|
{ turn && turn.roll === 7 && player && player.mustDiscard > 0 &&
|
||||||
|
<Button onClick={discardClick}>Discard</Button>
|
||||||
|
}
|
||||||
|
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled} onClick={passClick}>Done</Button>
|
||||||
|
</> }
|
||||||
|
{ /* inLobby &&
|
||||||
|
<Button onClick={quitClick}>Quit</Button>
|
||||||
|
*/ }
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Actions };
|
||||||
|
|
48
client/src/GameOrder.css
Normal file
48
client/src/GameOrder.css
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
.GameOrder {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 30vw;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
max-height: 100vh;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GameOrder .Title {
|
||||||
|
align-self: center;
|
||||||
|
padding: 2px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GameOrder .PlayerList {
|
||||||
|
padding: 0.5em;
|
||||||
|
background-color:rgba(224, 224, 224);
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
||||||
|
.GameOrder > * {
|
||||||
|
min-width: 20em;
|
||||||
|
display: inline-flex;
|
||||||
|
padding: 0.5em;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GameOrder .PlayerColor {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GameOrder .GameOrderPlayer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GameOrderPlayer > * {
|
||||||
|
margin: 0 0.25em;
|
||||||
|
}
|
109
client/src/GameOrder.js
Normal file
109
client/src/GameOrder.js
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import React, { useState, useEffect, useContext, useRef, useMemo } from "react";
|
||||||
|
import "./Actions.css";
|
||||||
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import { Dice } from "./Dice.js";
|
||||||
|
import { PlayerColor } from "./PlayerColor.js";
|
||||||
|
|
||||||
|
import "./GameOrder.css";
|
||||||
|
|
||||||
|
import { GlobalContext } from "./GlobalContext.js";
|
||||||
|
|
||||||
|
const GameOrder = () => {
|
||||||
|
const { ws } = useContext(GlobalContext);
|
||||||
|
const [player, setPlayer] = useState(undefined);
|
||||||
|
const [players, setPlayers] = useState({});
|
||||||
|
const fields = useMemo(() => [
|
||||||
|
'player', 'players'
|
||||||
|
], []);
|
||||||
|
|
||||||
|
const color = player ? player.color : undefined;
|
||||||
|
|
||||||
|
const onWsMessage = (event) => {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
switch (data.type) {
|
||||||
|
case 'game-update':
|
||||||
|
console.log(`GameOrder game-update: `, data.update);
|
||||||
|
if ('player' in data.update) {
|
||||||
|
setPlayer(data.update.player);
|
||||||
|
}
|
||||||
|
if ('players' in data.update) {
|
||||||
|
setPlayers(data.update.players);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const refWsMessage = useRef(onWsMessage);
|
||||||
|
useEffect(() => { refWsMessage.current = onWsMessage; });
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ws) { return; }
|
||||||
|
const cbMessage = e => refWsMessage.current(e);
|
||||||
|
ws.addEventListener('message', cbMessage);
|
||||||
|
return () => { ws.removeEventListener('message', cbMessage); }
|
||||||
|
}, [ws, refWsMessage]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ws) { return; }
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: 'get',
|
||||||
|
fields
|
||||||
|
}));
|
||||||
|
}, [ws, fields]);
|
||||||
|
|
||||||
|
const sendMessage = (data) => {
|
||||||
|
ws.send(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
const rollClick = (event) => {
|
||||||
|
sendMessage({ type: 'roll' });
|
||||||
|
}
|
||||||
|
|
||||||
|
let playerElements = [], hasRolled = true;
|
||||||
|
for (let key in players) {
|
||||||
|
const item = players[key], name = item.name;
|
||||||
|
if (!name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!item.orderRoll) {
|
||||||
|
item.orderRoll = 0;
|
||||||
|
}
|
||||||
|
if (key === color) {
|
||||||
|
hasRolled = item.orderRoll !== 0;
|
||||||
|
}
|
||||||
|
playerElements.push({ name, color: key, ...item });
|
||||||
|
}
|
||||||
|
|
||||||
|
playerElements.sort((A, B) => {
|
||||||
|
if (A.order === B.order) {
|
||||||
|
if (A.orderRoll === B.orderRoll) {
|
||||||
|
return A.name.localeCompare(B.name);
|
||||||
|
}
|
||||||
|
return B.orderRoll - A.orderRoll;
|
||||||
|
}
|
||||||
|
return B.order - A.order;
|
||||||
|
});
|
||||||
|
|
||||||
|
playerElements = playerElements.map(item =>
|
||||||
|
<div className="GameOrderPlayer" key={`player-${item.color}`}>
|
||||||
|
<PlayerColor color={item.color}/>
|
||||||
|
<div>{item.name}</div>
|
||||||
|
{ item.orderRoll !== 0 && <>rolled <Dice pips={item.orderRoll}/>. {item.orderStatus}</> }
|
||||||
|
{ item.orderRoll === 0 && <>has not rolled yet. {item.orderStatus}</>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="GameOrder">
|
||||||
|
<Paper>
|
||||||
|
<div className="Title">Game Order</div>
|
||||||
|
<div className="PlayerList">
|
||||||
|
{ playerElements }
|
||||||
|
</div>
|
||||||
|
<Button disabled={hasRolled} onClick={rollClick}>Roll Dice</Button>
|
||||||
|
</Paper>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { GameOrder };
|
Loading…
x
Reference in New Issue
Block a user