1
0

Board pieces now show up

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-03-13 04:10:50 -07:00
parent 593267ec49
commit 8fc3f1edcd
8 changed files with 56 additions and 385 deletions

View File

@ -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 {

View File

@ -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/> }

View File

@ -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})`;
}

View File

@ -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}/>);
@ -46,4 +48,4 @@ const BoardPieces = ({ player, onClick, color }) => {
);
};
export {BoardPieces};
export { BoardPieces };

View File

@ -1,40 +1,51 @@
import React from "react";
import "./Placard.css";
import { assetsPath } from './Common.js';
import React, { useContext, useEffect, useState } from "react";
const Placard = ({table, type, active, disabled, count}) => {
const dismissClicked = (event) => {
table.setState({ buildActive: false });
import { assetsPath } from './Common.js';
import { GlobalContext } from "./GlobalContext.js";
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={{

View File

@ -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;

View File

@ -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;

View File

@ -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
});