Jofthomas's picture
bulk2
90cbf22
raw
history blame
4.63 kB
import { useRef, useState } from 'react';
import PixiGame from './PixiGame.tsx';
import { useElementSize } from 'usehooks-ts';
import { Stage } from '@pixi/react';
import { ConvexProvider, useConvex, useQuery } from 'convex/react';
import PlayerDetails from './PlayerDetails.tsx';
import { api } from '../../convex/_generated/api';
import { useWorldHeartbeat } from '../hooks/useWorldHeartbeat.ts';
import { useHistoricalTime } from '../hooks/useHistoricalTime.ts';
import { DebugTimeManager } from './DebugTimeManager.tsx';
import { GameId } from '../../convex/aiTown/ids.ts';
import { useServerGame } from '../hooks/serverGame.ts';
import { VoteModal } from './VoteModal.tsx';
import { GameCycle } from '../../convex/aiTown/gameCycle.ts';
import { PlayerDescription } from '../../convex/aiTown/playerDescription.ts';
export const SHOW_DEBUG_UI = !!import.meta.env.VITE_SHOW_DEBUG_UI;
export function VotingName(gameState: string) {
switch (gameState) {
case 'warewolf-vote':
return {
name: 'Warewolf Vote',
desc: 'Select a player who is warewolf',
type: 'warewolf-vote',
};
case 'player-kill':
return {
name: 'Player Kill',
desc: 'Select a player to kill',
type: 'player-kill',
};
default:
return {
name: 'Voting',
desc: 'Select a player to vote',
type: 'voting',
};
}
}
export function isVotingState(gameCycle: GameCycle) {
return gameCycle.cycleIndex === 0 || gameCycle.cycleIndex === 2;
}
function showMap(gameCycle: GameCycle, player: PlayerDescription) {
// Here also check for player description
return gameCycle.cycleIndex === 2 || gameCycle.cycleIndex == 1;
}
export default function Game() {
const convex = useConvex();
const [selectedElement, setSelectedElement] = useState<{
kind: 'player';
id: GameId<'players'>;
}>();
const [gameWrapperRef, { width, height }] = useElementSize();
const worldStatus = useQuery(api.world.defaultWorldStatus);
const worldId = worldStatus?.worldId;
const engineId = worldStatus?.engineId;
const game = useServerGame(worldId);
// Send a periodic heartbeat to our world to keep it alive.
useWorldHeartbeat();
const worldState = useQuery(api.world.worldState, worldId ? { worldId } : 'skip');
const { historicalTime, timeManager } = useHistoricalTime(worldState?.engine);
const scrollViewRef = useRef<HTMLDivElement>(null);
// TODO: base this on the game state
const [gameState, setGameState] = useState<'warewolf-vote' | 'player-kill' | 'none'>('none');
if (!worldId || !engineId || !game) {
return null;
}
return (
<>
{SHOW_DEBUG_UI && <DebugTimeManager timeManager={timeManager} width={200} height={100} />}
<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">
{/* Game area */}
<div className="relative overflow-hidden bg-brown-900" ref={gameWrapperRef}>
<div className={`absolute inset-0 ${!showMap ? 'invisible' : '' }`}>
<div className="container">
<Stage width={width} height={height} options={{ backgroundColor: 0x7ab5ff }}>
{/* Re-propagate context because contexts are not shared between renderers.
https://github.com/michalochman/react-pixi-fiber/issues/145#issuecomment-531549215 */}
<ConvexProvider client={convex}>
<PixiGame
game={game}
worldId={worldId}
engineId={engineId}
width={width}
height={height}
historicalTime={historicalTime}
setSelectedElement={setSelectedElement}
/>
</ConvexProvider>
</Stage>
</div>
</div>
<div></div>
</div>
{/* Right column area */}
<div
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"
ref={scrollViewRef}
>
{isVotingState(game.world.gameCycle) ? <VoteModal game={game} worldId={worldId} engineId={engineId} /> :
<PlayerDetails
worldId={worldId}
engineId={engineId}
game={game}
playerId={selectedElement?.id}
setSelectedElement={setSelectedElement}
scrollViewRef={scrollViewRef}
/>
}
</div>
</div>
</>
);
}