Spaces:
Running
Running
Simeon Garratt
feat: multiplayer — matchmaking, 1v1 match with bot demo, match results with ELO
7edc107 | "use client"; | |
| import { useState, useCallback, useRef, useEffect } from "react"; | |
| import { | |
| MatchmakingManager, | |
| type MatchFoundData, | |
| } from "@/lib/game/matchmaking"; | |
| /** The current phase of the matchmaking flow. */ | |
| export type MatchmakingState = "idle" | "searching" | "found" | "error"; | |
| /** | |
| * React hook that wraps `MatchmakingManager` with component-friendly state. | |
| * | |
| * Returns reactive `state`, `playerCount`, `matchData`, and `error` values | |
| * alongside `startSearching` / `cancelSearch` actions. | |
| * | |
| * Automatically cleans up the matchmaking channel on unmount. | |
| */ | |
| export function useMatchmaking( | |
| playerId: string, | |
| playerName: string, | |
| playerElo: number, | |
| ) { | |
| const [state, setState] = useState<MatchmakingState>("idle"); | |
| const [playerCount, setPlayerCount] = useState(0); | |
| const [matchData, setMatchData] = useState<MatchFoundData | null>(null); | |
| const [error, setError] = useState<string | null>(null); | |
| const managerRef = useRef<MatchmakingManager | null>(null); | |
| const startSearching = useCallback(async () => { | |
| setState("searching"); | |
| setError(null); | |
| const manager = new MatchmakingManager(playerId, playerName, playerElo); | |
| managerRef.current = manager; | |
| await manager.joinQueue({ | |
| onPlayerCount: setPlayerCount, | |
| onMatchFound: (data) => { | |
| setState("found"); | |
| setMatchData(data); | |
| }, | |
| onError: (err) => { | |
| setState("error"); | |
| setError(err); | |
| }, | |
| }); | |
| }, [playerId, playerName, playerElo]); | |
| const cancelSearch = useCallback(async () => { | |
| if (managerRef.current) { | |
| await managerRef.current.leaveQueue(); | |
| managerRef.current = null; | |
| } | |
| setState("idle"); | |
| setMatchData(null); | |
| }, []); | |
| // Cleanup on unmount | |
| useEffect(() => { | |
| return () => { | |
| managerRef.current?.leaveQueue(); | |
| }; | |
| }, []); | |
| return { state, playerCount, matchData, error, startSearching, cancelSearch }; | |
| } | |