Spaces:
Sleeping
Sleeping
revert
Browse files- src/components/Game.tsx +31 -43
src/components/Game.tsx
CHANGED
|
@@ -1,4 +1,7 @@
|
|
| 1 |
-
import
|
|
|
|
|
|
|
|
|
|
| 2 |
import { Stage } from '@pixi/react';
|
| 3 |
import { ConvexProvider, useConvex, useQuery } from 'convex/react';
|
| 4 |
import PlayerDetails from './PlayerDetails.tsx';
|
|
@@ -17,25 +20,12 @@ import { createPortal } from 'react-dom';
|
|
| 17 |
import GameVote from './GameVote.tsx';
|
| 18 |
import { EndGame } from './EndGame.tsx';
|
| 19 |
import { LOBBY_SIZE } from '../../convex/constants';
|
| 20 |
-
import { useElementSize } from 'usehooks-ts';
|
| 21 |
|
| 22 |
export const SHOW_DEBUG_UI = !!import.meta.env.VITE_SHOW_DEBUG_UI;
|
| 23 |
|
| 24 |
-
function GameStateLabel(
|
| 25 |
-
const
|
| 26 |
-
|
| 27 |
-
useEffect(() => {
|
| 28 |
-
const updateHumanPlayers = () => {
|
| 29 |
-
const humanCount = [...game.world.players.values()].filter(player => player.human).length;
|
| 30 |
-
setHumans(humanCount);
|
| 31 |
-
};
|
| 32 |
-
|
| 33 |
-
// Update the count of human players when the component mounts and when game.world.players changes
|
| 34 |
-
updateHumanPlayers();
|
| 35 |
-
}, [game.world.players]);
|
| 36 |
-
|
| 37 |
-
console.log('Human player seen by lobby', game.world.players.values());
|
| 38 |
-
|
| 39 |
switch (game.world.gameCycle.cycleState) {
|
| 40 |
case 'Day':
|
| 41 |
return {
|
|
@@ -45,7 +35,7 @@ function GameStateLabel({ game, me }) {
|
|
| 45 |
case 'WerewolfVoting':
|
| 46 |
return {
|
| 47 |
label: 'Werewolf Vote',
|
| 48 |
-
desc: 'Select a player who is a
|
| 49 |
};
|
| 50 |
case 'PlayerKillVoting':
|
| 51 |
return {
|
|
@@ -55,32 +45,31 @@ function GameStateLabel({ game, me }) {
|
|
| 55 |
case 'LobbyState':
|
| 56 |
return {
|
| 57 |
label: 'Lobby (waiting for start)',
|
| 58 |
-
desc: `Waiting
|
| 59 |
};
|
| 60 |
case 'Night':
|
| 61 |
return {
|
| 62 |
label: 'Night',
|
| 63 |
-
desc: me?.type === 'werewolf' ? 'Discuss who to kill with other
|
| 64 |
};
|
| 65 |
case 'EndGame':
|
| 66 |
return {
|
| 67 |
label: 'The End',
|
| 68 |
-
desc: `Winners are ${game.world.winner}!`,
|
| 69 |
};
|
| 70 |
-
default:
|
| 71 |
-
return null;
|
| 72 |
}
|
| 73 |
}
|
| 74 |
|
| 75 |
-
export function canVote(game, me) {
|
| 76 |
return me && (game.world.gameCycle.cycleState === "WerewolfVoting" || (game.world.gameCycle.cycleState === "PlayerKillVoting" && me.type === "werewolf"));
|
| 77 |
}
|
| 78 |
|
| 79 |
-
export function isEndGame(game) {
|
| 80 |
return game.world.gameCycle.cycleState === "EndGame";
|
| 81 |
}
|
| 82 |
|
| 83 |
-
function showMap(gameCycle, me) {
|
|
|
|
| 84 |
return (gameCycle.cycleState === "Day" || gameCycle.cycleState === "WerewolfVoting") || me?.type === "werewolf";
|
| 85 |
}
|
| 86 |
|
|
@@ -96,7 +85,8 @@ export default function Game() {
|
|
| 96 |
const engineId = worldStatus?.engineId;
|
| 97 |
const oauth = JSON.parse(localStorage.getItem('oauth'));
|
| 98 |
const oauthToken = oauth ? oauth.userInfo.fullname : undefined;
|
| 99 |
-
const humanTokenIdentifier =
|
|
|
|
| 100 |
|
| 101 |
const game = useServerGame(worldId);
|
| 102 |
|
|
@@ -108,26 +98,24 @@ export default function Game() {
|
|
| 108 |
|
| 109 |
const scrollViewRef = useRef<HTMLDivElement>(null);
|
| 110 |
|
| 111 |
-
if (!worldId || !engineId || !game) {
|
| 112 |
return null;
|
| 113 |
}
|
| 114 |
-
|
|
|
|
| 115 |
const playerId = [...game.world.players.values()].find(
|
| 116 |
(p) => !!p && p.human === humanTokenIdentifier,
|
| 117 |
)?.id;
|
| 118 |
-
console.log("playerId",
|
| 119 |
|
| 120 |
const meDescription = playerId ? game?.playerDescriptions.get(playerId) : undefined;
|
| 121 |
-
|
| 122 |
-
const gameStateLabel = GameStateLabel({ game: game as GameObj, me: meDescription });
|
| 123 |
-
|
| 124 |
return (
|
| 125 |
<>
|
| 126 |
{SHOW_DEBUG_UI && <DebugTimeManager timeManager={timeManager} width={200} height={100} />}
|
| 127 |
<div className="mx-auto w-full max-w grid grid-rows-[240px_1fr] lg:grid-rows-[1fr] lg:grid-cols-[1fr_auto] lg:grow max-w-[1400px] min-h-[480px] game-frame">
|
| 128 |
{/* Game area */}
|
| 129 |
<div className="relative overflow-hidden bg-brown-900" ref={gameWrapperRef}>
|
| 130 |
-
<div className={`absolute inset-0 ${showMap(game.world.gameCycle, meDescription) ? '' : 'invisible'}`}>
|
| 131 |
<div className="container">
|
| 132 |
<Stage width={width} height={height} options={{ backgroundColor: 0x7ab5ff }}>
|
| 133 |
{/* Re-propagate context because contexts are not shared between renderers.
|
|
@@ -146,21 +134,21 @@ https://github.com/michalochman/react-pixi-fiber/issues/145#issuecomment-5315492
|
|
| 146 |
</Stage>
|
| 147 |
</div>
|
| 148 |
</div>
|
| 149 |
-
<div className={`absolute inset-0 ${!showMap(game.world.gameCycle, meDescription) ? '' : 'invisible'}`}>
|
| 150 |
<Cloud worldId={worldId} />
|
| 151 |
</div>
|
| 152 |
</div>
|
| 153 |
{/* Right column area */}
|
| 154 |
<div
|
| 155 |
-
className="flex flex-col overflow-y-auto shrink-0 px-4 py-6 sm:px-6 lg:w-96 xl:pr-6 border-t-8 sm:border-t-0 sm:border-l-8 border-brown-900
|
| 156 |
ref={scrollViewRef}
|
| 157 |
>
|
| 158 |
<div className="flex flex-col items-center mb-4 gap-4">
|
| 159 |
-
<h2 className="text-2xl font-bold">{
|
| 160 |
-
<p className="text-lg text-center">{
|
| 161 |
</div>
|
| 162 |
{playerId && !isEndGame(game) && canVote(game, meDescription) && <GameVote engineId={engineId} game={game} playerId={playerId} />}
|
| 163 |
-
{!isEndGame(game) && !canVote(game, meDescription) && playerId
|
| 164 |
worldId={worldId}
|
| 165 |
engineId={engineId}
|
| 166 |
game={game}
|
|
@@ -173,10 +161,10 @@ https://github.com/michalochman/react-pixi-fiber/issues/145#issuecomment-5315492
|
|
| 173 |
</div>
|
| 174 |
</div>
|
| 175 |
{createPortal(
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
)}
|
| 181 |
</>
|
| 182 |
);
|
|
|
|
| 1 |
+
import { useRef, useState } from 'react';
|
| 2 |
+
import PixiGame from './PixiGame.tsx';
|
| 3 |
+
|
| 4 |
+
import { useElementSize } from 'usehooks-ts';
|
| 5 |
import { Stage } from '@pixi/react';
|
| 6 |
import { ConvexProvider, useConvex, useQuery } from 'convex/react';
|
| 7 |
import PlayerDetails from './PlayerDetails.tsx';
|
|
|
|
| 20 |
import GameVote from './GameVote.tsx';
|
| 21 |
import { EndGame } from './EndGame.tsx';
|
| 22 |
import { LOBBY_SIZE } from '../../convex/constants';
|
|
|
|
| 23 |
|
| 24 |
export const SHOW_DEBUG_UI = !!import.meta.env.VITE_SHOW_DEBUG_UI;
|
| 25 |
|
| 26 |
+
export function GameStateLabel(game: GameObj, me: PlayerDescription | undefined) {
|
| 27 |
+
const humans = [...game.world.playersInit.values()].filter(player => player.human).length
|
| 28 |
+
console.log(humans)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
switch (game.world.gameCycle.cycleState) {
|
| 30 |
case 'Day':
|
| 31 |
return {
|
|
|
|
| 35 |
case 'WerewolfVoting':
|
| 36 |
return {
|
| 37 |
label: 'Werewolf Vote',
|
| 38 |
+
desc: 'Select a player who is a warewolf',
|
| 39 |
};
|
| 40 |
case 'PlayerKillVoting':
|
| 41 |
return {
|
|
|
|
| 45 |
case 'LobbyState':
|
| 46 |
return {
|
| 47 |
label: 'Lobby (waiting for start)',
|
| 48 |
+
desc: `Waiting the game to start. ${ humans } out of the ${ LOBBY_SIZE } requiered `,
|
| 49 |
};
|
| 50 |
case 'Night':
|
| 51 |
return {
|
| 52 |
label: 'Night',
|
| 53 |
+
desc: me?.type === 'werewolf' ? 'Discuss who to kill with other warewolves' : 'Hide in your home!!',
|
| 54 |
};
|
| 55 |
case 'EndGame':
|
| 56 |
return {
|
| 57 |
label: 'The End',
|
| 58 |
+
desc: `Winners are ${ game.world.winner }!`,
|
| 59 |
};
|
|
|
|
|
|
|
| 60 |
}
|
| 61 |
}
|
| 62 |
|
| 63 |
+
export function canVote(game: ServerGame, me: PlayerDescription | undefined) {
|
| 64 |
return me && (game.world.gameCycle.cycleState === "WerewolfVoting" || (game.world.gameCycle.cycleState === "PlayerKillVoting" && me.type === "werewolf"));
|
| 65 |
}
|
| 66 |
|
| 67 |
+
export function isEndGame(game: ServerGame) {
|
| 68 |
return game.world.gameCycle.cycleState === "EndGame";
|
| 69 |
}
|
| 70 |
|
| 71 |
+
function showMap(gameCycle: GameCycle, me: PlayerDescription | undefined) {
|
| 72 |
+
// Here also check for player description
|
| 73 |
return (gameCycle.cycleState === "Day" || gameCycle.cycleState === "WerewolfVoting") || me?.type === "werewolf";
|
| 74 |
}
|
| 75 |
|
|
|
|
| 85 |
const engineId = worldStatus?.engineId;
|
| 86 |
const oauth = JSON.parse(localStorage.getItem('oauth'));
|
| 87 |
const oauthToken = oauth ? oauth.userInfo.fullname : undefined;
|
| 88 |
+
const humanTokenIdentifier = useQuery(api.world.userStatus, { worldId, oauthToken });
|
| 89 |
+
|
| 90 |
|
| 91 |
const game = useServerGame(worldId);
|
| 92 |
|
|
|
|
| 98 |
|
| 99 |
const scrollViewRef = useRef<HTMLDivElement>(null);
|
| 100 |
|
| 101 |
+
if (!worldId || !engineId || !game ) {
|
| 102 |
return null;
|
| 103 |
}
|
| 104 |
+
//console.log(humanTokenIdentifier)
|
| 105 |
+
//console.log("game.world.players.values() :",game.world.players.values())
|
| 106 |
const playerId = [...game.world.players.values()].find(
|
| 107 |
(p) => !!p && p.human === humanTokenIdentifier,
|
| 108 |
)?.id;
|
| 109 |
+
console.log("playerId",playerId)
|
| 110 |
|
| 111 |
const meDescription = playerId ? game?.playerDescriptions.get(playerId) : undefined;
|
|
|
|
|
|
|
|
|
|
| 112 |
return (
|
| 113 |
<>
|
| 114 |
{SHOW_DEBUG_UI && <DebugTimeManager timeManager={timeManager} width={200} height={100} />}
|
| 115 |
<div className="mx-auto w-full max-w grid grid-rows-[240px_1fr] lg:grid-rows-[1fr] lg:grid-cols-[1fr_auto] lg:grow max-w-[1400px] min-h-[480px] game-frame">
|
| 116 |
{/* Game area */}
|
| 117 |
<div className="relative overflow-hidden bg-brown-900" ref={gameWrapperRef}>
|
| 118 |
+
<div className={`absolute inset-0 ${showMap(game.world.gameCycle, meDescription) ? '' : 'invisible' }`}>
|
| 119 |
<div className="container">
|
| 120 |
<Stage width={width} height={height} options={{ backgroundColor: 0x7ab5ff }}>
|
| 121 |
{/* Re-propagate context because contexts are not shared between renderers.
|
|
|
|
| 134 |
</Stage>
|
| 135 |
</div>
|
| 136 |
</div>
|
| 137 |
+
<div className={`absolute inset-0 ${!showMap(game.world.gameCycle, meDescription) ? '' : 'invisible' }`}>
|
| 138 |
<Cloud worldId={worldId} />
|
| 139 |
</div>
|
| 140 |
</div>
|
| 141 |
{/* Right column area */}
|
| 142 |
<div
|
| 143 |
+
className="flex flex-col overflow-y-auto shrink-0 px-4 py-6 sm:px-6 lg:w-96 xl:pr-6 border-t-8 sm:border-t-0 sm:border-l-8 border-brown-900 bg-brown-800 text-brown-100"
|
| 144 |
ref={scrollViewRef}
|
| 145 |
>
|
| 146 |
<div className="flex flex-col items-center mb-4 gap-4">
|
| 147 |
+
<h2 className="text-2xl font-bold">{GameStateLabel(game as GameObj, meDescription).label}</h2>
|
| 148 |
+
<p className="text-lg text-center">{GameStateLabel(game as GameObj, meDescription).desc}</p>
|
| 149 |
</div>
|
| 150 |
{playerId && !isEndGame(game) && canVote(game, meDescription) && <GameVote engineId={engineId} game={game} playerId={playerId} />}
|
| 151 |
+
{!isEndGame(game) && !canVote(game, meDescription) && playerId &&<PlayerDetails
|
| 152 |
worldId={worldId}
|
| 153 |
engineId={engineId}
|
| 154 |
game={game}
|
|
|
|
| 161 |
</div>
|
| 162 |
</div>
|
| 163 |
{createPortal(
|
| 164 |
+
<div className="max-w-[1400px] mx-auto">
|
| 165 |
+
{playerId && <VotingPopover engineId={engineId} game={game} playerId={playerId} />}
|
| 166 |
+
</div>,
|
| 167 |
+
document.getElementById('footer-buttons')
|
| 168 |
)}
|
| 169 |
</>
|
| 170 |
);
|