Live location tracking and playback for the game "manhunt"
1import React from "react";
2import { commands } from "@/bindings";
3import { sharedSwrConfig, useTauriEvent } from "@/lib/hooks";
4import useSWR from "swr";
5
6export default function GameScreen() {
7 const { data: profiles } = useSWR("game-get-profiles", commands.getProfiles);
8
9 const { data: gameState, mutate } = useSWR(
10 "fetch-game-state",
11 commands.getGameState,
12 sharedSwrConfig
13 );
14
15 useTauriEvent("gameStateUpdate", () => {
16 mutate();
17 });
18
19 const isSeeker = gameState.caught_state[gameState.my_id];
20
21 const markCaught = async () => {
22 if (!isSeeker) {
23 await commands.markCaught();
24 }
25 };
26
27 const grabPowerup = async () => {
28 if (gameState.available_powerup !== null) {
29 await commands.grabPowerup();
30 }
31 };
32
33 const activatePowerup = async () => {
34 if (gameState.held_powerup !== null && gameState.held_powerup !== "PingSeeker") {
35 await commands.activatePowerup();
36 }
37 };
38
39 const quitToMenu = async () => {
40 await commands.quitToMenu();
41 };
42
43 if (gameState.game_ended) {
44 return <h2>Game Over! Syncing histories...</h2>;
45 } else if (isSeeker && gameState.seekers_started === null) {
46 return <h2>Waiting for hiders to hide...</h2>;
47 } else {
48 return (
49 <>
50 <h2>Hiders Left</h2>
51 {Object.keys(gameState.caught_state)
52 .filter((k) => !gameState.caught_state[k])
53 .map((key) => (
54 <li key={key}>{profiles?.[key]?.display_name ?? key}</li>
55 ))}
56 {!isSeeker && <button onClick={markCaught}>I got caught!</button>}
57 <h2>Pings</h2>
58 {gameState.last_global_ping !== null ? (
59 <>
60 <p>Last Ping: {gameState.last_global_ping}</p>
61 {Object.entries(gameState.pings)
62 .filter(([key, v]) => key && v !== undefined)
63 .map(([k, v]) => (
64 <li key={k}>
65 {profiles?.[v!.display_player]?.display_name ??
66 v!.display_player}
67 : {v && JSON.stringify(v.loc)}
68 </li>
69 ))}
70 </>
71 ) : (
72 <small>Pings haven't started yet</small>
73 )}
74 <h2>Powerups</h2>
75 {gameState.last_powerup_spawn === null && (
76 <small>Powerups haven't started yet</small>
77 )}
78 {gameState.available_powerup && (
79 <p>
80 Powerup Available: {JSON.stringify(gameState.available_powerup)}{" "}
81 <button onClick={grabPowerup}>Grab!</button>
82 </p>
83 )}
84 {gameState.held_powerup && (
85 <p>
86 Held Powerup: {gameState.held_powerup}
87 {(gameState.held_powerup === "PingSeeker" && (
88 <small>(Will be used next ping)</small>
89 )) || <button onClick={activatePowerup}>Use</button>}
90 </p>
91 )}
92 <h2>Quit</h2>
93 <button onClick={quitToMenu}>Quit To Menu</button>
94 </>
95 );
96 }
97}