From 7c6c48769494fabce0c2673455721323d510d4d0 Mon Sep 17 00:00:00 2001 From: Oliboy50 Date: Sat, 27 Aug 2022 21:20:35 +0200 Subject: [PATCH] fix: eventually consistent number of hidden cards --- velonimo.game.php | 12 +++++- velonimo.js | 95 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 82 insertions(+), 25 deletions(-) diff --git a/velonimo.game.php b/velonimo.game.php index 153cf32..a991f13 100644 --- a/velonimo.game.php +++ b/velonimo.game.php @@ -349,6 +349,7 @@ function playCards(array $playedCardIds, bool $cardsPlayedWithJersey) { self::setGameStateValue(self::GAME_STATE_PREVIOUS_PLAYED_CARDS_VALUE, $lastPlayedCardsValue); self::setGameStateValue(self::GAME_STATE_LAST_PLAYED_CARDS_VALUE, $playedCardsValue); self::notifyAllPlayers('cardsPlayed', clienttranslate('${player_name} attacks with ${cardsImage}'), [ + 'players' => $this->formatPlayersForClient($players), 'playedCardsPlayerId' => $currentPlayerId, 'playedCards' => $formattedCards = $this->formatCardsForClient($playedCards), 'cardsImage' => $cardsPlayedWithJersey @@ -384,10 +385,11 @@ function playCards(array $playedCardIds, bool $cardsPlayedWithJersey) { if ($numberOfCardsToPickFromDeck > 0) { $cardsPickedFromDeck = $this->fromBgaCardsToVelonimoCards( - $this->deck->pickCards($numberOfPlayedCardsOfValueTwo, self::CARD_LOCATION_DECK, $currentPlayer->getId()) + $this->deck->pickCards($numberOfCardsToPickFromDeck, self::CARD_LOCATION_DECK, $currentPlayer->getId()) ); $numberOfCurrentPlayerCards = $numberOfCurrentPlayerCards + $numberOfCardsToPickFromDeck; self::notifyAllPlayers('cardsMovedFromDeckToAnotherPlayer', clienttranslate('${player_name} picks ${numberOfCards} card(s) from the deck'), [ + 'players' => $this->formatPlayersForClient($players), 'receiverPlayerId' => $currentPlayer->getId(), 'numberOfCards' => $numberOfCardsToPickFromDeck, 'player_name' => $currentPlayer->getName(), @@ -396,6 +398,7 @@ function playCards(array $playedCardIds, bool $cardsPlayedWithJersey) { foreach ($players as $player) { if ($player->getId() === $currentPlayer->getId()) { self::notifyPlayer($currentPlayer->getId(), 'cardsReceivedFromDeck', $translatedMessage, [ + 'players' => $this->formatPlayersForClient($players), 'cards' => $formattedCards = $this->formatCardsForClient($cardsPickedFromDeck), 'cardsImage' => $formattedCards, 'player_name' => $currentPlayer->getName(), @@ -542,6 +545,7 @@ function selectWhoTakeAttackReward(int $selectedPlayerId) { $translatedMessage = clienttranslate('${player_name} gives the attacker reward ${cardsImage} to ${player_name2}'); } self::notifyAllPlayers('attackRewardCardsMovedToPlayer', $translatedMessage, [ + 'players' => $this->formatPlayersForClient($players), 'cards' => $formattedCards = $this->formatCardsForClient($rewardCards), 'cardsImage' => $formattedCards, 'receiverPlayerId' => $selectedPlayer->getId(), @@ -602,6 +606,7 @@ function selectPlayerToPickCards(int $selectedPlayerId) { // notify players $formattedPickedCards = $this->formatCardsForClient($pickedCards); self::notifyAllPlayers('cardsMovedBetweenTwoOtherPlayers', clienttranslate('${player_name} picks ${numberOfCards} card(s) from ${player_name2} hand'), [ + 'players' => $this->formatPlayersForClient($players), 'receiverPlayerId' => $currentPlayer->getId(), 'senderPlayerId' => $selectedPlayer->getId(), 'numberOfCards' => $numberOfCardsToPick, @@ -612,6 +617,7 @@ function selectPlayerToPickCards(int $selectedPlayerId) { foreach ($players as $player) { if ($player->getId() === $currentPlayer->getId()) { self::notifyPlayer($currentPlayer->getId(), 'cardsReceivedFromAnotherPlayer', $translatedMessage, [ + 'players' => $this->formatPlayersForClient($players), 'cards' => $formattedPickedCards, 'cardsImage' => $formattedPickedCards, 'senderPlayerId' => $selectedPlayer->getId(), @@ -621,6 +627,7 @@ function selectPlayerToPickCards(int $selectedPlayerId) { ]); } elseif ($player->getId() === $selectedPlayer->getId()) { self::notifyPlayer($selectedPlayer->getId(), 'cardsSentToAnotherPlayer', $translatedMessage, [ + 'players' => $this->formatPlayersForClient($players), 'cards' => $formattedPickedCards, 'cardsImage' => $formattedPickedCards, 'receiverPlayerId' => $currentPlayer->getId(), @@ -688,6 +695,7 @@ function selectCardsToGiveBack(array $selectedCardIds) { // notify players $formattedSelectedCards = $this->formatCardsForClient($selectedCards); self::notifyAllPlayers('cardsMovedBetweenTwoOtherPlayers', clienttranslate('${player_name} gives back ${numberOfCards} card(s) to ${player_name2}'), [ + 'players' => $this->formatPlayersForClient($players), 'receiverPlayerId' => $receiverPlayer->getId(), 'senderPlayerId' => $currentPlayer->getId(), 'numberOfCards' => $numberOfCardsToGiveBack, @@ -698,6 +706,7 @@ function selectCardsToGiveBack(array $selectedCardIds) { foreach ($players as $player) { if ($player->getId() === $currentPlayer->getId()) { self::notifyPlayer($currentPlayer->getId(), 'cardsSentToAnotherPlayer', $translatedMessage, [ + 'players' => $this->formatPlayersForClient($players), 'cards' => $formattedSelectedCards, 'cardsImage' => $formattedSelectedCards, 'receiverPlayerId' => $receiverPlayer->getId(), @@ -707,6 +716,7 @@ function selectCardsToGiveBack(array $selectedCardIds) { ]); } elseif ($player->getId() === $receiverPlayer->getId()) { self::notifyPlayer($receiverPlayer->getId(), 'cardsReceivedFromAnotherPlayer', $translatedMessage, [ + 'players' => $this->formatPlayersForClient($players), 'cards' => $formattedSelectedCards, 'cardsImage' => $formattedSelectedCards, 'senderPlayerId' => $currentPlayer->getId(), diff --git a/velonimo.js b/velonimo.js index 9173b2f..93d9eb6 100644 --- a/velonimo.js +++ b/velonimo.js @@ -205,10 +205,12 @@ function (dojo, declare) { this.howManyRounds = 0; this.playedCardsValue = 0; this.howManyCardsToGiveBack = 0; - this.players = []; + this.players = {}; this.playerHand = null; // https://en.doc.boardgamearena.com/Stock // /!\ 2P mode only this.howManyCardsInDeck = 0; + this.resetDisplayedNumberOfCardsByPlayerId(); + this.timeoutToRefreshDisplayedNumberOfCards = null; this.resetCardsGroups(); }, setup: function (gamedatas) { @@ -264,8 +266,8 @@ function (dojo, declare) { `, DOM_ID_BOARD_CARPET); }); - console.log(this.players); - this.setupNumberOfCardsInPlayersHand(); + this.resetDisplayedNumberOfCardsByPlayerId(); + this.setupPlayersHiddenCards(); this.setupPlayersFinishPosition(); // setup jersey @@ -321,11 +323,11 @@ function (dojo, declare) { this.onClickOnTogglePlayerHandSortButton(); dojo.connect($(DOM_ID_PLAYER_HAND_TOGGLE_SORT_BUTTON), 'onclick', this, 'onClickOnTogglePlayerHandSortButton'); // setup currentPlayer cards - this.players[this.player_id].howManyCards = 0; this.addCardsToPlayerHand( (this.currentPlayerHasJersey && !this.jerseyHasBeenUsedInTheCurrentRound) ? this.addJerseyToCards(gamedatas.currentPlayerCards) - : gamedatas.currentPlayerCards + : gamedatas.currentPlayerCards, + false ); // setup cards played on table @@ -545,10 +547,18 @@ function (dojo, declare) { is2PlayersMode: function () { return Object.keys(this.players).length === 2; }, + resetDisplayedNumberOfCardsByPlayerId: function () { + this.displayedNumberOfCardsByPlayerId = {}; + Object.entries(this.players).forEach((entry) => { + const player = entry[1]; + + this.displayedNumberOfCardsByPlayerId[player.id] = player.howManyCards; + }); + }, setupRoundsInfo: function () { $(DOM_ID_CURRENT_ROUND).innerHTML = `${this.currentRound} / ${this.howManyRounds}`; }, - setupNumberOfCardsInPlayersHand: function () { + setupPlayersHiddenCards: function () { const getCardRotateDeg = (numberOfCards, i) => { if (numberOfCards === 1) { return 0; @@ -558,14 +568,15 @@ function (dojo, declare) { return offset + ((i * -1) * 5); }; - Object.entries(this.players).forEach((entry) => { - const player = entry[1]; + Object.entries(this.displayedNumberOfCardsByPlayerId).forEach((entry) => { + const playerId = entry[0]; + const howManyCards = entry[1]; const playerCardsHtml = []; - for (let i = 0; i < player.howManyCards; i++) { - playerCardsHtml.push(`
`); + for (let i = 0; i < howManyCards; i++) { + playerCardsHtml.push(`
`); } - $(`player-table-${player.id}-hand-cards`).innerHTML = playerCardsHtml.join(''); + $(`player-table-${playerId}-hand-cards`).innerHTML = playerCardsHtml.join(''); }); }, setupPlayersScore: function () { @@ -1575,7 +1586,8 @@ function (dojo, declare) { * @param {number} numberOfCards */ decreaseNumberOfCardsInDeck: function (numberOfCards) { - this.howManyCardsInDeck = (this.howManyCardsInDeck || numberOfCards) - numberOfCards; + const removableNumberOfCards = Math.max(0, Math.min(numberOfCards, this.howManyCardsInDeck)); + this.howManyCardsInDeck = this.howManyCardsInDeck - removableNumberOfCards; this.setupDeckOfCards(); }, /** @@ -1782,32 +1794,57 @@ function (dojo, declare) { * @param {number} numberOfCards */ increaseNumberOfCardsOfPlayer: function (playerId, numberOfCards) { - this.players[playerId].howManyCards = this.players[playerId].howManyCards + numberOfCards; + const addableNumberOfCards = Math.max(0, numberOfCards); + this.displayedNumberOfCardsByPlayerId[playerId] = this.displayedNumberOfCardsByPlayerId[playerId] + addableNumberOfCards; - this.setupNumberOfCardsInPlayersHand(); + this.updatePlayersHiddenCardsWithEventualConsistency(); }, /** * @param {number} playerId * @param {number} numberOfCards */ decreaseNumberOfCardsOfPlayer: function (playerId, numberOfCards) { - if (this.players[playerId].howManyCards > 0) { - this.players[playerId].howManyCards = this.players[playerId].howManyCards - numberOfCards; - } + const removableNumberOfCards = Math.max(0, Math.min(numberOfCards, this.displayedNumberOfCardsByPlayerId[playerId])); + this.displayedNumberOfCardsByPlayerId[playerId] = this.displayedNumberOfCardsByPlayerId[playerId] - removableNumberOfCards; - this.setupNumberOfCardsInPlayersHand(); + this.updatePlayersHiddenCardsWithEventualConsistency(); + }, + /** + * Setup players hidden cards and eventually update the correct number of cards for each player (in case some card animations did not work) + */ + updatePlayersHiddenCardsWithEventualConsistency: function () { + this.setupPlayersHiddenCards(); + + if (this.timeoutToRefreshDisplayedNumberOfCards !== null) { + clearTimeout(this.timeoutToRefreshDisplayedNumberOfCards); + } + this.timeoutToRefreshDisplayedNumberOfCards = setTimeout( + () => { + this.resetDisplayedNumberOfCardsByPlayerId(); + this.setupPlayersHiddenCards(); + }, + 3000 + ); }, /** * @param {Object[]} cards + * @param {boolean=true} updateNumberOfCards */ - addCardsToPlayerHand: function (cards) { + addCardsToPlayerHand: function (cards, updateNumberOfCards) { + if (typeof updateNumberOfCards === 'undefined') { + updateNumberOfCards = true; + } + cards.forEach((card) => { - if (card.id !== CARD_ID_JERSEY) { + if ( + updateNumberOfCards + && card.id !== CARD_ID_JERSEY + ) { this.increaseNumberOfCardsOfPlayer(this.player_id, 1); } this.playerHand.addToStockWithId(this.getCardPositionInSpriteByColorAndValue(card.color, card.value), card.id); - this.setupPlayerHandSelectableCards(); }); + this.setupPlayerHandSelectableCards(); }, /** * @param {number} cardId @@ -2235,10 +2272,10 @@ function (dojo, declare) { notif_cardsDealt: function (data) { this.playerHand.removeAll(); this.resetCardsGroups(); - this.players[this.player_id].howManyCards = 0; this.addCardsToPlayerHand((this.currentPlayerHasJersey && !this.jerseyHasBeenUsedInTheCurrentRound) ? this.addJerseyToCards(data.args.cards) - : data.args.cards + : data.args.cards, + false ); }, notif_roundStarted: function (data) { @@ -2246,7 +2283,8 @@ function (dojo, declare) { this.setupRoundsInfo(); this.players = data.args.players; - this.setupNumberOfCardsInPlayersHand(); + this.resetDisplayedNumberOfCardsByPlayerId(); + this.setupPlayersHiddenCards(); this.setupPlayersFinishPosition(); if (this.is2PlayersMode()) { @@ -2255,6 +2293,7 @@ function (dojo, declare) { } }, notif_cardsPlayed: function (data) { + this.players = data.args.players; this.discardPlayerSpeechBubbles(); this.movePlayedCardsToPreviousPlayedCards(); @@ -2282,12 +2321,15 @@ function (dojo, declare) { this.discardPlayedCards(); }, notif_cardsReceivedFromAnotherPlayer: function (data) { + this.players = data.args.players; this.receiveCardsFromAnotherPlayer(data.args.senderPlayerId, data.args.cards); }, notif_cardsSentToAnotherPlayer: function (data) { + this.players = data.args.players; this.sendCardsToAnotherPlayer(data.args.receiverPlayerId, data.args.cards); }, notif_cardsMovedBetweenTwoOtherPlayers: function (data) { + this.players = data.args.players; this.moveCardsBetweenTwoOtherPlayers(data.args.senderPlayerId, data.args.receiverPlayerId, data.args.numberOfCards); }, notif_roundEnded: function (data) { @@ -2301,6 +2343,8 @@ function (dojo, declare) { } const previousJerseyWearerId = this.getCurrentJerseyWearerIdIfExists(); this.players = data.args.players; + this.resetDisplayedNumberOfCardsByPlayerId(); + this.setupPlayersHiddenCards(); this.restoreJerseyForCurrentRound(); this.moveJerseyToCurrentWinner(previousJerseyWearerId); @@ -2316,6 +2360,7 @@ function (dojo, declare) { * /!\ 2P mode only */ notif_attackRewardCardsMovedToPlayer: function (data) { + this.players = data.args.players; this.moveAttackRewardCardsToPlayer(data.args.receiverPlayerId, data.args.cards); }, /** @@ -2329,12 +2374,14 @@ function (dojo, declare) { * /!\ 2P mode only */ notif_cardsReceivedFromDeck: function (data) { + this.players = data.args.players; this.moveCardsFromDeckToPlayerHand(data.args.cards); }, /** * /!\ 2P mode only */ notif_cardsMovedFromDeckToAnotherPlayer: function (data) { + this.players = data.args.players; this.moveCardsFromDeckToAnotherPlayer(data.args.receiverPlayerId, data.args.numberOfCards); }, });