175 lines
5.1 KiB
JavaScript
175 lines
5.1 KiB
JavaScript
import React, { useContext, useState, useMemo, useRef, useEffect } from "react";
|
|
import equal from "fast-deep-equal";
|
|
|
|
import "./PlayersStatus.css";
|
|
import { BoardPieces } from './BoardPieces.js';
|
|
import { Resource } from './Resource.js';
|
|
import { PlayerColor } from './PlayerColor.js';
|
|
import { Placard } from './Placard.js';
|
|
import { GlobalContext } from './GlobalContext.js';
|
|
|
|
const Player = ({ player, onClick, reverse, color,
|
|
largestArmy, isSelf, longestRoad }) => {
|
|
if (!player) {
|
|
return <></>;
|
|
}
|
|
|
|
const developmentCards = player.unplayed
|
|
? <Resource label={true} type={'progress-back'}
|
|
count={player.unplayed} disabled/>
|
|
: undefined;
|
|
const resourceCards = player.resources
|
|
? <Resource label={true} type={'resource-back'}
|
|
count={player.resources} disabled/>
|
|
: undefined;
|
|
const armyCards = player.army
|
|
? <Resource label={true} type={'army-1'} count={player.army} disabled/>
|
|
: undefined;
|
|
let points = <></>;
|
|
if (player.points && reverse) {
|
|
points = <><b>{player.points}</b><Resource type={'progress-back'}
|
|
count={player.points} disabled/></>;
|
|
} else if (player.points) {
|
|
points = <><Resource type={'progress-back'} count={player.points}
|
|
disabled/><b>{player.points}</b></>;
|
|
}
|
|
|
|
const longestRoadPlacard = longestRoad && longestRoad === color ?
|
|
<Placard
|
|
disabled
|
|
active={false}
|
|
type='longest-road'
|
|
count={player.longestRoad}
|
|
/> : undefined;
|
|
|
|
const largestArmyPlacard = largestArmy && largestArmy === color ?
|
|
<Placard
|
|
disabled
|
|
active={false}
|
|
type='largest-army'
|
|
count={player.army}
|
|
/> : undefined;
|
|
|
|
return <div className="Player">
|
|
<div className="Who">
|
|
<PlayerColor color={color}/>{player.name}
|
|
</div>
|
|
<div className="What">
|
|
{ isSelf &&
|
|
<div className="LongestRoad">
|
|
Longest road: {player.longestRoad ? player.longestRoad : 0}
|
|
</div>
|
|
}
|
|
<div className="Points">{points}</div>
|
|
{ (largestArmy || longestRoad || armyCards || resourceCards || developmentCards) && <>
|
|
<div className="Has">
|
|
{ !reverse && <>
|
|
{ largestArmyPlacard }
|
|
{ longestRoadPlacard }
|
|
{ !largestArmyPlacard && armyCards }
|
|
{ developmentCards }
|
|
{ resourceCards }
|
|
</> }
|
|
{ reverse && <>
|
|
{ resourceCards }
|
|
{ developmentCards }
|
|
{ !largestArmyPlacard && armyCards }
|
|
{ longestRoadPlacard }
|
|
{ largestArmyPlacard }
|
|
</> }
|
|
</div>
|
|
</> }
|
|
</div>
|
|
<div className={`${onClick ? 'Normal' : 'Shrunken'}`}>
|
|
<BoardPieces onClick={onClick} player={player}/>
|
|
</div>
|
|
</div>
|
|
};
|
|
|
|
const PlayersStatus = ({ active }) => {
|
|
const { ws } = useContext(GlobalContext);
|
|
const [players, setPlayers] = useState(undefined);
|
|
const [color, setColor] = useState(undefined);
|
|
const [largestArmy, setLargestArmy] = useState(undefined);
|
|
const [longestRoad, setLongestRoad] = useState(undefined);
|
|
const fields = useMemo(() => [
|
|
'players', 'color', 'longestRoad', 'largestArmy'
|
|
], []);
|
|
const onWsMessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
switch (data.type) {
|
|
case 'game-update':
|
|
console.log(`players-status - game-update: `, data.update);
|
|
if ('players' in data.update && !equal(players, data.update.players)) {
|
|
setPlayers(data.update.players);
|
|
}
|
|
if ('color' in data.update && data.update.color !== color) {
|
|
setColor(data.update.color);
|
|
}
|
|
if ('longestRoad' in data.update && data.update.longestRoad !== longestRoad) {
|
|
setLongestRoad(data.update.longestRoad);
|
|
}
|
|
if ('largestArmy' in data.update && data.update.largestArmy !== largestArmy) {
|
|
setLargestArmy(data.update.largestArmy);
|
|
}
|
|
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]);
|
|
|
|
if (!players) {
|
|
return <></>;
|
|
}
|
|
|
|
const buildItem = () => {
|
|
console.log(`player-status - build-item`);
|
|
}
|
|
|
|
let elements;
|
|
if (active) {
|
|
elements = <Player
|
|
player={players[color]}
|
|
onClick={buildItem}
|
|
reverse
|
|
largestArmy={largestArmy}
|
|
longestRoad={longestRoad}
|
|
isSelf={active}
|
|
key={`PlayerStatus-${color}`}
|
|
color={color}/>;
|
|
} else {
|
|
elements = Object.getOwnPropertyNames(players)
|
|
.filter(key => color !== key)
|
|
.map(key => {
|
|
return <Player
|
|
player={players[key]}
|
|
largestArmy={largestArmy}
|
|
longestRoad={longestRoad}
|
|
key={`PlayerStatus-${key}}`}
|
|
color={key}/>;
|
|
});
|
|
}
|
|
|
|
return (
|
|
<div className={`PlayersStatus ${active ? 'ActivePlayer' : ''}`}>
|
|
{ elements }
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export { PlayersStatus }; |