improving game

This commit is contained in:
2026-03-02 16:31:44 -07:00
parent 0dae393d0d
commit c009d23e76
17 changed files with 144 additions and 84 deletions

View File

@@ -4,6 +4,7 @@ import { BoardDisplay } from "./game/BoardDisplay";
import { ConnectionStatus } from "./game/ConnectionStatus";
import { SessionOverride } from "./game/SessionOverride";
import { useGameChannelContext } from "./contexts/useGameChannelContext";
import { ClusterStatus } from "./clusterStatus/ClusterStatus";
const App: FC<{ playerName: string }> = ({ playerName }) => {
const { isOverridden } = useGameChannelContext();
@@ -15,8 +16,11 @@ const App: FC<{ playerName: string }> = ({ playerName }) => {
return (
<>
<UserInput playerName={playerName} />
<div className="w-screen h-screen bg-navy-900">
<ConnectionStatus />
<div className="w-screen h-screen bg-navy-900 text-navy-100">
<div className="flex justify-between px-3">
<ConnectionStatus />
<ClusterStatus />
</div>
<BoardDisplay playerName={playerName} />
</div>
</>

View File

@@ -0,0 +1,43 @@
import { useEffect, useState } from "react";
import { useWebSocketContext } from "../contexts/useWebSocketContext";
export const ClusterStatus = () => {
const { socket, isConnected } = useWebSocketContext();
const [channelStatus, setChannelStatus] = useState<string>("waiting");
useEffect(() => {
if (!socket || !isConnected) {
return;
}
const channelName = "clusterstatus";
console.log(`Joining channel: ${channelName}`);
const newChannel = socket.channel(channelName, {});
newChannel
.join()
.receive("ok", () => {
setChannelStatus("connected");
})
.receive("error", (resp: unknown) => {
console.log(`Failed to join channel ${channelName}:`, resp);
setChannelStatus("join failed");
})
.receive("timeout", () => {
setChannelStatus("timeout");
});
return () => {
console.log(`Leaving channel: ${channelName}`);
newChannel.leave();
setChannelStatus("waiting");
};
}, [socket, isConnected]);
return (
<div>
<div>ClusterStatus</div>
<div>Channel: {channelStatus}</div>
</div>
);
}

View File

@@ -8,13 +8,16 @@ const PlayerSchema = z.object({
y: z.number(),
});
const GameStateSchema = z.record(z.string(), PlayerSchema);
const GameStateSchema = z.object({
players: z.record(z.string(), PlayerSchema),
tick_number: z.number(),
});
type GameState = z.infer<typeof GameStateSchema>;
type Player = z.infer<typeof PlayerSchema>;
export const BoardDisplay = ({ playerName }: { playerName: string }) => {
const { channel, isJoined, joinGame } = useGameChannelContext();
const [players, setPlayers] = useState<GameState>({});
const [players, setPlayers] = useState<Record<string, Player>>({});
useEffect(() => {
if (channel && !isJoined) {
@@ -25,18 +28,15 @@ export const BoardDisplay = ({ playerName }: { playerName: string }) => {
useEffect(() => {
if (!channel) return;
const ref = channel.on(
"game_state",
(payload: { game_state: unknown }) => {
const result = GameStateSchema.safeParse(payload.game_state);
if (result.success) {
setPlayers(result.data);
} else {
console.error("Invalid game state received:", result.error);
setPlayers({});
}
},
);
const ref = channel.on("game_state", (payload: { game_state: unknown }) => {
const result = GameStateSchema.safeParse(payload.game_state);
if (result.success) {
setPlayers(result.data.players);
} else {
console.error("Invalid game state received:", result.error);
setPlayers({});
}
});
return () => {
channel.off("game_state", ref);

View File

@@ -4,7 +4,6 @@ export const SessionOverride: FC = () => {
return (
<div className="fixed inset-0 bg-navy-900/95 flex items-center justify-center z-50">
<div className="bg-navy-800 border-2 border-accent-600 rounded-lg p-8 max-w-md text-center">
<div className="text-6xl mb-4"></div>
<h2 className="text-2xl font-bold text-accent-500 mb-4">
Session Overridden
</h2>