diff --git a/lerna.json b/lerna.json index bbf3669..119222b 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "packages": [ "packages/*" ], - "version": "1.2.4" + "version": "1.2.5" } diff --git a/package-lock.json b/package-lock.json index 4c7fa86..db06ca1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "zahlenspiel", - "version": "1.2.4", + "version": "1.2.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index adb8868..ccfb513 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zahlenspiel", - "version": "1.2.4", + "version": "1.2.5", "description": "Zahlenspiel", "main": "index.js", "scripts": { diff --git a/packages/zahlenspiel-backend/package-lock.json b/packages/zahlenspiel-backend/package-lock.json index 42fec2c..6572cac 100644 --- a/packages/zahlenspiel-backend/package-lock.json +++ b/packages/zahlenspiel-backend/package-lock.json @@ -1,6 +1,6 @@ { "name": "zahlenspiel-backend", - "version": "1.2.4", + "version": "1.2.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/zahlenspiel-backend/package.json b/packages/zahlenspiel-backend/package.json index d15e8d6..204fc02 100644 --- a/packages/zahlenspiel-backend/package.json +++ b/packages/zahlenspiel-backend/package.json @@ -1,6 +1,6 @@ { "name": "zahlenspiel-backend", - "version": "1.2.4", + "version": "1.2.5", "description": "Zahlenspiel Backend", "main": "dist/index", "types": "dist/index", @@ -38,6 +38,6 @@ "sneer": "^1.0.1", "uuid": "^7.0.2", "winston": "^3.2.1", - "zahlenspiel-shared-entities": "^1.2.4" + "zahlenspiel-shared-entities": "^1.2.5" } } diff --git a/packages/zahlenspiel-backend/src/rooms/zahlenspiel-room.ts b/packages/zahlenspiel-backend/src/rooms/zahlenspiel-room.ts index 7ee43d7..2815818 100644 --- a/packages/zahlenspiel-backend/src/rooms/zahlenspiel-room.ts +++ b/packages/zahlenspiel-backend/src/rooms/zahlenspiel-room.ts @@ -86,10 +86,10 @@ export class ZahlenspielRoom extends Room { this.send(player.client, new TurnValidMessage(player.cards)); this.updateCardStacks(); if (this.state.isGameWon()) { - this.broadcast(new GameWonMessage()); + this.broadcastWin(); return; } else if (this.state.isGameLost()) { - this.broadcast(new GameLostMessage(this.state.totalRemainingCards(), "You can't drop anymore cards!")); + this.broadcastLoss("You can't drop anymore cards!"); } else if (turnFinishable(this.state.validDroppedCards, this.state.currentDeck.length)) { this.send(player.client, new TurnFinishableMessage()); } @@ -111,9 +111,9 @@ export class ZahlenspielRoom extends Room { const leavingPlayer = this.state.getPlayer(client.id); this.state.removePlayer(client.id); const playerList = marshallPlayers(this.state.players); - this.broadcast(new PlayerLeaveMessage(playerList), {except: client}); + this.broadcastDelayed(new PlayerLeaveMessage(playerList), {except: client}); if (this.isGamePhase()) { - this.broadcastDelayed(new GameLostMessage(this.state.totalRemainingCards(), `${leavingPlayer.name} couldn't handle the pressure and left!`), {except: client}); + this.broadcastLoss(`${leavingPlayer.name} couldn't handle the pressure and left!`, {except: client}); } } else { const reconnectedClient = await this.allowReconnection(client, MAX_RECONNECTION_TIME_IN_SECONDS); @@ -126,9 +126,19 @@ export class ZahlenspielRoom extends Room { onDispose() { } + private broadcastWin() { + this.state.currentGameState = GameStates.WON; + this.broadcastDelayed(new GameWonMessage()); + } + + private broadcastLoss(reason?: string, options?: BroadcastOptions) { + this.state.currentGameState = GameStates.LOST; + this.broadcastDelayed(new GameLostMessage(this.state.totalRemainingCards(), reason), options); + } + private nextPlayer() { if (this.state.isGameLost()) { - this.broadcast(new GameLostMessage(this.state.totalRemainingCards(), "You can't drop anymore cards!")); + this.broadcastLoss("You can't drop anymore cards!"); } else { this.state.nextPlayer(); this.broadcast(new PlayerSwitchMessage(toPlayerDTO(this.state.currentPlayer))); @@ -183,14 +193,22 @@ export class ZahlenspielRoom extends Room { } } - private isPreGamePhase(): boolean { - return this.state.currentGameState === GameStates.PREGAME; + private isGameLost(): boolean { + return this.state.currentGameState === GameStates.LOST; + } + + private isGameWon(): boolean { + return this.state.currentGameState === GameStates.WON; } private isGamePhase(): boolean { return this.state.currentGameState === GameStates.GAME; } + private isPreGamePhase(): boolean { + return this.state.currentGameState === GameStates.PREGAME; + } + private isWaitingPhase(): boolean { return this.state.currentGameState === GameStates.WAITING; } @@ -210,6 +228,16 @@ export class ZahlenspielRoom extends Room { if (this.state.isCurrentPlayer(player) && turnFinishable(this.state.validDroppedCards, this.state.currentDeck.length)) { this.sendDelayed(player.client, new TurnFinishableMessage()); } + } else if (this.isGameWon()) { + this.sendDelayed(player.client, new UpdateCardStackMessage(marshallCardStacks(this.state.cardStacks), this.state.remainingCardsOnStack())); + this.sendDelayed(player.client, new NewCardMessage(player.cards)); + this.sendDelayed(player.client, new PlayerSwitchMessage(toPlayerDTO(this.state.currentPlayer))); + this.sendDelayed(player.client, new GameWonMessage()); + } else if (this.isGameLost()) { + this.sendDelayed(player.client, new UpdateCardStackMessage(marshallCardStacks(this.state.cardStacks), this.state.remainingCardsOnStack())); + this.sendDelayed(player.client, new NewCardMessage(player.cards)); + this.sendDelayed(player.client, new PlayerSwitchMessage(toPlayerDTO(this.state.currentPlayer))); + this.sendDelayed(player.client, new GameLostMessage(this.state.totalRemainingCards())); } } diff --git a/packages/zahlenspiel-backend/src/states/game-state.spec.ts b/packages/zahlenspiel-backend/src/states/game-state.spec.ts index dc33bc4..2031007 100644 --- a/packages/zahlenspiel-backend/src/states/game-state.spec.ts +++ b/packages/zahlenspiel-backend/src/states/game-state.spec.ts @@ -272,5 +272,19 @@ describe("GameState", () => { // THEN expect(gameState.currentPlayer).toEqual(gameState.players[2]); }); + + it("should not loop endlessly if no players has anymore cards", () => { + // GIVEN + const clientMock = mockPartial({}); + const gameState = new GameState("pw"); + ["first", "second", "third"].forEach(playerName => gameState.addNewPlayer(clientMock, playerName)); + gameState.setCurrentPlayer(gameState.players[0]); + + // WHEN + const SUT = () => gameState.nextPlayer(); + + // THEN + expect(SUT).not.toThrow(); + }); }); }); \ No newline at end of file diff --git a/packages/zahlenspiel-backend/src/states/game-state.ts b/packages/zahlenspiel-backend/src/states/game-state.ts index bff3aea..9b27bba 100644 --- a/packages/zahlenspiel-backend/src/states/game-state.ts +++ b/packages/zahlenspiel-backend/src/states/game-state.ts @@ -90,6 +90,10 @@ export class GameState extends Schema { } nextPlayer() { + const playersWithCardsLeft = this.players.filter(player => player.cards.length).length > 0; + if (!playersWithCardsLeft) { + return; + } const nextPlayerOrdinal = (this.currentPlayer.order + 1) % this.players.length; this.currentPlayer = this.players.find((player: Player) => player.order === nextPlayerOrdinal); if (this.currentPlayer.cards.length === 0) { diff --git a/packages/zahlenspiel-shared-entities/package-lock.json b/packages/zahlenspiel-shared-entities/package-lock.json index 953f2d5..ee8a256 100644 --- a/packages/zahlenspiel-shared-entities/package-lock.json +++ b/packages/zahlenspiel-shared-entities/package-lock.json @@ -1,6 +1,6 @@ { "name": "zahlenspiel-shared-entities", - "version": "1.2.4", + "version": "1.2.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/zahlenspiel-shared-entities/package.json b/packages/zahlenspiel-shared-entities/package.json index 5933e0c..4705efb 100644 --- a/packages/zahlenspiel-shared-entities/package.json +++ b/packages/zahlenspiel-shared-entities/package.json @@ -1,6 +1,6 @@ { "name": "zahlenspiel-shared-entities", - "version": "1.2.4", + "version": "1.2.5", "description": "Zahlenspiel Shared Entities", "main": "dist/index", "types": "dist/index", diff --git a/packages/zahlenspiel-ui/package-lock.json b/packages/zahlenspiel-ui/package-lock.json index 66b9086..b78d52f 100644 --- a/packages/zahlenspiel-ui/package-lock.json +++ b/packages/zahlenspiel-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "zahlenspiel-ui", - "version": "1.2.4", + "version": "1.2.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/zahlenspiel-ui/package.json b/packages/zahlenspiel-ui/package.json index 1a357c6..4094ada 100644 --- a/packages/zahlenspiel-ui/package.json +++ b/packages/zahlenspiel-ui/package.json @@ -1,6 +1,6 @@ { "name": "zahlenspiel-ui", - "version": "1.2.4", + "version": "1.2.5", "private": true, "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.28", @@ -21,7 +21,7 @@ "react-scripts": "3.4.1", "styled-components": "^5.0.1", "typescript": "~3.7.2", - "zahlenspiel-shared-entities": "^1.2.4" + "zahlenspiel-shared-entities": "^1.2.5" }, "scripts": { "start": "react-scripts start", diff --git a/packages/zahlenspiel-ui/src/Game.tsx b/packages/zahlenspiel-ui/src/Game.tsx index 0557fb7..0ca616e 100644 --- a/packages/zahlenspiel-ui/src/Game.tsx +++ b/packages/zahlenspiel-ui/src/Game.tsx @@ -177,13 +177,12 @@ const Game = (props: GameProps) => {
- {"Great job, you beat the game!"} - leaveGame(true)}>{"New game!"} -
; + + {"Great job, you beat the game!"} + leaveGame(true)}>{"New game!"} + + - - {renderCards()} - ); case GameStates.LOST: