Turn notice!
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
083e3c3a6f
commit
391e438990
@ -25,9 +25,3 @@
|
|||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Actions button {
|
|
||||||
margin: 0.25em;
|
|
||||||
background-color: white;
|
|
||||||
border: 1px solid black !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ body {
|
|||||||
background-image: url("./assets/tabletop.png");
|
background-image: url("./assets/tabletop.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.Table .ErrorDialog {
|
.Table .Dialogs {
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
@ -29,46 +29,44 @@ body {
|
|||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Table .Dialogs .Dialog {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0.25rem;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Table .Dialogs .Dialog > div {
|
||||||
|
display: flex;
|
||||||
|
padding: 1rem;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Table .Dialogs .Dialog > div > div:first-child {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Table .Dialogs .TurnNoticeDialog {
|
||||||
|
background-color: #7a680060;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Table .Dialogs .ErrorDialog {
|
||||||
background-color: #40000060;
|
background-color: #40000060;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Table .ErrorDialog .Error {
|
.Table .Dialogs .WarningDialog {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Table .ErrorDialog .Error > div {
|
|
||||||
display: flex;
|
|
||||||
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;
|
|
||||||
background-color: #00000060;
|
background-color: #00000060;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Table .WarningDialog .Warning {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Table .WarningDialog .Warning > div {
|
|
||||||
display: flex;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.Table .PlayersStatus {
|
.Table .PlayersStatus {
|
||||||
z-index: 5000;
|
z-index: 5000;
|
||||||
}
|
}
|
||||||
@ -161,3 +159,15 @@ body {
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Table button {
|
||||||
|
margin: 0.25em;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.Table button:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
border: 1px solid #ccc !important;
|
||||||
|
}
|
@ -29,6 +29,7 @@ import { Winner } from "./Winner.js";
|
|||||||
|
|
||||||
import history from "./history.js";
|
import history from "./history.js";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
|
import equal from "fast-deep-equal";
|
||||||
|
|
||||||
const Table = () => {
|
const Table = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
@ -39,14 +40,14 @@ const Table = () => {
|
|||||||
const [ warning, setWarning ] = useState(undefined);
|
const [ warning, setWarning ] = useState(undefined);
|
||||||
const [ peers, setPeers ] = useState({});
|
const [ peers, setPeers ] = useState({});
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [loaded, setLoaded] = useState(false);
|
||||||
const [connecting, setConnecting] = useState(undefined);
|
const [connection, setConnection] = useState(undefined);
|
||||||
const [state, setState] = useState(undefined);
|
const [state, setState] = useState(undefined);
|
||||||
const [color, setColor] = useState(undefined);
|
const [color, setColor] = useState(undefined);
|
||||||
const [players, setPlayers] = useState(undefined);
|
const [setPlayers] = useState(undefined);
|
||||||
const [player, setPlayer] = useState(undefined);
|
const [priv, setPriv] = useState(undefined);
|
||||||
const [buildActive, setBuildActive] = useState(false);
|
const [buildActive, setBuildActive] = useState(false);
|
||||||
const [cardActive, setCardActive] = useState(undefined);
|
const [cardActive, setCardActive] = useState(undefined);
|
||||||
const fields = [ 'id', 'state', 'color', 'name' ];
|
const fields = [ 'id', 'state', 'color', 'name', 'private' ];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(`app - media-agent - peers`, peers);
|
console.log(`app - media-agent - peers`, peers);
|
||||||
@ -58,7 +59,7 @@ const Table = () => {
|
|||||||
|
|
||||||
/* We do not set the socket as connected until the 'open' message
|
/* We do not set the socket as connected until the 'open' message
|
||||||
* comes through */
|
* comes through */
|
||||||
setConnecting(event.target);
|
setConnection(ws);
|
||||||
|
|
||||||
/* Request a full game-update
|
/* Request a full game-update
|
||||||
* We only need gameId and name for App.js, however in the event
|
* We only need gameId and name for App.js, however in the event
|
||||||
@ -95,31 +96,22 @@ const Table = () => {
|
|||||||
setLoaded(true);
|
setLoaded(true);
|
||||||
}
|
}
|
||||||
console.log(`ws: message - ${data.type}`, data.update);
|
console.log(`ws: message - ${data.type}`, data.update);
|
||||||
if ('player' in data.update) {
|
|
||||||
const player = data.update.player;
|
if ('private' in data.update && !equal(priv, data.update.private)) {
|
||||||
if (player.name !== name) {
|
const priv = data.update.private;
|
||||||
console.log(`App - setting name (via player): ${data.update.name}`);
|
if (priv.name !== name) {
|
||||||
setName(data.update.name);
|
console.log(`App - setting name (via private): ${priv.name}`);
|
||||||
|
setName(priv.name);
|
||||||
}
|
}
|
||||||
if (player.color !== color) {
|
if (priv.color !== color) {
|
||||||
console.log(`App - setting color (via player): ${data.update.color}`);
|
console.log(`App - setting color (via private): ${priv.color}`);
|
||||||
setColor(data.update.color);
|
setColor(priv.color);
|
||||||
}
|
}
|
||||||
|
setPriv(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('players' in data.update) {
|
if ('players' in data.update) {
|
||||||
setPlayers(data.update.players);
|
setPlayers(data.update.players);
|
||||||
if (color in data.update.players) {
|
|
||||||
if (player !== data.update.players[color]) {
|
|
||||||
setPlayer(data.update.players[color]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (player) {
|
|
||||||
setPlayer(undefined);
|
|
||||||
}
|
|
||||||
if (color) {
|
|
||||||
setColor(undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ('name' in data.update && data.update.name !== name) {
|
if ('name' in data.update && data.update.name !== name) {
|
||||||
console.log(`App - setting name: ${data.update.name}`);
|
console.log(`App - setting name: ${data.update.name}`);
|
||||||
@ -136,21 +128,21 @@ const Table = () => {
|
|||||||
if ('color' in data.update && data.update.color !== color) {
|
if ('color' in data.update && data.update.color !== color) {
|
||||||
console.log(`App - setting color: ${color}`);
|
console.log(`App - setting color: ${color}`);
|
||||||
setColor(data.update.color);
|
setColor(data.update.color);
|
||||||
if (players && players[data.update.color] !== player) {
|
|
||||||
setPlayer(players[data.update.color]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const sendUpdate = (update) => {
|
||||||
|
ws.send(JSON.stringify(update));
|
||||||
|
};
|
||||||
|
|
||||||
const cbResetConnection = useCallback(() => {
|
const cbResetConnection = useCallback(() => {
|
||||||
let timer = 0;
|
let timer = 0;
|
||||||
function reset() {
|
function reset() {
|
||||||
timer = 0;
|
timer = 0;
|
||||||
setConnecting(undefined);
|
setConnection(undefined);
|
||||||
};
|
};
|
||||||
return _ => {
|
return _ => {
|
||||||
if (timer) {
|
if (timer) {
|
||||||
@ -158,7 +150,7 @@ const Table = () => {
|
|||||||
}
|
}
|
||||||
timer = setTimeout(reset, 5000);
|
timer = setTimeout(reset, 5000);
|
||||||
};
|
};
|
||||||
}, [setConnecting]);
|
}, [setConnection]);
|
||||||
|
|
||||||
const resetConnection = cbResetConnection();
|
const resetConnection = cbResetConnection();
|
||||||
|
|
||||||
@ -252,7 +244,7 @@ const Table = () => {
|
|||||||
|
|
||||||
console.log(`table - bind`);
|
console.log(`table - bind`);
|
||||||
|
|
||||||
if (!ws && !connecting) {
|
if (!ws && !connection) {
|
||||||
let loc = window.location, new_uri;
|
let loc = window.location, new_uri;
|
||||||
if (loc.protocol === "https:") {
|
if (loc.protocol === "https:") {
|
||||||
new_uri = "wss";
|
new_uri = "wss";
|
||||||
@ -262,7 +254,7 @@ const Table = () => {
|
|||||||
new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${gameId}`;
|
new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${gameId}`;
|
||||||
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
||||||
setWs(new WebSocket(new_uri));
|
setWs(new WebSocket(new_uri));
|
||||||
setConnecting(undefined);
|
setConnection(undefined);
|
||||||
return unbind;
|
return unbind;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,9 +279,9 @@ const Table = () => {
|
|||||||
ws.removeEventListener('error', cbError);
|
ws.removeEventListener('error', cbError);
|
||||||
ws.removeEventListener('message', cbMessage);
|
ws.removeEventListener('message', cbMessage);
|
||||||
}
|
}
|
||||||
}, [ setWs, connecting, setConnecting, gameId, ws, refWsOpen, refWsMessage, refWsClose, refWsError ]);
|
}, [ setWs, connection, setConnection, gameId, ws, refWsOpen, refWsMessage, refWsClose, refWsError ]);
|
||||||
|
|
||||||
return <GlobalContext.Provider value={{ ws: connecting, name, gameId, peers, setPeers }}>
|
return <GlobalContext.Provider value={{ ws: connection, name, gameId, peers, setPeers }}>
|
||||||
<MediaAgent/>
|
<MediaAgent/>
|
||||||
{ /* <PingPong/> */ }
|
{ /* <PingPong/> */ }
|
||||||
<div className="Table">
|
<div className="Table">
|
||||||
@ -297,13 +289,20 @@ const Table = () => {
|
|||||||
<Trade/>
|
<Trade/>
|
||||||
<div className="Game">
|
<div className="Game">
|
||||||
<div className="Dialogs">
|
<div className="Dialogs">
|
||||||
{ error && <div className="ErrorDialog">
|
{ error && <div className="Dialog ErrorDialog">
|
||||||
<Paper className="Error">
|
<Paper className="Error">
|
||||||
<div>{ error }</div>
|
<div>{ error }</div>
|
||||||
<Button onClick={() => { setError("")}}>dismiss</Button>
|
<Button onClick={() => { setError("")}}>dismiss</Button>
|
||||||
</Paper>
|
</Paper>
|
||||||
</div> }
|
</div> }
|
||||||
{ warning && <div className="WarningDialog">
|
{ priv && priv.turnNotice && <div className="Dialog TurnNoticeDialog">
|
||||||
|
<Paper className="TurnNotice">
|
||||||
|
<div>{ priv.turnNotice }</div>
|
||||||
|
<Button onClick={() => { sendUpdate({type: 'pass'}) }}>done</Button>
|
||||||
|
<Button onClick={() => { sendUpdate({type: 'turn-notice'}) }}>dismiss</Button>
|
||||||
|
</Paper>
|
||||||
|
</div> }
|
||||||
|
{ warning && <div className="Dialog WarningDialog">
|
||||||
<Paper className="Warning">
|
<Paper className="Warning">
|
||||||
<div>{ warning }</div>
|
<div>{ warning }</div>
|
||||||
<Button onClick={() => { setWarning("")}}>dismiss</Button>
|
<Button onClick={() => { setWarning("")}}>dismiss</Button>
|
||||||
|
@ -114,7 +114,6 @@
|
|||||||
height: 50px;
|
height: 50px;
|
||||||
transform-origin: 50% 0;
|
transform-origin: 50% 0;
|
||||||
z-index: 11; /* Above Tile, below Corner */
|
z-index: 11; /* Above Tile, below Corner */
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.Road-Shape {
|
.Road-Shape {
|
||||||
@ -153,47 +152,42 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
from {
|
||||||
|
filter: brightness(90%) drop-shadow(0 0 5px black);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
filter: brightness(100%) drop-shadow(0 0 10px black);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.Board .Option {
|
.Board .Option {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
filter: brightness(100%) drop-shadow(0 0 10px black);
|
filter: brightness(150%) drop-shadow(0 0 10px black);
|
||||||
|
|
||||||
/*
|
|
||||||
opacity: 0.7;
|
|
||||||
|
|
||||||
transition-timing-function: ease-in-out;
|
transition-timing-function: ease-in-out;
|
||||||
animation-duration: 0.5s;
|
animation-duration: 0.5s;
|
||||||
animation-name: blink;
|
animation-name: blink;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-direction: alternate;
|
animation-direction: alternate;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.Tile-Shape:hover,
|
.Tile-Shape:hover,
|
||||||
.Corner-Shape:hover,
|
.Corner-Shape:hover,
|
||||||
.Road-Shape:hover {
|
.Road-Shape:hover {
|
||||||
background-color: white;
|
background-color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Board .Option .Tile-Shape,
|
.Board .Option .Tile-Shape,
|
||||||
.Board .Option .Corner-Shape,
|
.Board .Option .Corner-Shape,
|
||||||
.Board .Option .Road-Shape {
|
.Board .Option .Road-Shape {
|
||||||
background-color: rgba(255, 255, 255, 0.75);
|
background-color: rgb(185, 185, 185);
|
||||||
}
|
}
|
||||||
|
|
||||||
.Board .Option:hover {
|
|
||||||
filter: brightness(150%) drop-shadow(0 0 5px white);
|
|
||||||
}
|
|
||||||
|
|
||||||
.Board .Option:hover {
|
|
||||||
|
|
||||||
/* opacity: 1;
|
|
||||||
filter: brightness(150%) drop-shadow(0 0 2px black);
|
|
||||||
animation-play-state: paused;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.Robber .Pip-Shape {
|
.Robber .Pip-Shape {
|
||||||
top: -40px;
|
top: -40px;
|
||||||
left: -40px;
|
left: -40px;
|
||||||
@ -304,43 +298,3 @@
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
@keyframes blink {
|
|
||||||
from {
|
|
||||||
filter: brightness(90%);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
filter: brightness(150%);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
filter: brightness(150%);
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.Board .Option:hover {
|
|
||||||
|
|
||||||
/* opacity: 1;
|
|
||||||
|
|
||||||
animation-play-state: paused;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.Board .Option {
|
|
||||||
|
|
||||||
/*
|
|
||||||
opacity: 0.7;
|
|
||||||
|
|
||||||
transition-timing-function: ease-in-out;
|
|
||||||
animation-duration: 0.5s;
|
|
||||||
animation-name: blink;
|
|
||||||
animation-iteration-count: infinite;
|
|
||||||
animation-direction: alternate;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
@ -24,6 +24,8 @@ const
|
|||||||
borderImageWidth = (2 + 2/3) * tileImageWidth, /* 2.667 * .Tile.width */
|
borderImageWidth = (2 + 2/3) * tileImageWidth, /* 2.667 * .Tile.width */
|
||||||
borderImageHeight = borderImageWidth * 0.29; /* 0.29 * .Border.height */
|
borderImageHeight = borderImageWidth * 0.29; /* 0.29 * .Border.height */
|
||||||
|
|
||||||
|
let hack = undefined;
|
||||||
|
|
||||||
const Board = () => {
|
const Board = () => {
|
||||||
const { ws } = useContext(GlobalContext);
|
const { ws } = useContext(GlobalContext);
|
||||||
const board = useRef();
|
const board = useRef();
|
||||||
@ -57,6 +59,13 @@ const Board = () => {
|
|||||||
console.log(`board - render ws is ${!ws ? 'NULL' : (ws.readyState === ws.OPEN ? 'OPEN' : '!OPEN')}`);
|
console.log(`board - render ws is ${!ws ? 'NULL' : (ws.readyState === ws.OPEN ? 'OPEN' : '!OPEN')}`);
|
||||||
|
|
||||||
const onWsMessage = (event) => {
|
const onWsMessage = (event) => {
|
||||||
|
if (ws !== event.target) {
|
||||||
|
console.error(`Disconnect occur?`);
|
||||||
|
}
|
||||||
|
if (hack !== ws) {
|
||||||
|
console.error(`Setting hack`)
|
||||||
|
hack = ws;
|
||||||
|
}
|
||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case 'game-update':
|
case 'game-update':
|
||||||
@ -131,10 +140,12 @@ const Board = () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const refWs = useRef(ws);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
const refWsMessage = useRef(onWsMessage);
|
||||||
useEffect(() => { refWsMessage.current = onWsMessage; });
|
useEffect(() => { refWsMessage.current = onWsMessage; });
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ws) { return; }
|
if (!ws) { return; }
|
||||||
|
refWs.current = ws;
|
||||||
console.log('board - bind');
|
console.log('board - bind');
|
||||||
const cbMessage = e => refWsMessage.current(e);
|
const cbMessage = e => refWsMessage.current(e);
|
||||||
ws.addEventListener('message', cbMessage);
|
ws.addEventListener('message', cbMessage);
|
||||||
@ -195,7 +206,6 @@ const Board = () => {
|
|||||||
|
|
||||||
onResize();
|
onResize();
|
||||||
|
|
||||||
|
|
||||||
const Tile = ({tile}) => {
|
const Tile = ({tile}) => {
|
||||||
const onClick = (event) => {
|
const onClick = (event) => {
|
||||||
console.log(`Tile clicked: ${tile.index}`);
|
console.log(`Tile clicked: ${tile.index}`);
|
||||||
@ -214,7 +224,8 @@ const Board = () => {
|
|||||||
}}
|
}}
|
||||||
><div className="Tile-Shape"/></div>;
|
><div className="Tile-Shape"/></div>;
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
|
useRef didn't work...
|
||||||
const staticSendCallback = (type, index) => {
|
const staticSendCallback = (type, index) => {
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
type, index
|
type, index
|
||||||
@ -222,14 +233,40 @@ const Board = () => {
|
|||||||
};
|
};
|
||||||
const refStaticSendCallback = useRef(staticSendCallback);
|
const refStaticSendCallback = useRef(staticSendCallback);
|
||||||
useEffect(() => { refStaticSendCallback.current = staticSendCallback; });
|
useEffect(() => { refStaticSendCallback.current = staticSendCallback; });
|
||||||
const sendPlacement = refStaticSendCallback.current;
|
|
||||||
|
|
||||||
|
|
||||||
|
const sendPlacement = function(...) doesn't work.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* const sendPlacement = useCallabck(...) doesn't work.
|
||||||
|
*
|
||||||
|
* However it is required for dependency tracking.
|
||||||
|
*/
|
||||||
|
const sendPlacement = useCallback((type, index) => {
|
||||||
|
console.log(`board - sendPlacement - ws is ${!ws ? 'NULL' : (ws.readyState === ws.OPEN ? 'OPEN' : '!OPEN')}`);
|
||||||
|
if (ws.readyState !== ws.OPEN) {
|
||||||
|
console.error(`ws is not OPEN in sendPlacement`);
|
||||||
|
}
|
||||||
|
if (ws !== hack) {
|
||||||
|
console.error(`hack and ws are different!`);
|
||||||
|
if (refWs.current === hack) {
|
||||||
|
console.log(`refWs is correct!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refWs.current.send(JSON.stringify({
|
||||||
|
type, index
|
||||||
|
}));
|
||||||
|
}, [ws, refWs]);
|
||||||
|
|
||||||
const onRoadClicked = useCallback((road) => {
|
const onRoadClicked = useCallback((road) => {
|
||||||
console.log(`Road clicked: ${road.index}`);
|
console.log(`Road clicked: ${road.index}`);
|
||||||
sendPlacement('place-road', road.index);
|
sendPlacement('place-road', road.index);
|
||||||
}, [sendPlacement]);
|
}, [sendPlacement]);
|
||||||
|
|
||||||
const Road = ({road}) => {
|
const Road = useCallback(({road}) => {
|
||||||
return <div className="Road"
|
return <div className="Road"
|
||||||
onClick={() => { onRoadClicked(road) }}
|
onClick={() => { onRoadClicked(road) }}
|
||||||
data-index={road.index}
|
data-index={road.index}
|
||||||
@ -239,7 +276,7 @@ const Board = () => {
|
|||||||
left: `${road.left}px`
|
left: `${road.left}px`
|
||||||
}}
|
}}
|
||||||
><div className="Road-Shape"/></div>;
|
><div className="Road-Shape"/></div>;
|
||||||
};
|
}, [onRoadClicked]);
|
||||||
|
|
||||||
const onCornerClicked = useCallback((event, corner) => {
|
const onCornerClicked = useCallback((event, corner) => {
|
||||||
let type;
|
let type;
|
||||||
|
@ -103,12 +103,6 @@ const games = {};
|
|||||||
const audio = {};
|
const audio = {};
|
||||||
|
|
||||||
const processTies = (players) => {
|
const processTies = (players) => {
|
||||||
players.sort((A, B) => {
|
|
||||||
if (A.order === B.order) {
|
|
||||||
return B.orderRoll - A.orderRoll;
|
|
||||||
}
|
|
||||||
return B.order - A.order;
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Sort the players into buckets based on their
|
/* Sort the players into buckets based on their
|
||||||
* order, and their current roll. If a resulting
|
* order, and their current roll. If a resulting
|
||||||
@ -119,58 +113,61 @@ const processTies = (players) => {
|
|||||||
if (!slots[player.order]) {
|
if (!slots[player.order]) {
|
||||||
slots[player.order] = [];
|
slots[player.order] = [];
|
||||||
}
|
}
|
||||||
if (!(player.orderRoll in slots[player.order])) {
|
slots[player.order].push(player);
|
||||||
slots[player.order][player.orderRoll] = [];
|
|
||||||
}
|
|
||||||
slots[player.order][player.orderRoll].push(player);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let ties = false, order = 0;
|
let ties = false, position = 1;
|
||||||
|
const irstify = (position) => {
|
||||||
|
switch (position) {
|
||||||
|
case 1: return `1st`;
|
||||||
|
case 2: return `2nd`;
|
||||||
|
case 3: return `3rd`;
|
||||||
|
case 4: return `4th`;
|
||||||
|
default: return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(`Slots: `, slots);
|
||||||
/* Reverse from high to low */
|
/* Reverse from high to low */
|
||||||
slots.reverse().forEach((slot) => {
|
slots.reverse().forEach((slot) => {
|
||||||
slot.forEach(dice => {
|
if (slot.length !== 1) {
|
||||||
if (dice.length !== 1) {
|
ties = true;
|
||||||
ties = true;
|
slot.forEach(player => {
|
||||||
dice.forEach(player => {
|
player.orderRoll = 0; /* Ties have to be re-rolled */
|
||||||
player.orderRoll = 0;
|
player.position = irstify(position);
|
||||||
player.order = order;
|
player.orderStatus = `Tied for ${irstify(position)}`;
|
||||||
player.orderStatus = `Tied.`;
|
player.tied = true;
|
||||||
player.tied = true;
|
});
|
||||||
});
|
} else {
|
||||||
} else {
|
slot[0].tied = false;
|
||||||
dice[0].order = order;
|
slot[0].position = irstify(position);
|
||||||
dice[0].tied = false;
|
slot[0].orderStatus = `Placed in ${irstify(position)}.`;
|
||||||
dice[0].orderStatus = `Placed in ${order+1}.`;
|
}
|
||||||
}
|
position += slot.length
|
||||||
order += dice.length
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return !ties;
|
return ties;
|
||||||
}
|
}
|
||||||
|
|
||||||
const processGameOrder = (game, player, dice) => {
|
const processGameOrder = (game, player, dice) => {
|
||||||
if (player.orderRoll) {
|
if (player.orderRoll) {
|
||||||
return `You have already rolled for game order and are not in a tie.`;
|
return `You have already rolled for game order and are not in a tie.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.orderRoll = dice;
|
player.orderRoll = dice;
|
||||||
|
player.order = player.order * 6 + dice;
|
||||||
|
|
||||||
const players = [];
|
const players = [];
|
||||||
|
|
||||||
let doneRolling = true;
|
let doneRolling = true;
|
||||||
for (let key in game.players) {
|
for (let key in game.players) {
|
||||||
const tmp = game.players[key];
|
if (!game.players[key].orderRoll) {
|
||||||
if (tmp.status === 'Not active') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!tmp.orderRoll) {
|
|
||||||
doneRolling = false;
|
doneRolling = false;
|
||||||
}
|
}
|
||||||
players.push(tmp);
|
players.push(game.players[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If 'doneRolling' is FALSE then there are still players to roll */
|
/* If 'doneRolling' is FALSE then there are still players to roll */
|
||||||
if (!doneRolling || !processTies(players)) {
|
if (!doneRolling) {
|
||||||
sendUpdateToPlayers(game, {
|
sendUpdateToPlayers(game, {
|
||||||
players: getFilteredPlayers(game),
|
players: getFilteredPlayers(game),
|
||||||
chat: game.chat
|
chat: game.chat
|
||||||
@ -178,10 +175,25 @@ const processGameOrder = (game, player, dice) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
addChatMessage(game, null, `Player order set to ${players
|
/* sort updated player.order into the array */
|
||||||
.map((player, index) => {
|
players.sort((A, B) => {
|
||||||
return `${index+1}. ${player.name}`;
|
return B.order - A.order;
|
||||||
}).join(', ')}.`);
|
});
|
||||||
|
|
||||||
|
console.log(`Pre process ties: `, players);
|
||||||
|
|
||||||
|
if (processTies(players)) {
|
||||||
|
console.log(`${info}: There are ties in player rolls:`, players);
|
||||||
|
sendUpdateToPlayers(game, {
|
||||||
|
players: getFilteredPlayers(game),
|
||||||
|
chat: game.chat
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addChatMessage(game, null, `Player order set to ` +
|
||||||
|
players.map((player) => `${player.position}: ${player.name}`)
|
||||||
|
.join(', ') + `.`);
|
||||||
|
|
||||||
game.playerOrder = players.map(player => player.color);
|
game.playerOrder = players.map(player => player.color);
|
||||||
game.state = 'initial-placement';
|
game.state = 'initial-placement';
|
||||||
@ -210,18 +222,13 @@ const roll = (game, session) => {
|
|||||||
name = session.name ? session.name : "Unnamed";
|
name = session.name ? session.name : "Unnamed";
|
||||||
|
|
||||||
switch (game.state) {
|
switch (game.state) {
|
||||||
case "lobby":
|
case "lobby": /* currently not available as roll is only after color is
|
||||||
|
* set for players */
|
||||||
addChatMessage(game, session, `${name} rolled ${Math.ceil(Math.random() * 6)}.`);
|
addChatMessage(game, session, `${name} rolled ${Math.ceil(Math.random() * 6)}.`);
|
||||||
sendUpdateToPlayers(game, { chat: game.chat });
|
sendUpdateToPlayers(game, { chat: game.chat });
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case "game-order":
|
case "game-order":
|
||||||
if (!player) {
|
|
||||||
return `This player is not active!`;
|
|
||||||
}
|
|
||||||
if (player.order && player.orderRoll) {
|
|
||||||
return `Player ${name} has already rolled for player order.`;
|
|
||||||
}
|
|
||||||
game.startTime = Date.now();
|
game.startTime = Date.now();
|
||||||
const dice = Math.ceil(Math.random() * 6);
|
const dice = Math.ceil(Math.random() * 6);
|
||||||
addChatMessage(game, session, `${name} rolled ${dice}.`);
|
addChatMessage(game, session, `${name} rolled ${dice}.`);
|
||||||
@ -730,14 +737,15 @@ const adminActions = (game, action, value) => {
|
|||||||
|
|
||||||
case "pass":
|
case "pass":
|
||||||
let name = game.turn.name;
|
let name = game.turn.name;
|
||||||
const next = getNextPlayer(game, name);
|
const next = getNextPlayerSession(game, name);
|
||||||
game.turn = {
|
game.turn = {
|
||||||
name: next.player,
|
name: next.player,
|
||||||
color: next.color
|
color: next.color
|
||||||
};
|
};
|
||||||
game.turns++;
|
game.turns++;
|
||||||
|
startTurnTimer(game, next);
|
||||||
addChatMessage(game, null, `The admin skipped ${name}'s turn.`);
|
addChatMessage(game, null, `The admin skipped ${name}'s turn.`);
|
||||||
addChatMessage(game, null, `It is ${next}'s turn.`);
|
addChatMessage(game, null, `It is ${next.name}'s turn.`);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "kick":
|
case "kick":
|
||||||
@ -1065,7 +1073,7 @@ const getFirstPlayerName = (game) => {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNextPlayer = (game, name) => {
|
const getNextPlayerSession = (game, name) => {
|
||||||
let color;
|
let color;
|
||||||
for (let id in game.sessions) {
|
for (let id in game.sessions) {
|
||||||
if (game.sessions[id].name === name) {
|
if (game.sessions[id].name === name) {
|
||||||
@ -1073,25 +1081,20 @@ const getNextPlayer = (game, name) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(`current player is ${color}`);
|
|
||||||
let index = game.playerOrder.indexOf(color);
|
let index = game.playerOrder.indexOf(color);
|
||||||
console.log(`current player is ${color} ${index}`);
|
|
||||||
index = (index + 1) % game.playerOrder.length;
|
index = (index + 1) % game.playerOrder.length;
|
||||||
console.log(`current player is ${color} ${index}`);
|
|
||||||
color = game.playerOrder[index];
|
color = game.playerOrder[index];
|
||||||
console.log(`current player is ${color} ${index}`);
|
|
||||||
for (let id in game.sessions) {
|
for (let id in game.sessions) {
|
||||||
if (game.sessions[id].color === color) {
|
if (game.sessions[id].color === color) {
|
||||||
return game.sessions[id].player;
|
return game.sessions[id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(`nothing found... returning current player.`);
|
console.error(`getNextPlayerSession -- no player found!`);
|
||||||
console.log(game.players);
|
console.log(game.players);
|
||||||
|
|
||||||
return player;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPrevPlayer = (game, name) => {
|
const getPrevPlayerSession = (game, name) => {
|
||||||
let color;
|
let color;
|
||||||
for (let id in game.sessions) {
|
for (let id in game.sessions) {
|
||||||
if (game.sessions[id].name === name) {
|
if (game.sessions[id].name === name) {
|
||||||
@ -1103,10 +1106,11 @@ const getPrevPlayer = (game, name) => {
|
|||||||
index = (index - 1) % game.playerOrder.length;
|
index = (index - 1) % game.playerOrder.length;
|
||||||
for (let id in game.sessions) {
|
for (let id in game.sessions) {
|
||||||
if (game.sessions[id].color === game.playerOrder[index]) {
|
if (game.sessions[id].color === game.playerOrder[index]) {
|
||||||
return game.sessions[id].player;
|
return game.sessions[id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return player;
|
console.error(`getNextPlayerSession -- no player found!`);
|
||||||
|
console.log(game.players);
|
||||||
}
|
}
|
||||||
|
|
||||||
const processCorner = (game, color, cornerIndex, placedCorner) => {
|
const processCorner = (game, color, cornerIndex, placedCorner) => {
|
||||||
@ -1834,6 +1838,44 @@ const trade = (game, session, action, offer) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clearTimeNotice= (game, session) => {
|
||||||
|
if (!session.player.turnNotice) {
|
||||||
|
return `You have not been idle.`;
|
||||||
|
}
|
||||||
|
session.player.turnNotice = "";
|
||||||
|
sendUpdateToPlayer(game, session, {
|
||||||
|
private: session.player
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const startTurnTimer = (game, session) => {
|
||||||
|
const timeout = 30;
|
||||||
|
console.log(`${session.id}: (Re)setting turn timer for ${session.name} to ${timeout} seconds.`);
|
||||||
|
if (game.turnTimer) {
|
||||||
|
clearTimeout(game.turnTimer);
|
||||||
|
}
|
||||||
|
game.turnTimer = setTimeout(() => {
|
||||||
|
console.log(`${session.id}: Turn timer expired for ${session.name}`);
|
||||||
|
session.player.turnNotice = 'It is still your turn.';
|
||||||
|
sendUpdateToPlayer(game, session, {
|
||||||
|
private: session.player
|
||||||
|
});
|
||||||
|
resetTurnTimer(game, session);
|
||||||
|
}, timeout * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetTurnTimer = (game, session) => {
|
||||||
|
startTurnTimer(game, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
const stopTurnTimer = (game) => {
|
||||||
|
if (game.turnTimer) {
|
||||||
|
console.log(`${info}: Stopping turn timer.`);
|
||||||
|
clearTimeout(game.turnTimer);
|
||||||
|
game.turnTimer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const shuffle = (game, session) => {
|
const shuffle = (game, session) => {
|
||||||
const name = session.name;
|
const name = session.name;
|
||||||
|
|
||||||
@ -1861,17 +1903,21 @@ const pass = (game, session) => {
|
|||||||
return `Robber is in action. Turn can not stop until all Robber tasks are resolved.`;
|
return `Robber is in action. Turn can not stop until all Robber tasks are resolved.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const next = getNextPlayer(game, session.name);
|
const next = getNextPlayerSession(game, session.name);
|
||||||
session.player.totalTime += Date.now() - session.player.turnStart;
|
session.player.totalTime += Date.now() - session.player.turnStart;
|
||||||
|
session.player.turnNotice = "";
|
||||||
game.turn = {
|
game.turn = {
|
||||||
name: next.name,
|
name: next.name,
|
||||||
color: next.color
|
color: next.color
|
||||||
};
|
};
|
||||||
next.turnStart = Date.now();
|
next.turnStart = Date.now();
|
||||||
|
game.turnTimer = startTurnTimer(game, next);
|
||||||
game.turns++;
|
game.turns++;
|
||||||
addActivity(game, session, `${name} passed their turn.`);
|
addActivity(game, session, `${name} passed their turn.`);
|
||||||
addChatMessage(game, null, `It is ${next.name}'s turn.`);
|
addChatMessage(game, null, `It is ${next.name}'s turn.`);
|
||||||
|
sendUpdateToPlayer(game, session, {
|
||||||
|
private: session.player
|
||||||
|
});
|
||||||
sendUpdateToPlayers(game, {
|
sendUpdateToPlayers(game, {
|
||||||
turns: game.turns,
|
turns: game.turns,
|
||||||
turn: game.turn,
|
turn: game.turn,
|
||||||
@ -2406,11 +2452,9 @@ const placeRoad = (game, session, index) => {
|
|||||||
delete game.direction;
|
delete game.direction;
|
||||||
} else {
|
} else {
|
||||||
if (game.direction === 'forward') {
|
if (game.direction === 'forward') {
|
||||||
next = getNextPlayer(game, session.name);
|
next = getNextPlayerSession(game, session.name);
|
||||||
console.log(`advance from ${session.name} to `, next);
|
|
||||||
} else {
|
} else {
|
||||||
next = getPrevPlayer(game, session.name);
|
next = getPrevPlayerSession(game, session.name);
|
||||||
console.log(`devance from ${session.name} to `, next);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (next) {
|
if (next) {
|
||||||
@ -2418,6 +2462,7 @@ const placeRoad = (game, session, index) => {
|
|||||||
name: next.name,
|
name: next.name,
|
||||||
color: next.color
|
color: next.color
|
||||||
};
|
};
|
||||||
|
startTurnTimer(game, next);
|
||||||
setForSettlementPlacement(game, getValidCorners(game));
|
setForSettlementPlacement(game, getValidCorners(game));
|
||||||
calculateRoadLengths(game, session);
|
calculateRoadLengths(game, session);
|
||||||
addChatMessage(game, null, `It is ${next.name}'s turn to place a settlement.`);
|
addChatMessage(game, null, `It is ${next.name}'s turn to place a settlement.`);
|
||||||
@ -2863,6 +2908,14 @@ const setGameState = (game, session, state) => {
|
|||||||
if (active < 2) {
|
if (active < 2) {
|
||||||
return `You need at least two players to start the game.`;
|
return `You need at least two players to start the game.`;
|
||||||
}
|
}
|
||||||
|
/* Delete any non-played colors from the player map; reduces all
|
||||||
|
* code that would otherwise have to filter out players by checking
|
||||||
|
* the 'Not active' state of player.status */
|
||||||
|
for (let key in game.players) {
|
||||||
|
if (game.players[key].status !== 'Active') {
|
||||||
|
delete game.players[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
addChatMessage(game, null, `${session.name} requested to start the game.`);
|
addChatMessage(game, null, `${session.name} requested to start the game.`);
|
||||||
game.state = state;
|
game.state = state;
|
||||||
|
|
||||||
@ -2968,12 +3021,14 @@ const saveGame = async (game) => {
|
|||||||
if (reduced.keepAlive) {
|
if (reduced.keepAlive) {
|
||||||
delete reduced.keepAlive;
|
delete reduced.keepAlive;
|
||||||
}
|
}
|
||||||
|
|
||||||
reducedGame.sessions[id] = reduced;
|
reducedGame.sessions[id] = reduced;
|
||||||
|
|
||||||
/* Do not send session-id as those are secrets */
|
/* Do not send session-id as those are secrets */
|
||||||
reducedSessions.push(reduced);
|
reducedSessions.push(reduced);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete reducedGame.turnTimer;
|
||||||
delete reducedGame.unselected;
|
delete reducedGame.unselected;
|
||||||
|
|
||||||
/* Save per turn while debugging... */
|
/* Save per turn while debugging... */
|
||||||
@ -3062,15 +3117,15 @@ const sendUpdateToPlayers = async (game, update) => {
|
|||||||
for (let key in game.sessions) {
|
for (let key in game.sessions) {
|
||||||
const _session = game.sessions[key];
|
const _session = game.sessions[key];
|
||||||
if (!_session.ws) {
|
if (!_session.ws) {
|
||||||
continue;
|
console.log(`${_session.id}: -> sendUpdateToPlayers: Currently no connection.`);
|
||||||
|
} else {
|
||||||
|
_session.ws.send(message);
|
||||||
}
|
}
|
||||||
_session.ws.send(message);
|
|
||||||
}
|
}
|
||||||
await saveGame(game);
|
await saveGame(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendUpdateToPlayer = async (game, session, update) => {
|
const sendUpdateToPlayer = async (game, session, update) => {
|
||||||
|
|
||||||
/* Ensure clearing of a field actually gets sent by setting
|
/* Ensure clearing of a field actually gets sent by setting
|
||||||
* undefined to 'false'
|
* undefined to 'false'
|
||||||
*/
|
*/
|
||||||
@ -3093,7 +3148,12 @@ const sendUpdateToPlayer = async (game, session, update) => {
|
|||||||
type: 'game-update',
|
type: 'game-update',
|
||||||
update
|
update
|
||||||
});
|
});
|
||||||
session.ws.send(message);
|
|
||||||
|
if (!session.ws) {
|
||||||
|
console.log(`${session.id}: -> sendUpdateToPlayer: Currently no connection.`);
|
||||||
|
} else {
|
||||||
|
session.ws.send(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFilteredUnselected = (game) => {
|
const getFilteredUnselected = (game) => {
|
||||||
@ -3216,6 +3276,7 @@ const calculatePoints = (game, update) => {
|
|||||||
game.winner = update.winner;
|
game.winner = update.winner;
|
||||||
game.state = 'winner';
|
game.state = 'winner';
|
||||||
game.waiting = [];
|
game.waiting = [];
|
||||||
|
stopTurnTimer(game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3463,7 +3524,8 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
case 'startTime':
|
case 'startTime':
|
||||||
case 'state':
|
case 'state':
|
||||||
case 'turns':
|
case 'turns':
|
||||||
update[field] = game[field];
|
case 'winner':
|
||||||
|
update[field] = game[field];
|
||||||
break;
|
break;
|
||||||
case 'name':
|
case 'name':
|
||||||
update.name = session.name;
|
update.name = session.name;
|
||||||
@ -3509,13 +3571,6 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
sendUpdateToPlayers(game, { chat: game.chat });
|
sendUpdateToPlayers(game, { chat: game.chat });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'roll':
|
|
||||||
console.log(`${short}: <- roll:${getName(session)}`);
|
|
||||||
warning = roll(game, session);
|
|
||||||
if (warning) {
|
|
||||||
sendWarning(session, warning);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
processed = false;
|
processed = false;
|
||||||
break;
|
break;
|
||||||
@ -3534,7 +3589,15 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processed = true;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
|
case 'roll':
|
||||||
|
console.log(`${short}: <- roll:${getName(session)}`);
|
||||||
|
warning = roll(game, session);
|
||||||
|
if (warning) {
|
||||||
|
sendWarning(session, warning);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'shuffle':
|
case 'shuffle':
|
||||||
console.log(`${short}: <- shuffle:${getName(session)}`);
|
console.log(`${short}: <- shuffle:${getName(session)}`);
|
||||||
warning = shuffle(game, session);
|
warning = shuffle(game, session);
|
||||||
@ -3634,7 +3697,7 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'trade':
|
case 'trade':
|
||||||
console.log(`${short}: <- trade:${getName(session)} - ${data.action} - `, data.offer);
|
console.log(`${short}: <- trade:${getName(session)} - ${data.action} - `, data.offer ? data.offer : 'no trade yet');
|
||||||
warning = trade(game, session, data.action, data.offer);
|
warning = trade(game, session, data.action, data.offer);
|
||||||
if (warning) {
|
if (warning) {
|
||||||
sendWarning(session, warning);
|
sendWarning(session, warning);
|
||||||
@ -3658,6 +3721,13 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'turn-notice':
|
||||||
|
console.log(`${short}: <- turn-notice:${getName(session)}`);
|
||||||
|
warning = clearTimeNotice(game, session);
|
||||||
|
if (warning) {
|
||||||
|
sendWarning(session, warning);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'goto-lobby':
|
case 'goto-lobby':
|
||||||
console.log(`${short}: <- goto-lobby:${getName(session)}`);
|
console.log(`${short}: <- goto-lobby:${getName(session)}`);
|
||||||
warning = gotoLobby(game, session);
|
warning = gotoLobby(game, session);
|
||||||
@ -3667,10 +3737,16 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn(`Unsupported request: ${data.type}`);
|
console.warn(`Unsupported request: ${data.type}`);
|
||||||
|
processed = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (processed && session.color === game.turn.color) {
|
||||||
|
resetTurnTimer(game, session);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/* This will result in the node tick moving forward; if we haven't already
|
/* This will result in the node tick moving forward; if we haven't already
|
||||||
* setup the event handlers, a 'message' could come through prior to this
|
* setup the event handlers, a 'message' could come through prior to this
|
||||||
* completing */
|
* completing */
|
||||||
@ -3694,6 +3770,11 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the current turn player just rejoined, set their turn timer */
|
||||||
|
if (game.turn && game.turn.color === session.color) {
|
||||||
|
resetTurnTimer(game, session);
|
||||||
|
}
|
||||||
|
|
||||||
if (session.name) {
|
if (session.name) {
|
||||||
if (session.color) {
|
if (session.color) {
|
||||||
addChatMessage(game, null, `${session.name} has reconnected to the game.`);
|
addChatMessage(game, null, `${session.name} has reconnected to the game.`);
|
||||||
@ -3774,6 +3855,9 @@ const getFilteredGameForPlayer = (game, session) => {
|
|||||||
/* Strip out data that should not be shared with players */
|
/* Strip out data that should not be shared with players */
|
||||||
delete reducedGame.developmentCards;
|
delete reducedGame.developmentCards;
|
||||||
|
|
||||||
|
/* Delete the game timer */
|
||||||
|
delete reducedGame.turnTimer;
|
||||||
|
|
||||||
reducedGame.unselected = getFilteredUnselected(game);
|
reducedGame.unselected = getFilteredUnselected(game);
|
||||||
|
|
||||||
return Object.assign(reducedGame, {
|
return Object.assign(reducedGame, {
|
||||||
@ -3840,6 +3924,8 @@ const resetGame = (game) => {
|
|||||||
active: 0
|
active: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
stopTurnTimer(game);
|
||||||
|
|
||||||
/* Populate the game corner and road placement data as cleared */
|
/* Populate the game corner and road placement data as cleared */
|
||||||
for (let i = 0; i < layout.corners.length; i++) {
|
for (let i = 0; i < layout.corners.length; i++) {
|
||||||
game.placements.corners[i] = {
|
game.placements.corners[i] = {
|
||||||
@ -3885,10 +3971,14 @@ const resetGame = (game) => {
|
|||||||
|
|
||||||
shuffleArray(game.developmentCards);
|
shuffleArray(game.developmentCards);
|
||||||
|
|
||||||
/* Reset all player data */
|
/* Reset all player data, and add in any missing colors */
|
||||||
for (let color in game.players) {
|
[ 'R', 'B', 'W', 'O' ].forEach(color => {
|
||||||
clearPlayer(game.players[color]);
|
if (color in game.players) {
|
||||||
}
|
clearPlayer(game.players[color]);
|
||||||
|
} else {
|
||||||
|
game.players.color = newPlayer(color);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* Ensure sessions are connected to player objects */
|
/* Ensure sessions are connected to player objects */
|
||||||
for (let key in game.sessions) {
|
for (let key in game.sessions) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user