Spaces:
Sleeping
Sleeping
import { GameId } from '../../convex/aiTown/ids.ts'; | |
import { AgentDescription } from '../../convex/aiTown/agentDescription.ts'; | |
import { PlayerDescription } from '../../convex/aiTown/playerDescription.ts'; | |
import { World } from '../../convex/aiTown/world.ts'; | |
import { WorldMap } from '../../convex/aiTown/worldMap.ts'; | |
import { Id } from '../../convex/_generated/dataModel'; | |
import { useMemo } from 'react'; | |
import { useQuery } from 'convex/react'; | |
import { api } from '../../convex/_generated/api'; | |
import { parseMap } from '../../convex/util/object.ts'; | |
export type ServerGame = { | |
world: World; | |
playerDescriptions: Map<GameId<'players'>, PlayerDescription>; | |
agentDescriptions: Map<GameId<'agents'>, AgentDescription>; | |
worldMap: WorldMap; | |
}; | |
// TODO: This hook reparses the game state (even if we're not rerunning the query) | |
// when used in multiple components. Move this to a context to only parse it once. | |
export function useServerGame(worldId: Id<'worlds'> | undefined): ServerGame | undefined { | |
const worldState = useQuery(api.world.worldState, worldId ? { worldId } : 'skip'); | |
const descriptions = useQuery(api.world.gameDescriptions, worldId ? { worldId } : 'skip'); | |
const game = useMemo(() => { | |
if (!worldState || !descriptions) { | |
return undefined; | |
} | |
return { | |
world: new World(worldState.world), | |
agentDescriptions: parseMap( | |
descriptions.agentDescriptions, | |
AgentDescription, | |
(p) => p.agentId, | |
), | |
playerDescriptions: parseMap( | |
descriptions.playerDescriptions, | |
PlayerDescription, | |
(p) => p.playerId, | |
), | |
worldMap: new WorldMap(descriptions.worldMap), | |
}; | |
}, [worldState, descriptions]); | |
return game; | |
} | |