From c82ab77a14fbbbf4188b83fc9a2ed3d5f2178b6d Mon Sep 17 00:00:00 2001 From: Omid Nikrah Date: Wed, 1 Jan 2025 13:17:39 +0330 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix:=20fix=20empty=20plays=20lim?= =?UTF-8?q?itation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/game/dto/player-fill-hand.dto.ts | 5 +- apps/backend/src/modules/game/game.gateway.ts | 30 +++--- apps/backend/src/modules/game/game.service.ts | 35 +++--- apps/frontend/src/enums/Toasts.ts | 1 + apps/frontend/src/hooks/useGameControls.ts | 15 ++- .../GameRoom/components/Player/index.tsx | 100 +++++++++--------- libs/shared/src/constants/events.constants.ts | 2 +- libs/shared/src/interfaces/game.interface.ts | 1 + 8 files changed, 103 insertions(+), 86 deletions(-) diff --git a/apps/backend/src/modules/game/dto/player-fill-hand.dto.ts b/apps/backend/src/modules/game/dto/player-fill-hand.dto.ts index d01ba9b..6f1696b 100644 --- a/apps/backend/src/modules/game/dto/player-fill-hand.dto.ts +++ b/apps/backend/src/modules/game/dto/player-fill-hand.dto.ts @@ -1,5 +1,5 @@ import type { GameState, HandPosition, Player } from '@gol-ya-pooch/shared'; -import { IsString } from 'class-validator'; +import { IsArray, IsString } from 'class-validator'; export class PlayerFillHandDTO { @IsString() @@ -13,4 +13,7 @@ export class PlayerFillHandDTO { @IsString() direction: HandPosition; + + @IsArray() + filledHands: Player['id'][]; } diff --git a/apps/backend/src/modules/game/game.gateway.ts b/apps/backend/src/modules/game/game.gateway.ts index c21f84f..a43f293 100644 --- a/apps/backend/src/modules/game/game.gateway.ts +++ b/apps/backend/src/modules/game/game.gateway.ts @@ -228,16 +228,26 @@ export class GameGateway @SubscribeMessage(Events.REQUEST_EMPTY_PLAY) async handleRequestEmptyPlay(@MessageBody() data: RequestEmptyPlayDTO) { const { gameId, playerId } = data; - this.server.to(gameId).emit(Events.REQUEST_EMPTY_PLAY, playerId); + + const canEmptyPlay = await this.gameService.validateEmptyPlay(gameId); + + if (canEmptyPlay) { + this.server.to(gameId).emit(Events.REQUEST_EMPTY_PLAY, playerId); + } else { + this.server.to(gameId).emit(Events.REACH_EMPTY_PLAYS_LIMIT, { + message: 'خالی بازی‌هاتون تموم شده.', + }); + } } @SubscribeMessage(Events.PLAYER_FILL_HAND) async handlePlayerFillHand(@MessageBody() data: PlayerFillHandDTO) { - const { gameId, fromPlayerId, toPlayerId, direction } = data; + const { gameId, fromPlayerId, toPlayerId, direction, filledHands } = data; this.server.to(gameId).emit(Events.PLAYER_FILL_HAND, { fromPlayerId, toPlayerId, direction, + filledHands, }); } @@ -248,7 +258,7 @@ export class GameGateway ) { const { gameId, playerId, hand } = data; - const { canEmptyPlay, hasObjectInHand, objectLocation } = + const { hasObjectInHand, objectLocation } = await this.gameService.emptyPlayerHand(gameId, playerId, hand); if (hasObjectInHand) { @@ -264,15 +274,9 @@ export class GameGateway return; } - if (canEmptyPlay) { - this.server.to(gameId).emit(Events.PLAYER_EMPTY_HAND, { - playerId, - hand, - }); - } else { - this.server.to(gameId).emit(Events.REACH_EMPTY_HANDS_LIMIT, { - message: 'خالی بازی‌هاتون تموم شده.', - }); - } + this.server.to(gameId).emit(Events.PLAYER_EMPTY_HAND, { + playerId, + hand, + }); } } diff --git a/apps/backend/src/modules/game/game.service.ts b/apps/backend/src/modules/game/game.service.ts index 2c4c3e8..30cf745 100644 --- a/apps/backend/src/modules/game/game.service.ts +++ b/apps/backend/src/modules/game/game.service.ts @@ -269,20 +269,11 @@ export class GameService { playerId: Player['id'], hand: HandPosition | 'both', ): Promise<{ - canEmptyPlay: boolean; hasObjectInHand: boolean; objectLocation: IObjectLocation; }> { const gameState = await this.getGameState(gameId); - if (gameState.emptyPlays <= 0) { - return { - objectLocation: null, - canEmptyPlay: false, - hasObjectInHand: false, - }; - } - const hasObjectInHand = gameState.objectLocation.playerId === playerId && (hand === 'both' || gameState.objectLocation.hand === hand); @@ -290,21 +281,12 @@ export class GameService { if (hasObjectInHand) { return { objectLocation: gameState.objectLocation, - canEmptyPlay: false, hasObjectInHand: true, }; } - gameState.emptyPlays--; - - await this.redisClient.set( - `game:${gameState.gameId}`, - JSON.stringify(gameState), - ); - return { objectLocation: null, - canEmptyPlay: true, hasObjectInHand: false, }; } @@ -369,6 +351,23 @@ export class GameService { }; } + async validateEmptyPlay(gameId: GameState['gameId']): Promise { + const gameState = await this.getGameState(gameId); + + console.log(gameState.emptyPlays); + + if (gameState.emptyPlays === 0) return false; + + gameState.emptyPlays--; + + await this.redisClient.set( + `game:${gameState.gameId}`, + JSON.stringify(gameState), + ); + + return true; + } + async getRoomInfo(gameId: GameState['gameId']): Promise { const gameState = await this.getGameState(gameId); diff --git a/apps/frontend/src/enums/Toasts.ts b/apps/frontend/src/enums/Toasts.ts index 5e031b1..dae60b5 100644 --- a/apps/frontend/src/enums/Toasts.ts +++ b/apps/frontend/src/enums/Toasts.ts @@ -1,3 +1,4 @@ export enum Toasts { REQUESTED_EMPTY_PLAY = 'REQUESTED_EMPTY_PLAY', + SPREAD_OBJECT = 'SPREAD_OBJECT', } diff --git a/apps/frontend/src/hooks/useGameControls.ts b/apps/frontend/src/hooks/useGameControls.ts index 149fc94..67b1980 100644 --- a/apps/frontend/src/hooks/useGameControls.ts +++ b/apps/frontend/src/hooks/useGameControls.ts @@ -60,6 +60,8 @@ export const useGameControls = () => { const playerSiblingsInfo = isItemInArray(teamMembers!, 'id', player.id); let toPlayerId = ''; + dismissToastByName(Toasts.SPREAD_OBJECT); + switch (hand) { case 'left': if (playerSiblingsInfo.hasLeft) { @@ -87,6 +89,7 @@ export const useGameControls = () => { fromPlayerId: player?.id, toPlayerId, direction: hand, + filledHands: filledHands.current, }); } else { showToast('دست این بازیکن رو پر کردی'); @@ -95,7 +98,10 @@ export const useGameControls = () => { }; const handleEmitPlaying = (hand: HandPosition) => { - if (requestedPlayerIdToEmptyPlay === player?.id) { + if ( + requestedPlayerIdToEmptyPlay === player?.id && + phase === GamePhases.PLAYING + ) { playEmptyPlayingSound(); setIsPlaying(true); @@ -215,7 +221,7 @@ export const useGameControls = () => { }, ); - on(Events.REACH_EMPTY_HANDS_LIMIT, (data: { message: string }) => { + on(Events.REACH_EMPTY_PLAYS_LIMIT, (data: { message: string }) => { showToast(data.message, 3000); }); @@ -223,7 +229,7 @@ export const useGameControls = () => { off(Events.GAME_STATE_UPDATED); off(Events.PLAYER_RECEIVE_OBJECT); off(Events.GUESS_LOCATION_RESULT); - off(Events.REACH_EMPTY_HANDS_LIMIT); + off(Events.REACH_EMPTY_PLAYS_LIMIT); }; }, []); @@ -232,13 +238,14 @@ export const useGameControls = () => { phase === GamePhases.SPREADING_OBJECT && player?.id === gameState?.gameMaster ) { - showToast('اوستا گل رو پخش کن'); + showToast('اوستا گل رو پخش کن', 5000, true, Toasts.SPREAD_OBJECT); } }, [phase, player, gameState]); useEffect(() => { on(Events.PLAYER_FILL_HAND, (data: PlayerFillHand) => { setHandFillingData(data); + filledHands.current = data.filledHands; setTimeout(() => { setHandFillingData(null); diff --git a/apps/frontend/src/pages/GameRoom/components/Player/index.tsx b/apps/frontend/src/pages/GameRoom/components/Player/index.tsx index 5007635..c2998c2 100644 --- a/apps/frontend/src/pages/GameRoom/components/Player/index.tsx +++ b/apps/frontend/src/pages/GameRoom/components/Player/index.tsx @@ -225,69 +225,71 @@ export const Player = ({ team, data, isJoined, position }: IPlayer) => { )} /> )} - {gameState?.currentTurn === team && position !== 'bottom' && ( - <> -
- {gameState.gameSize > 2 && ( -
+ {gameState?.currentTurn === team && + position !== 'bottom' && + phase === GamePhases.PLAYING && ( + <> +
+ {gameState.gameSize > 2 && ( +
+ + + +
+ )} +
-
- )} -
-
- -
- - )} + + )}
); }; diff --git a/libs/shared/src/constants/events.constants.ts b/libs/shared/src/constants/events.constants.ts index d9256cd..511e360 100644 --- a/libs/shared/src/constants/events.constants.ts +++ b/libs/shared/src/constants/events.constants.ts @@ -18,7 +18,7 @@ export const Events = { REQUEST_EMPTY_HAND: 'game:opponent:requestEmptyHand', REQUEST_EMPTY_PLAY: 'game:opponent:requestEmptyPlay', - REACH_EMPTY_HANDS_LIMIT: 'game:team:reachEmptyHandsLimit', + REACH_EMPTY_PLAYS_LIMIT: 'game:team:reachEmptyPlaysLimit', PLAYER_JOINED: 'game:player:joined', PLAYER_LEFT: 'game:player:left', diff --git a/libs/shared/src/interfaces/game.interface.ts b/libs/shared/src/interfaces/game.interface.ts index 9c14699..39f6360 100644 --- a/libs/shared/src/interfaces/game.interface.ts +++ b/libs/shared/src/interfaces/game.interface.ts @@ -52,4 +52,5 @@ export interface PlayerFillHand { fromPlayerId: Player['id']; toPlayerId: Player['id']; direction: HandPosition; + filledHands: Player['id'][]; }