From f0e8bf07a3f3b7198ab6ed7fe0f16228fa924c74 Mon Sep 17 00:00:00 2001 From: Daithi Hearn Date: Sun, 29 Jan 2023 11:28:17 +0100 Subject: [PATCH 1/5] Bugfix Auto buying cards triggered incorrectly for goer --- src/components/Game/AutoActionManager.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Game/AutoActionManager.tsx b/src/components/Game/AutoActionManager.tsx index bd717da..79f282a 100644 --- a/src/components/Game/AutoActionManager.tsx +++ b/src/components/Game/AutoActionManager.tsx @@ -69,7 +69,7 @@ const AutoActionManager = () => { // Buy cards in if you are the goer useEffect(() => { - if (gameId && canBuyCards) buyCards(gameId, cards) + if (gameId && canBuyCards && cards.length <= 5) buyCards(gameId, cards) }, [gameId, cards, canBuyCards]) return null From 3d64b73860c5b36569d1afb2c030b92e032d7757 Mon Sep 17 00:00:00 2001 From: Daithi Hearn Date: Sun, 29 Jan 2023 11:44:28 +0100 Subject: [PATCH 2/5] Bugfix Last hand not appearing when the game is over --- src/components/Game/WebsocketManager.tsx | 32 +++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/components/Game/WebsocketManager.tsx b/src/components/Game/WebsocketManager.tsx index 23eb59a..47e0397 100644 --- a/src/components/Game/WebsocketManager.tsx +++ b/src/components/Game/WebsocketManager.tsx @@ -146,6 +146,31 @@ const WebsocketHandler = () => { dispatch(updateMyCards(game.cards)) } + // On game completion we need to display the last round to the user + const processGameCompleted = async ( + game: GameState, + previousRound: Round, + ) => { + // Disable actions by setting isMyGo to false + dispatch(disableActions()) + + // Show the last card of the penultimate round being played + playCardSound() + const penultimateHand = previousRound.completedHands.pop() + if (!penultimateHand) throw Error("Failed to get the penultimate round") + dispatch(updatePlayedCards(penultimateHand.playedCards)) + await new Promise(r => setTimeout(r, 4000)) + + // Next show the final round being played + playCardSound() + dispatch(updatePlayedCards(previousRound.currentHand.playedCards)) + dispatch(updateMyCards([])) + await new Promise(r => setTimeout(r, 6000)) + + // Finally update the game with the latest state + dispatch(updateGame(game)) + } + const processAction = useCallback( async (action: ActionEvent) => { console.log(action.type) @@ -186,8 +211,13 @@ const WebsocketHandler = () => { break case "REPLAY": - case "GAME_OVER": dispatch(updateGame(action.gameState)) + break + case "GAME_OVER": + await processGameCompleted( + action.gameState, + action.transitionData as Round, + ) } }, [playerProfiles, isMyGo], From b9137c76436b8fb49b3df0c6e1fba2d0b1a18cb3 Mon Sep 17 00:00:00 2001 From: Daithi Hearn Date: Sun, 29 Jan 2023 11:53:53 +0100 Subject: [PATCH 3/5] Bugfix Card disappearing and no error shown when autoplaying invalid card --- src/components/Game/AutoActionManager.tsx | 14 ++++++-------- src/services/GameService.ts | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/components/Game/AutoActionManager.tsx b/src/components/Game/AutoActionManager.tsx index 79f282a..e4889b6 100644 --- a/src/components/Game/AutoActionManager.tsx +++ b/src/components/Game/AutoActionManager.tsx @@ -30,13 +30,11 @@ const AutoActionManager = () => { const isMyGo = useAppSelector(getIsMyGo) const isInBunker = useAppSelector(getIsInBunker) - const playCard = (id: string, card: string, suppressError = false) => + const playCard = (id: string, card: string) => dispatch(GameService.playCard(id, card)).catch(e => { - if (!suppressError) - enqueueSnackbar(parseError(e), { - variant: "error", - }) - else console.error(e) + enqueueSnackbar(parseError(e), { + variant: "error", + }) }) const call = (id: string, callAmount: number) => @@ -59,10 +57,10 @@ const AutoActionManager = () => { round?.suit && round.status === RoundStatus.PLAYING ) { - if (autoPlayCard) playCard(gameId, autoPlayCard, true) + if (autoPlayCard) playCard(gameId, autoPlayCard) else if (bestCardLead(round)) { const cardToPlay = getWorstCard(cards, round.suit) - if (cardToPlay) playCard(gameId, cardToPlay.name, true) + if (cardToPlay) playCard(gameId, cardToPlay.name) } } }, [gameId, round, isMyGo, cards, autoPlayCard]) diff --git a/src/services/GameService.ts b/src/services/GameService.ts index a84711b..8bb64b2 100644 --- a/src/services/GameService.ts +++ b/src/services/GameService.ts @@ -178,14 +178,14 @@ const chooseFromDummy = const playCard = (gameId: string, card: string): AppThunk> => async (dispatch, getState) => { - dispatch(removeCard(card)) - dispatch(clearAutoPlay()) const accessToken = getAccessToken(getState()) await axios.put( `${process.env.REACT_APP_API_URL}/api/v1/playCard?gameId=${gameId}&card=${card}`, null, getDefaultConfig(accessToken), ) + dispatch(removeCard(card)) + dispatch(clearAutoPlay()) } export default { From c93abd9e94d620ff2385a78bf8cb5a3de8637f12 Mon Sep 17 00:00:00 2001 From: Daithi Hearn Date: Sun, 29 Jan 2023 12:09:17 +0100 Subject: [PATCH 4/5] Bigfix Fixing spectator mode --- src/components/Game/WebsocketManager.tsx | 14 +++++++++----- src/pages/Game/Game.tsx | 17 ++++++++++++----- src/services/GameService.ts | 8 +++++--- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/components/Game/WebsocketManager.tsx b/src/components/Game/WebsocketManager.tsx index 47e0397..bd553ef 100644 --- a/src/components/Game/WebsocketManager.tsx +++ b/src/components/Game/WebsocketManager.tsx @@ -6,6 +6,7 @@ import { disableActions, getGameId, getIsMyGo, + getIamSpectator, updateGame, updatePlayedCards, } from "../../caches/GameSlice" @@ -60,6 +61,7 @@ const WebsocketHandler = () => { const [autoActionEnabled, setAutoActionEnabled] = useState(false) const isMyGo = useAppSelector(getIsMyGo) + const iamSpectator = useAppSelector(getIamSpectator) const playerProfiles = useAppSelector(getPlayerProfiles) const { enqueueSnackbar } = useSnackbar() @@ -190,23 +192,25 @@ const WebsocketHandler = () => { case "BUY_CARDS": const buyCardsEvt = action.transitionData as BuyCardsEvent sendCardsBoughtNotification(buyCardsEvt) - reloadCards(action.gameState.cards, isMyGo) + if (!iamSpectator) + reloadCards(action.gameState.cards, isMyGo) dispatch(updateGame(action.gameState)) break case "CHOOSE_FROM_DUMMY": case "CARD_PLAYED": playCardSound() - reloadCards(action.gameState.cards, isMyGo) + if (!iamSpectator) + reloadCards(action.gameState.cards, isMyGo) dispatch(updateGame(action.gameState)) break case "CALL": callSound() - reloadCards(action.gameState.cards, true) + if (!iamSpectator) reloadCards(action.gameState.cards, true) dispatch(updateGame(action.gameState)) break case "PASS": passSound() - reloadCards(action.gameState.cards, true) + if (!iamSpectator) reloadCards(action.gameState.cards, true) dispatch(updateGame(action.gameState)) break @@ -220,7 +224,7 @@ const WebsocketHandler = () => { ) } }, - [playerProfiles, isMyGo], + [playerProfiles, iamSpectator, isMyGo], ) useSubscription(["/game", "/user/game"], message => diff --git a/src/pages/Game/Game.tsx b/src/pages/Game/Game.tsx index 8538d7c..aa1e9ff 100644 --- a/src/pages/Game/Game.tsx +++ b/src/pages/Game/Game.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react" +import React, { useCallback, useEffect } from "react" import GameWrapper from "../../components/Game/GameWrapper" import GameOver from "../../components/Game/GameOver" import GameService from "../../services/GameService" @@ -10,7 +10,11 @@ import { useParams } from "react-router-dom" import { useAppDispatch, useAppSelector } from "../../caches/hooks" import { useSnackbar } from "notistack" -import { getIsGameActive, resetGame } from "../../caches/GameSlice" +import { + getIamSpectator, + getIsGameActive, + resetGame, +} from "../../caches/GameSlice" import { clearAutoPlay } from "../../caches/AutoPlaySlice" import { clearMyCards } from "../../caches/MyCardsSlice" import RefreshingData from "../../components/icons/RefreshingData" @@ -20,18 +24,21 @@ const Game = () => { const dispatch = useAppDispatch() let { id } = useParams() const { enqueueSnackbar } = useSnackbar() + const iamSpectator = useAppSelector(getIamSpectator) const isGameActive = useAppSelector(getIsGameActive) - const fetchData = async () => { + const fetchData = useCallback(async () => { if (id) - await dispatch(GameService.refreshGameState(id)).catch((e: Error) => + await dispatch( + GameService.refreshGameState(id, iamSpectator), + ).catch((e: Error) => enqueueSnackbar(parseError(e), { variant: "error" }), ) await dispatch(GameService.getAllPlayers()).catch((e: Error) => enqueueSnackbar(parseError(e), { variant: "error" }), ) - } + }, [iamSpectator]) useEffect(() => { fetchData() diff --git a/src/services/GameService.ts b/src/services/GameService.ts index 8bb64b2..ee62a6b 100644 --- a/src/services/GameService.ts +++ b/src/services/GameService.ts @@ -29,7 +29,7 @@ const getGame = } const refreshGameState = - (gameId: string): AppThunk> => + (gameId: string, iamSpectator: boolean): AppThunk> => async (dispatch, getState) => { const accessToken = getAccessToken(getState()) const response = await axios.get( @@ -37,8 +37,10 @@ const refreshGameState = getDefaultConfig(accessToken), ) dispatch(updateGame(response.data)) - dispatch(updateMyCards(response.data.cards)) - dispatch(clearAutoPlay()) + if (!iamSpectator) { + dispatch(updateMyCards(response.data.cards)) + dispatch(clearAutoPlay()) + } } const getAll = (): AppThunk> => async (dispatch, getState) => { From b434f6589022503c50fa66ee71fdd83f39ad92eb Mon Sep 17 00:00:00 2001 From: Daithi Hearn Date: Sun, 29 Jan 2023 12:10:54 +0100 Subject: [PATCH 5/5] Bigfix Fixing spectator mode --- src/pages/Game/Game.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Game/Game.tsx b/src/pages/Game/Game.tsx index aa1e9ff..13795a0 100644 --- a/src/pages/Game/Game.tsx +++ b/src/pages/Game/Game.tsx @@ -49,7 +49,7 @@ const Game = () => { dispatch(clearMyCards()) dispatch(clearAutoPlay()) } - }, [id]) + }, [id, iamSpectator]) return (