diff --git a/client/src/App.css b/client/src/App.css
index 2dd8b20..585af2e 100755
--- a/client/src/App.css
+++ b/client/src/App.css
@@ -60,6 +60,7 @@ body {
}
.Table .Game {
+ position: relative;
display: flex;
flex-direction: column;
flex-grow: 1;
diff --git a/client/src/App.js b/client/src/App.js
index 5e8fcb1..3ffb29d 100755
--- a/client/src/App.js
+++ b/client/src/App.js
@@ -19,6 +19,7 @@ import { Actions } from "./Actions.js";
import { base, gamesPath } from './Common.js';
import { GameOrder } from "./GameOrder.js";
import { Activities } from "./Activities.js";
+import { SelectPlayer } from "./SelectPlayer.js";
import history from "./history.js";
import "./App.css";
@@ -291,10 +292,10 @@ const Table = () => {
}
{ warning &&
}
+ { state === 'normal' && }
+ { color && state === 'game-order' && }
+
- { color && state === 'game-order' &&
-
- }
{ /* state === 'winner' &&
@@ -311,12 +312,7 @@ const Table = () => {
{ isTurn && turn && turn.actions && game.turn.actions.indexOf('select-resources') !== -1 &&
- }
-
- { game.state === 'normal' &&
- turn && isTurn && turn.actions && turn.actions.indexOf('steal-resource') !== -1 &&
-
- */ }
+ */ }
todo: player's hand
diff --git a/client/src/GameOrder.css b/client/src/GameOrder.css
index 62384e5..7a0bbed 100644
--- a/client/src/GameOrder.css
+++ b/client/src/GameOrder.css
@@ -2,13 +2,12 @@
display: flex;
position: absolute;
left: 0;
- right: 30vw;
+ right: 0;
bottom: 0;
top: 0;
justify-content: center;
align-items: center;
z-index: 1000;
- max-height: 100vh;
overflow: auto;
}
diff --git a/client/src/SelectPlayer.css b/client/src/SelectPlayer.css
new file mode 100644
index 0000000..27b6e4f
--- /dev/null
+++ b/client/src/SelectPlayer.css
@@ -0,0 +1,53 @@
+.SelectPlayer {
+ display: flex;
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ justify-content: center;
+ align-items: center;
+ overflow: auto;
+ background-color: #40404020;
+ z-index: 10000;
+}
+
+.SelectPlayer .Title {
+ align-self: center;
+ padding: 2px;
+ font-weight: bold;
+}
+
+.SelectPlayer .SelectPlayerList {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ padding: 0.5em;
+ background-color:rgba(224, 224, 224);
+ margin: 0.5em 0;
+}
+
+.SelectPlayer > * {
+ width: 20em;
+ display: inline-flex;
+ padding: 0.5em;
+ flex-direction: column;
+}
+
+.SelectPlayer .PlayerColor {
+ width: 1em;
+ height: 1em;
+}
+
+.SelectPlayer .SelectPlayerItem {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+ align-items: center;
+ padding: 2px 0;
+ cursor: pointer;
+}
+
+.SelectPlayer > * {
+ margin: 0 0.25em;
+}
diff --git a/client/src/SelectPlayer.js b/client/src/SelectPlayer.js
new file mode 100644
index 0000000..b57eb25
--- /dev/null
+++ b/client/src/SelectPlayer.js
@@ -0,0 +1,84 @@
+import React, { useState, useEffect, useContext, useRef, useMemo } from "react";
+import Paper from '@material-ui/core/Paper';
+import equal from "fast-deep-equal";
+
+import { PlayerColor } from "./PlayerColor.js";
+
+import "./SelectPlayer.css";
+
+import { GlobalContext } from "./GlobalContext.js";
+
+const SelectPlayer = () => {
+ const { ws } = useContext(GlobalContext);
+ const [turn, setTurn] = useState(undefined);
+ const [color, setColor] = useState(undefined);
+ const fields = useMemo(() => [
+ 'turn', 'color'
+ ], []);
+
+ const onWsMessage = (event) => {
+ const data = JSON.parse(event.data);
+ switch (data.type) {
+ case 'game-update':
+ console.log(`select-players - game-update: `, data.update);
+ if ('turn' in data.update && !equal(turn, data.update.turn)) {
+ setTurn(data.update.turn);
+ }
+ if ('color' in data.update && data.update.color !== color) {
+ setColor(data.update.color);
+ }
+ 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 playerClick = (event) => {
+ ws.send(JSON.stringify({
+ type: 'steal-resource',
+ color: event.currentTarget.getAttribute('data-color')
+ }));
+ }
+
+ if (!color || !turn || turn.color !== color || !turn.limits || !turn.limits.players) {
+ return (<>>);
+ }
+
+ const list = turn.limits.players.map(item =>
+
+ );
+
+ return (
+
+
+ Select Player to Steal From
+
+ { list }
+
+
+
+ );
+};
+
+export { SelectPlayer };
\ No newline at end of file
diff --git a/client/src/Table.js b/client/src/Table.js
index 4dbc654..d86ea7d 100755
--- a/client/src/Table.js
+++ b/client/src/Table.js
@@ -67,41 +67,6 @@ const StartButton = ({ table, game }) => {
);
};
-const SelectPlayer = ({table, game, players}) => {
- const playerClick = (event) => {
- table.stealResource(event.currentTarget.getAttribute('data-color'));
- }
-
- if (!game.id) {
- return (<>>);
- }
-
- let list = players.map(color => {
- let item = {
- color: color,
- name: getPlayerName(game.sessions, color)
- };
- return ;
- });
-
- return (
-
- { game &&
- Select Player to Steal From
-
- { list }
-
- }
-
- );
-};
-
const PlayerName = ({table, game}) => {
const [name, setName] = useState(game.name ? game.name : "");
diff --git a/server/routes/games.js b/server/routes/games.js
index 25c6fac..38977fa 100755
--- a/server/routes/games.js
+++ b/server/routes/games.js
@@ -246,6 +246,7 @@ const roll = (game, session) => {
return `You already rolled this turn.`;
}
processRoll(game, session, [ Math.ceil(Math.random() * 6), Math.ceil(Math.random() * 6) ]);
+ sendUpdateToPlayers(game, { chat: game.chat });
return;
default:
@@ -361,6 +362,7 @@ const processRoll = (game, session, dice) => {
players: game.players,
chat: game.chat
});
+ return;
}
/* ROBBER Robber Robinson! */
@@ -1020,8 +1022,8 @@ const addChatMessage = (game, session, message) => {
if (game.chat.length) {
lastTime = game.chat[game.chat.length - 1].date;
}
- if (now === lastTime) {
- now++;
+ if (now <= lastTime) {
+ now = lastTime + 1;
}
const entry = {
@@ -1870,10 +1872,17 @@ const pass = (game, session) => {
game.turns++;
addActivity(game, session, `${name} passed their turn.`);
addChatMessage(game, null, `It is ${next}'s turn.`);
+
+ sendUpdateToPlayers(game, {
+ turn: game.turn,
+ chat: game.chat,
+ activites: game.activities
+ });
}
-const placeRobber = (game, session, value) => {
+const placeRobber = (game, session, robber) => {
const name = session.name;
+ robber = parseInt(robber);
if (game.state !== 'normal' && game.turn.roll !== 7) {
return `You cannot place robber unless 7 was rolled!`;
@@ -1890,7 +1899,7 @@ const placeRobber = (game, session, value) => {
return `You cannot place the robber until everyone has discarded!`;
}
}
- const robber = parseInt(value ? value : 0);
+
if (game.robber === robber) {
return `You must move the robber to a new location!`;
}
@@ -1900,17 +1909,22 @@ const placeRobber = (game, session, value) => {
pickRobber(game);
addActivity(game, null, `${game.robberName} Robber Robinson entered the scene as the nefarious robber!`);
- let colors = [];
+ let targets = [];
layout.tiles[robber].corners.forEach(cornerIndex => {
const active = game.placements.corners[cornerIndex];
- if (active && active.color && active.color !== game.turn.color && colors.indexOf(active.color) == -1) {
- colors.push(active.color);
+ if (active && active.color
+ && active.color !== game.turn.color
+ && targets.findIndex(item => item.color === active.color) === -1) {
+ targets.push({
+ color: active.color,
+ name: game.players[active.color].name
+ });
}
});
- if (colors.length) {
+ if (targets.length) {
game.turn.actions = [ 'steal-resource' ],
- game.turn.limits = { players: colors };
+ game.turn.limits = { players: targets };
} else {
game.turn.actions = [];
game.turn.robberInAction = false;
@@ -1920,18 +1934,29 @@ const placeRobber = (game, session, value) => {
`with no other players, ` +
`so ${game.turn.name} does not steal resources from anyone.`);
}
+
+ sendUpdateToPlayers(game, {
+ placements: game.placements,
+ turn: game.turn,
+ chat: game.chat,
+ robber: game.robber,
+ robberName: game.robberName,
+ activities: game.activities
+ });
+ sendUpdateToPlayer(session, {
+ private: game.player
+ });
}
-const stealResource = (game, session, value) => {
- const name = session.name;
+const stealResource = (game, session, color) => {
if (game.turn.actions.indexOf('steal-resource') === -1) {
return `You can only steal a resource when it is valid to do so!`;
}
- if (game.turn.limits.players.indexOf(value) === -1) {
+ if (game.turn.limits.players.findIndex(item => item.color === color) === -1) {
return `You can only steal a resource from a player on this terrain!`;
}
- let victim = game.players[value];
- cards = [];
+ const victim = game.players[color];
+ const cards = [];
[ 'wheat', 'brick', 'sheep', 'stone', 'wood' ].forEach(field => {
for (let i = 0; i < victim[field]; i++) {
cards.push(field);
@@ -1962,6 +1987,14 @@ const stealResource = (game, session, value) => {
debugChat(game, 'After steal');
game.turn.robberInAction = false;
+ sendUpdateToPlayers(game, {
+ turn: game.turn,
+ chat: game.chat,
+ activities: game.activities
+ });
+ sendUpdateToPlayer(session, {
+ private: game.player
+ });
}
const buyDevelopment = (game, session, value) => {
@@ -2005,6 +2038,15 @@ const buyDevelopment = (game, session, value) => {
card = game.developmentCards.pop();
card.turn = game.turns;
player.development.push(card);
+
+ sendUpdateToPlayers(game, {
+ chat: game.chat,
+ activities: game.activities,
+ players: getFilteredPlayers(game)
+ });
+ sendUpdateToPlayer(session, {
+ private: game.player
+ });
}
const playCard = (game, session, { card }) => {
@@ -2115,6 +2157,17 @@ const playCard = (game, session, { card }) => {
game.turn.limits.pips.push(i);
}
}
+
+ sendUpdateToPlayers(game, {
+ chat: game.chat,
+ activities: game.activities,
+ largestArmy: game.largestArmy,
+ largestArmySize: game.largestArmySize,
+ turn: game.turn
+ });
+ sendUpdateToPlayer(session, {
+ private: game.player
+ });
}
const placeSettlement = (game, session, index) => {
@@ -3344,6 +3397,27 @@ const wsConnect = async (ws, req) => {
sendWarning(session, warning);
}
break;
+ case 'place-robber':
+ console.log(`${short}: <- place-robber:${getName(session)} ${data.index}`);
+ warning = placeRobber(game, session, data.index);
+ if (warning) {
+ sendWarning(session, warning);
+ }
+ break;
+ case 'steal-resource':
+ console.log(`${short}: <- steal-resource:${getName(session)} ${data.color}`);
+ warning = stealResource(game, session, data.color);
+ if (warning) {
+ sendWarning(session, warning);
+ }
+ break;
+ case 'pass':
+ console.log(`${short}: <- pass:${getName(session)}`);
+ warning = pass(game, session);
+ if (warning) {
+ sendWarning(session, warning);
+ }
+ break;
default:
console.warn(`Unsupported request: ${data.type}`);
break;