Board pieces now show up
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
593267ec49
commit
8fc3f1edcd
@ -81,6 +81,7 @@ body {
|
||||
display: flex;
|
||||
position: relative;
|
||||
height: 11rem;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.Table .Sidebar {
|
||||
@ -90,11 +91,13 @@ body {
|
||||
width: 30rem;
|
||||
max-width: 30rem;
|
||||
overflow: hidden;
|
||||
z-index: 5000;
|
||||
}
|
||||
|
||||
.Table .Board {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
z-index: 500;
|
||||
}
|
||||
|
||||
.Table .Sidebar .Chat {
|
||||
|
@ -21,6 +21,7 @@ import { GameOrder } from "./GameOrder.js";
|
||||
import { Activities } from "./Activities.js";
|
||||
import { SelectPlayer } from "./SelectPlayer.js";
|
||||
import { PlayersStatus } from "./PlayersStatus.js";
|
||||
import { Hand } from "./Hand.js";
|
||||
|
||||
import history from "./history.js";
|
||||
import "./App.css";
|
||||
@ -299,6 +300,7 @@ const Table = () => {
|
||||
<Board/>
|
||||
<PlayersStatus/>
|
||||
<PlayersStatus active={true}/>
|
||||
<Hand/>
|
||||
{ /* state === 'winner' &&
|
||||
<Winner color={winner}/>
|
||||
}
|
||||
@ -315,8 +317,6 @@ const Table = () => {
|
||||
{ isTurn && turn && turn.actions && game.turn.actions.indexOf('select-resources') !== -1 &&
|
||||
<ChooseCard type={turn.active}/>
|
||||
*/ }
|
||||
|
||||
<div className="Hand">todo: player's hand</div>
|
||||
</div>
|
||||
<div className="Sidebar">
|
||||
{ name !== "" && <PlayerList/> }
|
||||
|
@ -148,7 +148,6 @@ const Board = () => {
|
||||
}));
|
||||
}, [ws, fields]);
|
||||
|
||||
|
||||
const onResize = debounce(() => {
|
||||
if (!board.current) {
|
||||
return;
|
||||
@ -159,7 +158,7 @@ const Board = () => {
|
||||
* so the board fills the Board
|
||||
*
|
||||
* The board is H tall, and H * hexRatio wide */
|
||||
const width = board.current.innerWidth,
|
||||
const width = board.current.offsetWidth,
|
||||
height = board.current.offsetHeight;
|
||||
let _transform;
|
||||
if (height * hexRatio > width) {
|
||||
@ -170,7 +169,7 @@ const Board = () => {
|
||||
|
||||
const boardBox = board.current.querySelector('.BoardBox');
|
||||
if (boardBox) {
|
||||
console.log(`Setting transofrm scale to ${_transform}`);
|
||||
console.log(`board - setting transform scale to ${_transform}`);
|
||||
if (boardBox.style.transform !== `scale(${_transform})`) {
|
||||
boardBox.style.transform = `scale(${_transform})`;
|
||||
}
|
||||
|
@ -19,11 +19,13 @@ const City = ({ color, onClick }) => {
|
||||
return <div className="City" onClick={() => onClick('city')}><div className={['Shape', classes[color]].join(' ')}/></div>;
|
||||
}
|
||||
|
||||
const BoardPieces = ({ player, onClick, color }) => {
|
||||
const BoardPieces = ({ player, onClick }) => {
|
||||
if (!player) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const color = player.color;
|
||||
|
||||
const roads = [];
|
||||
for (let i = 0; i < player.roads; i++) {
|
||||
roads.push(<Road onClick={onClick} key={`road-${i}`} color={color}/>);
|
||||
|
@ -1,40 +1,51 @@
|
||||
import React from "react";
|
||||
import "./Placard.css";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
|
||||
import { assetsPath } from './Common.js';
|
||||
import { GlobalContext } from "./GlobalContext.js";
|
||||
|
||||
const Placard = ({table, type, active, disabled, count}) => {
|
||||
const dismissClicked = (event) => {
|
||||
table.setState({ buildActive: false });
|
||||
import "./Placard.css";
|
||||
|
||||
const Placard = ({type, disabled, count}) => {
|
||||
const { ws } = useContext(GlobalContext);
|
||||
const [active, setActive] = useState(false);
|
||||
|
||||
const dismissClicked = () => {
|
||||
setActive(false);
|
||||
}
|
||||
|
||||
const buildClicked = (event) => {
|
||||
if (!type.match(/^l.*/)) {
|
||||
if (!table.state.buildActive) {
|
||||
table.setState({ buildActive: true });
|
||||
const buildClicked = () => {
|
||||
if (!type.match(/^l.*/)) { /* longest / largest ... */
|
||||
if (!active) {
|
||||
setActive(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const roadClicked = (event) => {
|
||||
table.buyRoad();
|
||||
table.setState({ buildActive: false });
|
||||
const roadClicked = () => {
|
||||
ws.send(JSON.stringify({ type: 'buy-road'}));
|
||||
setActive(false);
|
||||
};
|
||||
|
||||
const settlementClicked = (event) => {
|
||||
table.buySettlement();
|
||||
table.setState({ buildActive: false });
|
||||
const settlementClicked = () => {
|
||||
ws.send(JSON.stringify({ type: 'buy-settlement'}));
|
||||
setActive(false);
|
||||
};
|
||||
|
||||
const cityClicked = (event) => {
|
||||
table.buyCity();
|
||||
table.setState({ buildActive: false });
|
||||
const cityClicked = () => {
|
||||
ws.send(JSON.stringify({ type: 'buy-city'}));
|
||||
setActive(false);
|
||||
};
|
||||
|
||||
const developmentClicked = (event) => {
|
||||
table.buyDevelopment();
|
||||
table.setState({ buildActive: false });
|
||||
const developmentClicked = () => {
|
||||
ws.send(JSON.stringify({ type: 'buy-development'}));
|
||||
setActive(false);
|
||||
};
|
||||
|
||||
if (type === 'B') { type = 'blue'; }
|
||||
else if (type === 'O') { type = 'orange'; }
|
||||
else if (type === 'R') { type = 'red'; }
|
||||
else if (type === 'W') { type = 'white'; }
|
||||
|
||||
let buttons;
|
||||
if (!disabled && active) {
|
||||
switch (type) {
|
||||
@ -59,7 +70,7 @@ const Placard = ({table, type, active, disabled, count}) => {
|
||||
|
||||
if (!disabled) {
|
||||
return <div className={`Placard${active ? ' Selected' : ''}`}
|
||||
onClick={table ? buildClicked : undefined}
|
||||
onClick={buildClicked}
|
||||
disabled={disabled}
|
||||
data-type={type}
|
||||
style={{
|
||||
|
@ -10,7 +10,7 @@
|
||||
}
|
||||
|
||||
.PlayersStatus.ActivePlayer {
|
||||
right: 30rem;
|
||||
right: 0;
|
||||
bottom: 11rem; /* 1rem over top of Resource cards in hand */
|
||||
align-items: flex-end;
|
||||
pointer-events: all;
|
||||
|
@ -1,20 +1,3 @@
|
||||
.Table {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
align-self: stretch;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
min-height: 100%;
|
||||
justify-content: space-between; /* left-justify 'board', right-justify 'game' */
|
||||
background-image: url("./assets/tabletop.png");
|
||||
}
|
||||
|
||||
.Table .Chat {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 30rem;
|
||||
}
|
||||
|
||||
.Loading {
|
||||
position: absolute;
|
||||
@ -55,149 +38,12 @@
|
||||
height: 10.5rem;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.SelectPlayer {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 30rem;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
|
||||
.Display {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.Table .Cards {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
text-align: right;
|
||||
vertical-align: bottom;
|
||||
padding: 0.5em;
|
||||
box-sizing: border-box;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.Stack {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.Stack:not(:first-child) {
|
||||
margin-left: -3.5em;
|
||||
transition: margin-left 1s ease-in-out 0.25s;
|
||||
}
|
||||
|
||||
.Stack > * {
|
||||
transition: margin-left 1s ease-in-out 0.25s, margin-right 1s ease-in-out 0.25s;
|
||||
}
|
||||
|
||||
.Stack > *:not(:first-child) {
|
||||
margin-left: -4em;
|
||||
}
|
||||
|
||||
.Hand {
|
||||
display: flex;
|
||||
min-height: calc(7.2em + 0.5em);
|
||||
justify-items: space-between;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.Placard:hover {
|
||||
filter: brightness(105%);
|
||||
@ -212,42 +58,6 @@
|
||||
top: -1em;
|
||||
}
|
||||
|
||||
.Game {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
max-height: 100vh;
|
||||
overflow: hidden;
|
||||
max-width: 30rem;
|
||||
z-index: 100;
|
||||
padding: 0.5em;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.Game > * {
|
||||
/* for Firefox */
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.Game > *:not(:last-child) {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.Game.lobby {
|
||||
}
|
||||
|
||||
.Development {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 4.9em;
|
||||
height: 7.2em;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
margin: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.Action {
|
||||
display: flex;
|
||||
|
@ -456,6 +456,12 @@ const getSession = (game, reqSession) => {
|
||||
}
|
||||
|
||||
const session = game.sessions[id];
|
||||
session.lastActive = Date.now();
|
||||
session.live = true;
|
||||
if (session.player) {
|
||||
session.player.live = true;
|
||||
session.player.lastActive = session.lastActive;
|
||||
}
|
||||
|
||||
/* Expire old unused sessions */
|
||||
for (let _id in game.sessions) {
|
||||
@ -477,13 +483,6 @@ const getSession = (game, reqSession) => {
|
||||
}
|
||||
}
|
||||
|
||||
session.lastActive = Date.now();
|
||||
session.live = true;
|
||||
if (session.player) {
|
||||
session.player.live = true;
|
||||
session.player.lastActive = session.lastActive;
|
||||
}
|
||||
|
||||
return game.sessions[id];
|
||||
};
|
||||
|
||||
@ -875,7 +874,7 @@ const setPlayerName = (game, session, name) => {
|
||||
name: session.name,
|
||||
color: session.color,
|
||||
live: session.live,
|
||||
player: session.player
|
||||
private: session.player
|
||||
});
|
||||
sendUpdateToPlayers(game, {
|
||||
players: game.players,
|
||||
@ -954,7 +953,7 @@ const setPlayerColor = (game, session, color) => {
|
||||
name: session.name,
|
||||
color: undefined,
|
||||
live: session.live,
|
||||
player: session.player
|
||||
private: session.player
|
||||
});
|
||||
sendUpdateToPlayers(game, {
|
||||
active: game.active,
|
||||
@ -1007,7 +1006,7 @@ const setPlayerColor = (game, session, color) => {
|
||||
name: session.name,
|
||||
color: session.color,
|
||||
live: session.live,
|
||||
player: session.player
|
||||
private: session.player
|
||||
});
|
||||
sendUpdateToPlayers(game, update);
|
||||
};
|
||||
@ -3499,159 +3498,6 @@ const debugChat = (game, preamble) => {
|
||||
}
|
||||
}
|
||||
|
||||
const sendGameToSession = (session, reducedSessions, game, reducedGame, error, res) => {
|
||||
const player = session.player ? session.player : undefined;
|
||||
|
||||
/* Strip out data that should not be shared with players */
|
||||
delete reducedGame.developmentCards;
|
||||
|
||||
const playerGame = Object.assign({}, reducedGame, {
|
||||
timestamp: Date.now(),
|
||||
status: error ? error : "success",
|
||||
name: session.name,
|
||||
color: session.color,
|
||||
order: (session.color in game.players) ? game.players[session.color].order : 0,
|
||||
player: player,
|
||||
sessions: reducedSessions,
|
||||
layout: layout
|
||||
});
|
||||
|
||||
if (!res) {
|
||||
if (!error) {
|
||||
if (!session.ws) {
|
||||
console.error(`No WebSocket connection to ${session.name}`);
|
||||
} else {
|
||||
console.log(`Sending update to ${session.id}:${session.name ? session.name : 'Unnamed'}`);
|
||||
sendUpdateToPlayer(session, playerGame);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(`Returning update to ${session.name ? session.name : 'Unnamed'}`);
|
||||
res.status(200).send(playerGame);
|
||||
}
|
||||
}
|
||||
|
||||
const sendGame = async (req, res, game, error, wsUpdate) => {
|
||||
|
||||
/* Update the session lastActive clock */
|
||||
let session;
|
||||
if (req.session) {
|
||||
session = getSession(game, req.session);
|
||||
session.lastActive = Date.now();
|
||||
if (session.player) {
|
||||
session.player.lastActive = session.lastActive;
|
||||
}
|
||||
} else {
|
||||
session = {
|
||||
name: "command line"
|
||||
};
|
||||
}
|
||||
|
||||
/* Calculate points and determine if there is a winner */
|
||||
for (let key in game.players) {
|
||||
const player = game.players[key];
|
||||
if (player.status === 'Not active') {
|
||||
continue;
|
||||
}
|
||||
player.points = 0;
|
||||
if (key === game.longestRoad) {
|
||||
player.points += 2;
|
||||
}
|
||||
if (key === game.largestArmy) {
|
||||
player.points += 2;
|
||||
}
|
||||
player.points += MAX_SETTLEMENTS - player.settlements;
|
||||
player.points += 2 * (MAX_CITIES - player.cities);
|
||||
|
||||
player.unplayed = 0;
|
||||
player.potential = 0;
|
||||
player.development.forEach(card => {
|
||||
if (card.type === 'vp') {
|
||||
if (card.played) {
|
||||
player.points++;
|
||||
} else {
|
||||
player.potential++;
|
||||
}
|
||||
}
|
||||
if (!card.played) {
|
||||
player.unplayed++;
|
||||
}
|
||||
});
|
||||
|
||||
if (!game.winner && (player.points >= 10 && session.color === key)) {
|
||||
addChatMessage(game, null, `${player.name} won the game with ${player.points} victory points!`);
|
||||
game.winner = key;
|
||||
game.state = 'winner';
|
||||
delete game.turn.roll;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the game isn't in a win state, do not share development card information
|
||||
* with other players */
|
||||
if (game.state !== 'winner') {
|
||||
for (let key in game.players) {
|
||||
const player = game.players[key];
|
||||
if (player.status === 'Not active') {
|
||||
continue;
|
||||
}
|
||||
delete player.potential;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shallow copy game, filling its sessions with a shallow copy of sessions so we can then
|
||||
* delete the player field from them */
|
||||
const reducedGame = Object.assign({}, game, { sessions: {} }),
|
||||
reducedSessions = [];
|
||||
|
||||
for (let id in game.sessions) {
|
||||
const reduced = Object.assign({}, game.sessions[id]);
|
||||
if (reduced.player) {
|
||||
delete reduced.player;
|
||||
}
|
||||
if (reduced.ws) {
|
||||
delete reduced.ws;
|
||||
}
|
||||
if (reduced.keepAlive) {
|
||||
delete reduced.keepAlive;
|
||||
}
|
||||
reducedGame.sessions[id] = reduced;
|
||||
|
||||
/* Do not send session-id as those are secrets */
|
||||
reducedSessions.push(reduced);
|
||||
}
|
||||
|
||||
if (!wsUpdate) {
|
||||
/* Save per turn while debugging... */
|
||||
await writeFile(`games/${game.id}.${game.turns}`, JSON.stringify(reducedGame, null, 2))
|
||||
.catch((error) => {
|
||||
console.error(`Unable to write to games/${game.id}`);
|
||||
console.error(error);
|
||||
});
|
||||
await writeFile(`games/${game.id}`, JSON.stringify(reducedGame, null, 2))
|
||||
.catch((error) => {
|
||||
console.error(`Unable to write to games/${game.id}`);
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
if (wsUpdate) {
|
||||
/* This is a one-shot request from a client to send the game-update over WebSocket */
|
||||
sendGameToSession(session, reducedSessions, game, reducedGame);
|
||||
} else {
|
||||
for (let id in game.sessions) {
|
||||
const target = game.sessions[id], useWS = target !== session;
|
||||
if (useWS) {
|
||||
if (!error) {
|
||||
sendGameToSession(target, reducedSessions, game, reducedGame);
|
||||
}
|
||||
} else {
|
||||
sendGameToSession(target, reducedSessions, game, reducedGame, error, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const getFilteredGameForPlayer = (game, session) => {
|
||||
/* Calculate points and determine if there is a winner */
|
||||
for (let key in game.players) {
|
||||
@ -3740,7 +3586,7 @@ const getFilteredGameForPlayer = (game, session) => {
|
||||
name: session.name,
|
||||
color: session.color,
|
||||
order: (session.color in game.players) ? game.players[session.color].order : 0,
|
||||
player: player,
|
||||
private: player,
|
||||
sessions: reducedSessions,
|
||||
layout: layout
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user