Board rendering only occurs once per signature
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
dfc5123d25
commit
222ca2d3c3
@ -28,7 +28,7 @@ body {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #00000060;
|
||||
background-color: #80000060;
|
||||
}
|
||||
|
||||
.Table .ErrorDialog .Error {
|
||||
@ -36,6 +36,23 @@ body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.Table .WarningDialog {
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.Table .WarningDialog .Warning {
|
||||
display: flex;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.Table .Game {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -17,7 +17,8 @@ import { Chat } from "./Chat.js";
|
||||
import { MediaAgent } from "./MediaControl.js";
|
||||
import { Board } from "./Board.js";
|
||||
import { Actions } from "./Actions.js";
|
||||
import { base, gamesPath, debounce } from './Common.js';
|
||||
import { base, gamesPath } from './Common.js';
|
||||
import { GameOrder } from "./GameOrder.js";
|
||||
import history from "./history.js";
|
||||
import "./App.css";
|
||||
|
||||
@ -28,66 +29,89 @@ const Table = () => {
|
||||
const [ ws, setWs ] = useState(global.ws);
|
||||
const [ name, setName ] = useState(global.name);
|
||||
const [ error, setError ] = useState(undefined);
|
||||
const [ warning, setWarning ] = useState(undefined);
|
||||
const [ peers, setPeers ] = useState({});
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [connecting, setConnecting] = useState(false);
|
||||
const [connecting, setConnecting] = useState(undefined);
|
||||
const [state, setState] = useState(undefined);
|
||||
const [color, setColor] = useState(undefined);
|
||||
const fields = [ 'name', 'id', 'state', 'color', 'name' ];
|
||||
|
||||
/*
|
||||
useEffect(() => {
|
||||
console.log(peers);
|
||||
}, [peers]);
|
||||
*/
|
||||
|
||||
const onWsOpen = (event) => {
|
||||
console.log(`ws: open`);
|
||||
setError("");
|
||||
|
||||
/* We do not set the socket as bound until the 'open' message
|
||||
/* We do not set the socket as connected until the 'open' message
|
||||
* comes through */
|
||||
setWs(event.target);
|
||||
setConnecting(false);
|
||||
setConnecting(event.target);
|
||||
|
||||
/* Request a full game-update
|
||||
* We only need gameId and name for App.js, however in the event
|
||||
* of a network disconnect, we need to refresh the entire game
|
||||
* state on reload so all bound components reflect the latest
|
||||
* state */
|
||||
if (loaded) {
|
||||
event.target.send(JSON.stringify({
|
||||
type: 'game-update'
|
||||
}));
|
||||
if (name) {
|
||||
event.target.send(JSON.stringify({
|
||||
type: 'player-name',
|
||||
name
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.target.send(JSON.stringify({
|
||||
type: 'get',
|
||||
fields: [ 'name', 'id' ]
|
||||
}))
|
||||
}
|
||||
event.target.send(JSON.stringify({
|
||||
type: 'game-update'
|
||||
}));
|
||||
event.target.send(JSON.stringify({
|
||||
type: 'get',
|
||||
fields
|
||||
}));
|
||||
};
|
||||
|
||||
const onWsMessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
switch (data.type) {
|
||||
case 'error':
|
||||
console.error(data.error);
|
||||
console.error(`App - error`, data.error);
|
||||
window.alert(data.error);
|
||||
break;
|
||||
case 'warning':
|
||||
setWarning(`App - warning`, data.warning);
|
||||
setTimeout(() => {
|
||||
if (data.warning === warning) {
|
||||
setWarning("");
|
||||
}
|
||||
}, 3000);
|
||||
break;
|
||||
case 'game-update':
|
||||
if (!loaded) {
|
||||
setLoaded(true);
|
||||
}
|
||||
console.log(`ws: message - ${data.type}`, data.update);
|
||||
if ('player' in data.update) {
|
||||
const player = data.update.player;
|
||||
if (player.name !== name) {
|
||||
console.log(`App - setting name (via player): ${data.update.name}`);
|
||||
setName(data.update.name);
|
||||
}
|
||||
if (player.color !== color) {
|
||||
console.log(`App - setting color (via player): ${data.update.color}`);
|
||||
setColor(data.update.color);
|
||||
}
|
||||
}
|
||||
if ('name' in data.update && data.update.name !== name) {
|
||||
console.log(`Updating name to ${data.update.name}`);
|
||||
console.log(`App - setting name: ${data.update.name}`);
|
||||
setName(data.update.name);
|
||||
}
|
||||
if ('id' in data.update && data.update.id !== gameId) {
|
||||
console.log(`Updating id to ${data.update.id}`);
|
||||
console.log(`App - setting gameId ${data.update.id}`);
|
||||
setGameId(data.update.id);
|
||||
}
|
||||
if ('state' in data.update && data.update.state !== state) {
|
||||
console.log(`App - setting game state: ${data.update.state}`);
|
||||
setState(data.update.state);
|
||||
}
|
||||
if ('color' in data.update && data.update.color !== color) {
|
||||
console.log(`App - setting color: ${color}`);
|
||||
setColor(data.update.color);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -98,7 +122,7 @@ const Table = () => {
|
||||
let timer = 0;
|
||||
function reset() {
|
||||
timer = 0;
|
||||
setConnecting(false);
|
||||
setConnecting(undefined);
|
||||
};
|
||||
return _ => {
|
||||
if (timer) {
|
||||
@ -109,20 +133,19 @@ const Table = () => {
|
||||
})();
|
||||
|
||||
const onWsError = (event) => {
|
||||
console.log(`ws: error`, event);
|
||||
console.error(`ws: error`, event);
|
||||
const error = `Connection to Ketr Ketran game server failed! ` +
|
||||
`Connection attempt will be retried every 5 seconds.`;
|
||||
console.error(error);
|
||||
setError(error);
|
||||
setWs(undefined);
|
||||
resetConnection();
|
||||
setError(error);
|
||||
};
|
||||
|
||||
const onWsClose = (event) => {
|
||||
const error = `Connection to Ketr Ketran game was lost. ` +
|
||||
`Attempting to reconnect...`;
|
||||
console.error(error);
|
||||
console.log(`ws: close`);
|
||||
console.warn(`ws: close`);
|
||||
setError(error);
|
||||
setWs(undefined);
|
||||
resetConnection();
|
||||
};
|
||||
@ -152,7 +175,7 @@ const Table = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Requesting new game.");
|
||||
console.log(`Requesting new game.`);
|
||||
|
||||
window.fetch(`${base}/api/v1/games/`, {
|
||||
method: 'POST',
|
||||
@ -190,8 +213,13 @@ const Table = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
let socket = ws;
|
||||
if (!ws) {
|
||||
const unbind = () => {
|
||||
console.log(`table - unbind`);
|
||||
}
|
||||
|
||||
console.log(`table - bind`);
|
||||
|
||||
if (!ws && !connecting) {
|
||||
let loc = window.location, new_uri;
|
||||
if (loc.protocol === "https:") {
|
||||
new_uri = "wss";
|
||||
@ -200,42 +228,68 @@ const Table = () => {
|
||||
}
|
||||
new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${gameId}`;
|
||||
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
||||
socket = new WebSocket(new_uri);
|
||||
setConnecting(true);
|
||||
setWs(new WebSocket(new_uri));
|
||||
setConnecting(undefined);
|
||||
return unbind;
|
||||
}
|
||||
|
||||
if (!ws) {
|
||||
return unbind;
|
||||
}
|
||||
|
||||
console.log('table - bind');
|
||||
const cbOpen = e => refWsOpen.current(e);
|
||||
const cbMessage = e => refWsMessage.current(e);
|
||||
const cbClose = e => refWsClose.current(e);
|
||||
const cbError = e => refWsError.current(e);
|
||||
|
||||
socket.addEventListener('open', cbOpen);
|
||||
socket.addEventListener('close', cbClose);
|
||||
socket.addEventListener('error', cbError);
|
||||
socket.addEventListener('message', cbMessage);
|
||||
ws.addEventListener('open', cbOpen);
|
||||
ws.addEventListener('close', cbClose);
|
||||
ws.addEventListener('error', cbError);
|
||||
ws.addEventListener('message', cbMessage);
|
||||
|
||||
return () => {
|
||||
if (socket) {
|
||||
console.log('table - unbind');
|
||||
socket.removeEventListener('open', cbOpen);
|
||||
socket.removeEventListener('close', cbClose);
|
||||
socket.removeEventListener('error', cbError);
|
||||
socket.removeEventListener('message', cbMessage);
|
||||
}
|
||||
unbind();
|
||||
ws.removeEventListener('open', cbOpen);
|
||||
ws.removeEventListener('close', cbClose);
|
||||
ws.removeEventListener('error', cbError);
|
||||
ws.removeEventListener('message', cbMessage);
|
||||
}
|
||||
}, [ setWs, connecting, setConnecting, gameId, ws, refWsOpen, refWsMessage, refWsClose, refWsError ]);
|
||||
|
||||
console.log(`Loaded: ${loaded}`);
|
||||
|
||||
return <GlobalContext.Provider value={{
|
||||
ws, name, gameId, peers, setPeers }}>
|
||||
return <GlobalContext.Provider value={{ ws: connecting, name, gameId, peers, setPeers }}>
|
||||
<MediaAgent/>
|
||||
<PingPong/>
|
||||
<div className="Table">
|
||||
{ error && <div className="ErrorDialog"><Paper className="Error">{ error }</Paper></div> }
|
||||
<div className="Game">
|
||||
{ error && <div className="ErrorDialog"><Paper className="Error">{ error }</Paper></div> }
|
||||
{ warning && <div className="WarningDialog"><Paper className="Warning">{ warning }</Paper></div> }
|
||||
<Board/>
|
||||
{ color && state === 'game-order' &&
|
||||
<GameOrder/>
|
||||
}
|
||||
|
||||
{ /* state === 'winner' &&
|
||||
<Winner color={winner}/>
|
||||
}
|
||||
|
||||
{ state === 'normal' &&
|
||||
turn && turn.actions && turn.actions.indexOf('trade') !== -1 &&
|
||||
<Trade/>
|
||||
}
|
||||
|
||||
{ cardActive &&
|
||||
<ViewCard card={cardActive}/>
|
||||
}
|
||||
|
||||
{ isTurn && turn && turn.actions && game.turn.actions.indexOf('select-resources') !== -1 &&
|
||||
<ChooseCard type={turn.active}/>
|
||||
}
|
||||
|
||||
{ game.state === 'normal' &&
|
||||
turn && isTurn && turn.actions && turn.actions.indexOf('steal-resource') !== -1 &&
|
||||
<SelectPlayer table={this} game={this.state} players={game.turn.limits.players}/>
|
||||
*/ }
|
||||
|
||||
<div className="Hand">todo: player's hand</div>
|
||||
</div>
|
||||
<div className="Sidebar">
|
||||
@ -248,7 +302,6 @@ const Table = () => {
|
||||
};
|
||||
|
||||
const App = () => {
|
||||
console.log(`Base: ${base}`);
|
||||
return (
|
||||
<Router>
|
||||
<Routes>
|
||||
|
@ -2,6 +2,24 @@ import React, { useEffect, useState, useContext, useRef, useMemo } from "react";
|
||||
import { assetsPath, debounce } from "./Common.js";
|
||||
import "./Board.css";
|
||||
import { GlobalContext } from "./GlobalContext.js";
|
||||
const rows = [3, 4, 5, 4, 3, 2]; /* The final row of 2 is to place roads and corners */
|
||||
|
||||
const
|
||||
hexRatio = 1.1547,
|
||||
tileWidth = 67,
|
||||
tileHalfWidth = tileWidth * 0.5,
|
||||
tileHeight = tileWidth * hexRatio,
|
||||
tileHalfHeight = tileHeight * 0.5,
|
||||
radius = tileHeight * 2,
|
||||
borderOffsetX = 86, /* ~1/10th border image width... hand tuned */
|
||||
borderOffsetY = 3;
|
||||
|
||||
/* Actual sizing */
|
||||
const
|
||||
tileImageWidth = 90, /* Based on hand tuned and image width */
|
||||
tileImageHeight = tileImageWidth/hexRatio,
|
||||
borderImageWidth = (2 + 2/3) * tileImageWidth, /* 2.667 * .Tile.width */
|
||||
borderImageHeight = borderImageWidth * 0.29; /* 0.29 * .Border.height */
|
||||
|
||||
const Board = () => {
|
||||
const { ws } = useContext(GlobalContext);
|
||||
@ -12,13 +30,14 @@ const Board = () => {
|
||||
const [cornerElements, setCornerElements] = useState(<></>);
|
||||
const [roadElements, setRoadElements] = useState(<></>);
|
||||
const [ signature, setSignature ] = useState("");
|
||||
const [ generated, setGenerated ] = useState("");
|
||||
const [ robber, setRobber ] = useState(-1);
|
||||
const [ robberName, setRobberName ] = useState([]);
|
||||
const [ pips, setPips ] = useState([]);
|
||||
const [ pipOrder, setPipOrder ] = useState([]);
|
||||
const [ borders, setBorders ] = useState([]);
|
||||
const [ borderOrder, setBorderOrder ] = useState([]);
|
||||
const [ tiles, setTiles ] = useState([]);
|
||||
const [ pips, setPips ] = useState();
|
||||
const [ pipOrder, setPipOrder ] = useState();
|
||||
const [ borders, setBorders ] = useState();
|
||||
const [ borderOrder, setBorderOrder ] = useState();
|
||||
const [ tiles, setTiles ] = useState();
|
||||
const [ tileOrder, setTileOrder ] = useState([]);
|
||||
const [ placements, setPlacements ] = useState(undefined);
|
||||
const [ turn, setTurn ] = useState({});
|
||||
@ -31,59 +50,120 @@ const Board = () => {
|
||||
'placements', 'turn', 'state', 'color', 'longestRoadLength'
|
||||
], []);
|
||||
|
||||
/* Placements is a structure of roads and corners arrays
|
||||
* indicating what is stored at each of the locations
|
||||
*
|
||||
* Corners consist of a type and color
|
||||
* Roads consist of a color, and longestRoad
|
||||
*
|
||||
* See games.js resetGame, placeRoad, placeSettlement, placeCity,
|
||||
* and calculateRoadLengths
|
||||
*
|
||||
* Returns: true === differences, false === same
|
||||
*/
|
||||
const comparePlacements = (A, B) => {
|
||||
if (!A && !B) {
|
||||
return false; /* same */
|
||||
}
|
||||
if ((A && !B)
|
||||
|| (!A && B)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((A.roads.length !== B.roads.length)
|
||||
|| (A.corners.length !== B.corners.length)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Roads compare color and longestRoad */
|
||||
for (let i = 0; i < A.roads.length; i++) {
|
||||
if (A.roads[i].color !== B.roads[i].color) {
|
||||
return true;
|
||||
}
|
||||
if (A.roads[i].longestRoad !== B.roads[i].longestRoad) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Corners compare type and color */
|
||||
for (let i = 0; i < A.corners.length; i++) {
|
||||
if (A.corners[i].type !== B.corners[i].type) {
|
||||
return true;
|
||||
}
|
||||
if (A.corners[i].color !== B.corners[i].color) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false; /* same */
|
||||
};
|
||||
|
||||
const onWsMessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
switch (data.type) {
|
||||
case 'game-update':
|
||||
if (data.update.signature && data.update.signature !== signature) {
|
||||
setSignature(data.update.signature);
|
||||
}
|
||||
|
||||
if (data.update.robber && data.update.robber !== robber) {
|
||||
console.log(`board - game update`, data.update);
|
||||
if ('robber' in data.update && data.update.robber !== robber) {
|
||||
setRobber(data.update.robber);
|
||||
}
|
||||
|
||||
if (data.update.robberName && data.update.robberName !== robberName) {
|
||||
if ('robberName' in data.update && data.update.robberName !== robberName) {
|
||||
setRobberName(data.update.robberName);
|
||||
}
|
||||
|
||||
if (data.update.pips) {
|
||||
setPips(data.update.pips);
|
||||
}
|
||||
if (data.update.pipOrder) {
|
||||
setPipOrder(data.update.pipOrder);
|
||||
}
|
||||
|
||||
if (data.update.borders) {
|
||||
setBorders(data.update.borders);
|
||||
}
|
||||
if (data.update.borderOrder) {
|
||||
setBorderOrder(data.update.borderOrder);
|
||||
}
|
||||
|
||||
if (data.update.tiles) {
|
||||
setTiles(data.update.tiles);
|
||||
}
|
||||
if (data.update.tileOrder) {
|
||||
setTileOrder(data.update.tileOrder);
|
||||
}
|
||||
|
||||
if (data.update.state && data.update.state !== state) {
|
||||
if ('state' in data.update && data.update.state !== state) {
|
||||
setState(data.update.state);
|
||||
}
|
||||
if (data.update.color && data.update.color !== color) {
|
||||
|
||||
if ('color' in data.update && data.update.color !== color) {
|
||||
setColor(data.update.color);
|
||||
}
|
||||
if (data.update.longestRoadLength
|
||||
|
||||
if ('longestRoadLength' in data.update
|
||||
&& data.update.longestRoadLength !== longestRoadLength) {
|
||||
setLongestRoadLength(data.update.longestRoadLength);
|
||||
}
|
||||
if (data.update.turn) {
|
||||
|
||||
if ('turn' in data.update) {
|
||||
setTurn(data.update.turn);
|
||||
}
|
||||
if (data.update.placements) {
|
||||
console.log(`placements`, data.update.placements);
|
||||
setPlacements(data.update.placements);
|
||||
|
||||
if ('placement' in data.update) {
|
||||
if (comparePlacements(data.update.placements, placements)) {
|
||||
console.log(`placements`, data.update.placements);
|
||||
setPlacements(data.update.placements);
|
||||
}
|
||||
}
|
||||
|
||||
if ('signature' in data.update && data.update.signature !== signature) {
|
||||
setSignature(data.update.signature);
|
||||
|
||||
/* The following are only updated if there is a new game
|
||||
* signature */
|
||||
|
||||
if ('pipOrder' in data.update) {
|
||||
setPipOrder(data.update.pipOrder);
|
||||
}
|
||||
|
||||
if ('borderOrder' in data.update) {
|
||||
setBorderOrder(data.update.borderOrder);
|
||||
}
|
||||
|
||||
if ('tileOrder' in data.update) {
|
||||
setTileOrder(data.update.tileOrder);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is permanent static data from the server -- do not update
|
||||
* once set */
|
||||
if ('pips' in data.update && !pips) {
|
||||
setPips(data.update.pips);
|
||||
}
|
||||
if ('tiles' in data.update && !tiles) {
|
||||
setTiles(data.update.tiles);
|
||||
}
|
||||
if ('borders' in data.update && !borders) {
|
||||
setBorders(data.update.borders);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -135,9 +215,11 @@ const Board = () => {
|
||||
if (!ws) {
|
||||
return;
|
||||
}
|
||||
console.log('board - bind');
|
||||
const cbMessage = e => refWsMessage.current(e);
|
||||
ws.addEventListener('message', cbMessage);
|
||||
return () => {
|
||||
console.log('board - unbind');
|
||||
ws.removeEventListener('message', cbMessage);
|
||||
}
|
||||
}, [ws, refWsMessage]);
|
||||
@ -152,23 +234,6 @@ const Board = () => {
|
||||
}));
|
||||
}, [ws, fields]);
|
||||
|
||||
const
|
||||
hexRatio = 1.1547,
|
||||
tileWidth = 67,
|
||||
tileHalfWidth = tileWidth * 0.5,
|
||||
tileHeight = tileWidth * hexRatio,
|
||||
tileHalfHeight = tileHeight * 0.5,
|
||||
radius = tileHeight * 2,
|
||||
borderOffsetX = 86, /* ~1/10th border image width... hand tuned */
|
||||
borderOffsetY = 3;
|
||||
|
||||
/* Actual sizing */
|
||||
const
|
||||
tileImageWidth = 90, /* Based on hand tuned and image width */
|
||||
tileImageHeight = tileImageWidth/hexRatio,
|
||||
borderImageWidth = (2 + 2/3) * tileImageWidth, /* 2.667 * .Tile.width */
|
||||
borderImageHeight = borderImageWidth * 0.29; /* 0.29 * .Border.height */
|
||||
|
||||
const Tile = ({tile}) => {
|
||||
const onClick = (event) => {
|
||||
console.log(`Tile clicked: ${tile.index}`);
|
||||
@ -237,7 +302,7 @@ const Board = () => {
|
||||
sendPlacement('place-robber', pip.index);
|
||||
};
|
||||
|
||||
return <div className="Pip"
|
||||
return <div className="Pip"
|
||||
onClick={onClick}
|
||||
data-roll={pip.roll}
|
||||
data-index={pip.index}
|
||||
@ -255,7 +320,17 @@ const Board = () => {
|
||||
if (!signature) {
|
||||
return;
|
||||
}
|
||||
const rows = [3, 4, 5, 4, 3, 2]; /* The final row of 2 is to place roads and corners */
|
||||
|
||||
if (signature === generated) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pips || !pipOrder || !borders || !borderOrder
|
||||
|| !tiles || !tileOrder) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`board - Generate board - ${signature}`);
|
||||
|
||||
const generateRoads = () => {
|
||||
let row = 0, rowCount = 0;
|
||||
@ -406,7 +481,6 @@ const Board = () => {
|
||||
return pipOrder.map(order => {
|
||||
pip = {
|
||||
roll: pips[order].roll,
|
||||
robber: index === robber,
|
||||
index: index++,
|
||||
top: y,
|
||||
left: x,
|
||||
@ -484,19 +558,18 @@ const Board = () => {
|
||||
});
|
||||
};
|
||||
|
||||
console.log(`Generate for ${signature}`);
|
||||
setPipElements(generatePips());
|
||||
setBorderElements(generateBorders());
|
||||
setTileElements(generateTiles());
|
||||
setCornerElements(generateCorners());
|
||||
setRoadElements(generateRoads());
|
||||
|
||||
setGenerated(signature);
|
||||
}, [
|
||||
signature,
|
||||
setPipElements, setBorderElements, setTileElements,
|
||||
setCornerElements, setRoadElements,
|
||||
borderImageWidth, radius, tileHalfHeight, tileHalfWidth, tileHeight,
|
||||
borderImageHeight,
|
||||
borderOrder, borders, pipOrder, pips, robber, tileOrder, tiles
|
||||
borderOrder, borders, pipOrder, pips, tileOrder, tiles
|
||||
]);
|
||||
|
||||
if (turn) {
|
||||
|
@ -1,6 +1,4 @@
|
||||
import React, { useState, useEffect, useContext, useRef } from "react";
|
||||
import "./Chat.css";
|
||||
import PlayerColor from './PlayerColor.js';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
@ -9,8 +7,10 @@ import Moment from 'react-moment';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import 'moment-timezone';
|
||||
|
||||
import Resource from './Resource.js';
|
||||
import Dice from './Dice.js';
|
||||
import "./Chat.css";
|
||||
import { PlayerColor } from './PlayerColor.js';
|
||||
import { Resource } from './Resource.js';
|
||||
import { Dice } from './Dice.js';
|
||||
import { GlobalContext } from "./GlobalContext.js";
|
||||
|
||||
const Chat = () => {
|
||||
|
@ -18,6 +18,6 @@ const Dice = ({ pips }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Dice;
|
||||
export { Dice };
|
||||
|
||||
|
||||
|
@ -14,4 +14,4 @@ const PlayerColor = ({ color }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default PlayerColor;
|
||||
export { PlayerColor };
|
@ -1,9 +1,9 @@
|
||||
import React, { useState, useEffect, useContext, useRef } from "react";
|
||||
import "./PlayerList.css";
|
||||
import PlayerColor from './PlayerColor.js';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import List from '@material-ui/core/List';
|
||||
|
||||
import "./PlayerList.css";
|
||||
import { PlayerColor } from './PlayerColor.js';
|
||||
import { MediaControl } from "./MediaControl.js";
|
||||
import { GlobalContext } from "./GlobalContext.js";
|
||||
|
||||
@ -18,9 +18,12 @@ const PlayerList = () => {
|
||||
const data = JSON.parse(event.data);
|
||||
switch (data.type) {
|
||||
case 'game-update':
|
||||
console.log(`player-list - game update`, data.update);
|
||||
|
||||
if ('unselected' in data.update) {
|
||||
setUneslected(data.update.unselected);
|
||||
}
|
||||
|
||||
if ('players' in data.update) {
|
||||
let found = false;
|
||||
for (let key in data.update.players) {
|
||||
@ -35,6 +38,7 @@ const PlayerList = () => {
|
||||
}
|
||||
setPlayers(data.update.players);
|
||||
}
|
||||
|
||||
if ('state' in data.update && data.update.state !== state) {
|
||||
setState(data.update.state);
|
||||
}
|
||||
|
@ -39,4 +39,4 @@ const Resource = ({ type, select, disabled, available, count, label, onClick })
|
||||
);
|
||||
};
|
||||
|
||||
export default Resource;
|
||||
export { Resource };
|
@ -67,64 +67,6 @@ const StartButton = ({ table, game }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const GameOrder = ({table, game}) => {
|
||||
|
||||
const rollClick = (event) => {
|
||||
table.throwDice();
|
||||
}
|
||||
|
||||
if (!game) {
|
||||
return (<></>);
|
||||
}
|
||||
|
||||
let players = [], hasRolled = true;
|
||||
for (let color in game.players) {
|
||||
const item = game.players[color],
|
||||
name = getPlayerName(game.sessions, color);
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
if (!item.orderRoll) {
|
||||
item.orderRoll = 0;
|
||||
}
|
||||
if (color === game.color) {
|
||||
hasRolled = item.orderRoll !== 0;
|
||||
}
|
||||
players.push({ name: name, color: color, ...item });
|
||||
}
|
||||
|
||||
players.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;
|
||||
});
|
||||
|
||||
players = players.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">
|
||||
{ game && <Paper>
|
||||
<div className="Title">Game Order</div>
|
||||
<div className="PlayerList">
|
||||
{ players }
|
||||
</div>
|
||||
<Button disabled={hasRolled} onClick={rollClick}>Roll Dice</Button>
|
||||
</Paper> }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SelectPlayer = ({table, game, players}) => {
|
||||
const playerClick = (event) => {
|
||||
table.stealResource(event.currentTarget.getAttribute('data-color'));
|
||||
@ -160,78 +102,6 @@ const SelectPlayer = ({table, game, players}) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Action = ({ table, game }) => {
|
||||
const buildClicked = (event) => {
|
||||
table.buildClicked(event);
|
||||
};
|
||||
|
||||
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');
|
||||
}
|
||||
return table.discard(discarding);
|
||||
}
|
||||
|
||||
const newTableClick = (event) => {
|
||||
return table.shuffleTable();
|
||||
};
|
||||
|
||||
const tradeClick = (event) => {
|
||||
table.startTrading();
|
||||
}
|
||||
|
||||
const rollClick = (event) => {
|
||||
table.throwDice();
|
||||
}
|
||||
|
||||
const passClick = (event) => {
|
||||
return table.passTurn();
|
||||
}
|
||||
/*
|
||||
const quitClick = (event) => {
|
||||
table.setSelected("");
|
||||
}
|
||||
*/
|
||||
if (!game.id) {
|
||||
console.log("Why no game id?");
|
||||
return (<Paper className="Action"/>);
|
||||
}
|
||||
|
||||
const inLobby = game.state === 'lobby',
|
||||
inGame = game.state === 'normal',
|
||||
player = game ? game.player : undefined,
|
||||
hasRolled = (game && game.turn && game.turn.roll) ? true : false,
|
||||
isTurn = (game && game.turn && game.turn.color === game.color) ? true : false,
|
||||
robberActions = (game && game.turn && game.turn.robberInAction),
|
||||
haveResources = player ? player.haveResources : false,
|
||||
placement = (game.state === 'initial-placement' || game.turn.active === 'road-building'),
|
||||
placeRoad = placement && game.turn && game.turn.actions && game.turn.actions.indexOf('place-road') !== -1;
|
||||
|
||||
return (
|
||||
<Paper className="Action">
|
||||
{ inLobby && <>
|
||||
<StartButton table={table} game={game}/>
|
||||
<Button disabled={game.color ? false : true} onClick={newTableClick}>New table</Button>
|
||||
<Button disabled={game.color ? true : false} onClick={() => {table.setState({ pickName: true})}}>Change name</Button> </> }
|
||||
{ !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>
|
||||
{ game.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>
|
||||
*/ }
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
const PlayerName = ({table, game}) => {
|
||||
const [name, setName] = useState(game.name ? game.name : "");
|
||||
|
||||
|
@ -350,6 +350,7 @@ const Trade = ({table}) => {
|
||||
/* Order direction is reversed for self */
|
||||
source = {
|
||||
name: item.name,
|
||||
color: item.color,
|
||||
gets: trade.gives,
|
||||
gives: trade.gets
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user