From 82d13002f2bfd5caa7b41000a48da38beb6ad6d6 Mon Sep 17 00:00:00 2001 From: snen Date: Thu, 30 Sep 2021 21:28:15 -0400 Subject: [PATCH] Update session code --- client/game/Game.tsx | 12 ------ client/game/GameClient.tsx | 10 +++++ client/game/useServerSocket.ts | 79 ++++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 16 deletions(-) diff --git a/client/game/Game.tsx b/client/game/Game.tsx index 54e9a7c..28d7020 100644 --- a/client/game/Game.tsx +++ b/client/game/Game.tsx @@ -60,18 +60,6 @@ export default function Game(props: GameProps): JSX.Element { } }, [currentTurn, startTurn]) - React.useEffect(() => { - const intervalId = setInterval( - () => { - getView() - }, - 1000, - ) - return () => { - clearInterval(intervalId) - } - }, [getView]) - const enemyBoard = team === 1 ? board.scourge : board.sentinal const allyBoard = team === 1 ? board.sentinal : board.scourge const isMyTurn = currentTurn === team diff --git a/client/game/GameClient.tsx b/client/game/GameClient.tsx index 17d3319..c90b2c5 100644 --- a/client/game/GameClient.tsx +++ b/client/game/GameClient.tsx @@ -200,6 +200,16 @@ export default function GameClient(): JSX.Element { [socketHandle, team], ) + React.useEffect(() => { + if (gameHandle.status !== 'connected') return + const intervalId = setInterval(() => { + gameHandle.handle.getView() + }, 1000) + return () => { + clearInterval(intervalId) + } + }, [gameHandle]) + React.useEffect(() => { if (gameHandle.status !== 'connected') return gameHandle.handle.readyPlayer() diff --git a/client/game/useServerSocket.ts b/client/game/useServerSocket.ts index 22a5e09..2881436 100644 --- a/client/game/useServerSocket.ts +++ b/client/game/useServerSocket.ts @@ -27,6 +27,7 @@ interface SessionCommandAPI { leave: () => void play: () => void poll: () => void + ready: () => void } interface SocketMessage { @@ -43,6 +44,7 @@ type GameSocketSessionState = | { status: 'connecting' } | { status: 'finding-game' } | { status: 'joining-game'; playerId: string; matchId: string } + | { status: 'pre-game'; playerId: string; matchId: string } | { status: 'in-game'; playerId: string; matchId: string } type Action = @@ -50,6 +52,7 @@ type Action = | { type: 'close' } | { type: 'find-game'; playerId: string; matchId: string } | { type: 'join-game' } + | { type: 'ready-game' } function reducer(state: GameSocketSessionState, action: Action): GameSocketSessionState { switch (action.type) { @@ -63,6 +66,10 @@ function reducer(state: GameSocketSessionState, action: Action): GameSocketSessi } case 'join-game': { if (state.status !== 'joining-game') return state + return { ...state, status: 'pre-game' } + } + case 'ready-game': { + if (state.status !== 'pre-game') return state return { ...state, status: 'in-game' } } case 'close': { @@ -74,8 +81,38 @@ function reducer(state: GameSocketSessionState, action: Action): GameSocketSessi const initialState: GameSocketSessionState = {status: 'connecting'} +type ServerResult = + // session command result + | 'found' + | 'joined p1' + | 'joined p2' + | 'left' + | 'played' + | 'game ready' + | 'generic error' + // poll command result + | 'Scourge joined' + | 'Scourge turn' + | 'Scourge wins' + | 'Scourge player is ready' + | 'Scourge player has left' + | 'Sentinal joined' + | 'Sentinal turn' + | 'Sentinal wins' + | 'Sentinal player is ready' + | 'Sentinal player has left' + | 'update' + +interface ServerResponse { + player_id: string + match_id: string + result: ServerResult + game_result: any +} + interface SocketHandle { sendGameCommand: (command: GameCommand) => void + sendPoll: () => void } export default function useServerSocket( @@ -86,7 +123,7 @@ export default function useServerSocket( /* prep socket */ const onMessage = React.useCallback((message: WebSocketEventMap['message']) => { - const data = JSON.parse(message.data) + const data = JSON.parse(message.data) as ServerResponse switch (data.result) { case 'found': { dispatch({ @@ -106,6 +143,10 @@ export default function useServerSocket( dispatch ({ type: 'join-game' }) return } + case 'game ready': { + dispatch({ type: 'ready-game' }) + return + } case 'played': { switch (data.game_result.result_type) { case 'a': { @@ -138,6 +179,10 @@ export default function useServerSocket( default: return } } + case 'update': { + console.log(message) + return; + } default: return; } }, [onUpdate]) @@ -169,13 +214,22 @@ export default function useServerSocket( const sendGameCommand = React.useCallback((gameCommand: GameCommand) => { if (state.status !== 'in-game') return sendJson({ - player_id: MY_ID, + player_id: state.playerId, match_id: state.matchId, command: 'play', game_command: gameCommand, }) }, [state, sendJson]) + const sendPoll = React.useCallback(() => { + if (state.status !== 'in-game') return + sendJson({ + player_id: state.playerId, + match_id: state.matchId, + command: 'poll', + }) + }, [sendJson, state]) + /* effects to push the coordinator along */ React.useEffect(() => { @@ -188,15 +242,32 @@ export default function useServerSocket( sendJson({command: 'join', player_id: state.playerId, match_id: state.matchId}) }, [sendJson, state]) + React.useEffect(() => { + if (state.status !== 'pre-game') return + sendJson({command: 'ready', player_id: state.playerId, match_id: state.matchId}) + }, [sendJson, state]) + + React.useEffect(() => { + if (state.status !== 'in-game') return + const leaveGame = () => { + sendJson({command: 'leave', player_id: state.playerId, match_id: state.matchId}) + } + addEventListener('beforeunload', leaveGame) + return () => { + removeEventListener('beforeunload', leaveGame) + } + }, [sendJson, state]) + /* return game command handler in wrapper */ const handle = React.useMemo>(() => { switch (state.status) { case 'in-game': { - return {status: 'connected', handle: {sendGameCommand}} + return {status: 'connected', handle: {sendGameCommand, sendPoll}} } case 'finding-game': - case 'joining-game': { + case 'joining-game': + case 'pre-game': { return {status: 'connecting'} } case 'connecting':