241 lines
6.5 KiB
TypeScript
241 lines
6.5 KiB
TypeScript
import React, { useEffect, useContext, useMemo, useRef, useState, useCallback } from "react";
|
|
import equal from "fast-deep-equal";
|
|
|
|
import Paper from "@mui/material/Paper";
|
|
import Button from "@mui/material/Button";
|
|
|
|
import "./ViewCard.css";
|
|
import { Resource } from "./Resource";
|
|
import { GlobalContext } from "./GlobalContext";
|
|
|
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
|
|
interface ViewCardProps {
|
|
cardActive: any;
|
|
setCardActive: (card: any) => void;
|
|
}
|
|
|
|
const ViewCard: React.FC<ViewCardProps> = ({ cardActive, setCardActive }) => {
|
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
|
const [priv, setPriv] = useState<any>(undefined);
|
|
const [turns, setTurns] = useState<number>(0);
|
|
const [rules, setRules] = useState<any>({});
|
|
const fields = useMemo(() => ["private", "turns", "rules"], []);
|
|
useEffect(() => {
|
|
if (!lastJsonMessage) {
|
|
return;
|
|
}
|
|
const data = lastJsonMessage;
|
|
switch (data.type) {
|
|
case "game-update":
|
|
console.log(`view-card - game update`);
|
|
if ("private" in data.update && !equal(data.update.private, priv)) {
|
|
setPriv(data.update.private);
|
|
}
|
|
if ("turns" in data.update && data.update.turns !== turns) {
|
|
setTurns(data.update.turns);
|
|
}
|
|
if ("rules" in data.update && !equal(data.update.rules, rules)) {
|
|
setRules(data.update.rules);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}, [lastJsonMessage, priv, turns, rules]);
|
|
useEffect(() => {
|
|
if (!sendJsonMessage) {
|
|
return;
|
|
}
|
|
sendJsonMessage({
|
|
type: "get",
|
|
fields,
|
|
});
|
|
}, [sendJsonMessage, fields]);
|
|
|
|
const playCard = useCallback(() => {
|
|
if (sendJsonMessage) {
|
|
sendJsonMessage({
|
|
type: "play-card",
|
|
card: cardActive,
|
|
});
|
|
}
|
|
setCardActive(undefined);
|
|
}, [sendJsonMessage, cardActive, setCardActive]);
|
|
|
|
const close = () => {
|
|
setCardActive(undefined);
|
|
};
|
|
|
|
if (!cardActive) {
|
|
return <></>;
|
|
}
|
|
|
|
const capitalize = (string: string) => {
|
|
if (string === "vp") {
|
|
return "Victory Point";
|
|
}
|
|
if (string === "army") {
|
|
return "Knight";
|
|
}
|
|
|
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
};
|
|
|
|
let description: React.ReactElement, lookup: string;
|
|
if (cardActive.type === "progress") {
|
|
lookup = `${cardActive.type}-${cardActive.card}`;
|
|
} else {
|
|
lookup = cardActive.type;
|
|
}
|
|
|
|
const points = "victory-points" in rules && rules["victory-points"].enabled ? rules["victory-points"].points : 0;
|
|
|
|
let cardName = "";
|
|
switch (lookup) {
|
|
case "army":
|
|
cardName = "Knight";
|
|
description = (
|
|
<>
|
|
<div>
|
|
When played, you <b>must</b> move the robber.
|
|
</div>
|
|
<div>
|
|
Steal <b>1</b> resource card from the owner of an adjacent settlement or city.
|
|
</div>
|
|
<div>You may only play one development card during your turn -- either one knight or one progress card.</div>
|
|
</>
|
|
);
|
|
break;
|
|
case "vp":
|
|
cardName = `Victory Point: ${capitalize(cardActive.card)}`;
|
|
description = (
|
|
<>
|
|
<div>
|
|
<b>1</b> victory point.
|
|
</div>
|
|
<div>
|
|
You only reveal your victory point cards when the game is over, either when you or an opponent reaches{" "}
|
|
<b>{points}+</b> victory points on their turn and declares victory!
|
|
</div>
|
|
</>
|
|
);
|
|
break;
|
|
case "progress-road-1":
|
|
case "progress-road-2":
|
|
cardName = "Road Building";
|
|
description = (
|
|
<>
|
|
<div>
|
|
Play <b>2</b> new roads as if you had just built them.
|
|
</div>
|
|
<div>
|
|
This is still limited by the number of roads you have. If you do not have enough roads remaining, or if there
|
|
are no valid road building locations, the number of roads you can place will be reduced.
|
|
</div>
|
|
<div>
|
|
You currently have <b>{priv?.roads}</b> roads remaining.
|
|
</div>
|
|
</>
|
|
);
|
|
break;
|
|
case "progress-monopoly":
|
|
cardName = "Monopoly";
|
|
description = (
|
|
<>
|
|
<div>
|
|
When you play this card, you will select <b>1</b> type of resource. All other players must give you all their
|
|
resource cards of that type.
|
|
</div>
|
|
</>
|
|
);
|
|
break;
|
|
case "progress-year-of-plenty":
|
|
cardName = "Year of Plenty";
|
|
description = (
|
|
<>
|
|
<div>
|
|
Take any <b>2</b> resources from the bank. Add them to your hand. They can be
|
|
<b>2</b> of the same resource or <b>1</b> of two differ resources.
|
|
</div>
|
|
</>
|
|
);
|
|
break;
|
|
default:
|
|
description = <>Unknown card type {lookup}</>;
|
|
break;
|
|
}
|
|
|
|
let canPlay = false;
|
|
if (cardActive.type === "vp") {
|
|
let points = priv?.points || 0;
|
|
priv?.development?.forEach((item: any) => {
|
|
if (item.type === "vp") {
|
|
points++;
|
|
}
|
|
});
|
|
canPlay = points >= points;
|
|
if (!canPlay && !cardActive.played) {
|
|
description = (
|
|
<>
|
|
{description}
|
|
<div>
|
|
You do not have enough victory points to play this card yet. You can currently reach <b>{points}</b> points.
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
} else {
|
|
canPlay = cardActive.turn < turns;
|
|
if (!canPlay) {
|
|
description = (
|
|
<>
|
|
{description}
|
|
<div>You can not play this card until your next turn.</div>
|
|
</>
|
|
);
|
|
}
|
|
if (canPlay) {
|
|
canPlay = priv?.playedCard !== turns;
|
|
if (!canPlay) {
|
|
description = (
|
|
<>
|
|
{description}
|
|
<div>You have already played a development card this turn.</div>
|
|
</>
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cardActive.played) {
|
|
description = (
|
|
<>
|
|
{description}
|
|
<div>You have already played this card.</div>
|
|
</>
|
|
);
|
|
canPlay = false;
|
|
}
|
|
|
|
return (
|
|
<div className="ViewCard">
|
|
<Paper>
|
|
<div className="Title">{cardName}</div>
|
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
|
<Resource type={`${cardActive.type}-${cardActive.card}`} disabled count={1} />
|
|
<div className="Description">{description}</div>
|
|
</div>
|
|
{!cardActive.played && (
|
|
<Button disabled={!canPlay} onClick={playCard}>
|
|
play
|
|
</Button>
|
|
)}
|
|
<Button onClick={close}>close</Button>
|
|
</Paper>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { ViewCard };
|