From 5b15a1ee4d45ac732ba07d12cff7c45874a9fe08 Mon Sep 17 00:00:00 2001 From: gereon77 Date: Mon, 23 Oct 2023 15:10:28 +0200 Subject: [PATCH] Make retreat region public to avoid error deserializing combat state in post combat states and clear public regions after combat. --- .../src/client/GameSettingsComponent.tsx | 4 +- .../ingame-game-state/IngameGameState.ts | 2 +- .../combat-game-state/CombatGameState.ts | 4 +- .../PostCombatGameState.ts | 20 +++++-- .../ResolveRetreatGameState.ts | 57 +++++-------------- .../ArianneMartellHouseCardAbility.ts | 11 +++- 6 files changed, 43 insertions(+), 55 deletions(-) diff --git a/agot-bg-game-server/src/client/GameSettingsComponent.tsx b/agot-bg-game-server/src/client/GameSettingsComponent.tsx index be1bda23d..89cf3bce0 100644 --- a/agot-bg-game-server/src/client/GameSettingsComponent.tsx +++ b/agot-bg-game-server/src/client/GameSettingsComponent.tsx @@ -821,7 +821,7 @@ export default class GameSettingsComponent extends Component (Inspired by LordWazza) }> - + } checked={this.gameSettings.dragonWar} onChange={() => this.changeGameSettings(() => this.gameSettings.dragonWar = !this.gameSettings.dragonWar)} @@ -836,7 +836,7 @@ export default class GameSettingsComponent extends Component If a player has only one remaining non-dragon land unit and no more castles, it will turn into a dragon. }> - + } checked={this.gameSettings.dragonRevenge} onChange={() => this.changeGameSettings(() => this.gameSettings.dragonRevenge = !this.gameSettings.dragonRevenge)} diff --git a/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts index 3a2288c3a..731ffa2e8 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts @@ -1813,7 +1813,7 @@ export default class IngameGameState extends GameState< return _.uniq(result); } - addPublicVisibleRegions(regions: Region[]): void { + addPublicVisibleRegions(...regions: Region[]): void { if (this.fogOfWar) { const addedRegions = regions.filter(r => !this.publicVisibleRegions.includes(r)); this.publicVisibleRegions.push(...addedRegions); diff --git a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/CombatGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/CombatGameState.ts index cee1b40cf..328ea96a7 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/CombatGameState.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/CombatGameState.ts @@ -179,6 +179,8 @@ export default class CombatGameState extends GameState< [defender, {region: combatRegion, army: combatRegion.units.values, houseCard: null, tidesOfBattleCard: this.isTidesOfBattleCardsActive ? null : undefined}] ]); + this.ingameGameState.addPublicVisibleRegions(attackerComingFrom, combatRegion); + // Automatically declare attackers and defenders support const possibleSupporters = this.getPossibleSupportingHouses(); @@ -196,8 +198,6 @@ export default class CombatGameState extends GameState< if (!this.proceedNextSupportDeclaration(true)) { this.proceedToChooseGeneral(); } - - this.ingameGameState.addPublicVisibleRegions([attackerComingFrom, combatRegion]); } declareSupport(supportingHouse: House, supportedHouse: House | null, writeToGameLog: boolean): void { diff --git a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/post-combat-game-state/PostCombatGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/post-combat-game-state/PostCombatGameState.ts index 700eebb96..4279f7f9f 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/post-combat-game-state/PostCombatGameState.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/post-combat-game-state/PostCombatGameState.ts @@ -319,12 +319,6 @@ export default class PostCombatGameState extends GameState< if (this.doesVictoriousDefenderNeedToRetreat() && !this.originalLoser) { // For the sake of simplicity, declare the winner the loser for the upcoming retreat phase. // This way we do not have to complicate the code and handle the possible retreat of the winner in ResolveRetreatGameState. - this.combat.ingameGameState.log({ - type: "arianne-martell-force-retreat", - house: this.loser.id, - enemyHouse: this.winner.id - }); - this.originalLoser = this.loser; this.loser = this.winner; this.proceedRetreat(); @@ -426,6 +420,20 @@ export default class PostCombatGameState extends GameState< }); } }); + + // Hide combat areas after combat + this.combat.ingameGameState.publicVisibleRegions = []; + this.entireGame.users.values.filter(u => u.connected).forEach(u => { + this.entireGame.sendMessageToClients([u], { + type: "update-public-visible-regions", + regionsToMakeVisible: [], + ordersToMakeVisible: [], + clear: true, + applyChangesNow: !this.combat.ingameGameState.players.has(u) + }); + }); + this.combat.ingameGameState.updateVisibleRegions(true); + this.combat.resolveMarchOrderGameState.onResolveSingleMarchOrderGameStateFinish(this.attacker); } diff --git a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/post-combat-game-state/resolve-retreat-game-state/ResolveRetreatGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/post-combat-game-state/resolve-retreat-game-state/ResolveRetreatGameState.ts index 5ce082a18..3b64710f1 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/post-combat-game-state/resolve-retreat-game-state/ResolveRetreatGameState.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/combat-game-state/post-combat-game-state/resolve-retreat-game-state/ResolveRetreatGameState.ts @@ -192,49 +192,20 @@ export default class ResolveRetreatGameState extends GameState< const from = this.postCombat.loserCombatData.region; - if (!this.ingame.fogOfWar) { - this.entireGame.broadcastToClients({ - type: "move-units", - from: from.id, - to: this.retreatRegion.id, - units: armyLeft.map(u => u.id), - isRetreat: true - }); - } else { - const to = this.retreatRegion as Region; - const userVisibilityList = this.entireGame.users.values.map(u => { - const p = this.ingame.players.tryGet(u, null); - const visibleRegions = this.ingame.getVisibleRegionsForPlayer(p); - return { - user: u, - seesFrom: visibleRegions.includes(from), - seesTo: visibleRegions.includes(to) - } - }); - - const usersWhoSeeFromAndTo = userVisibilityList.filter(item => item.seesFrom && item.seesTo).map(item => item.user); - this.entireGame.sendMessageToClients(usersWhoSeeFromAndTo, { - type: "move-units", - from: from.id, - to: to.id, - units: armyLeft.map(u => u.id) - }); - - const userWhoOnlySeeFrom = userVisibilityList.filter(dict => dict.seesFrom && !dict.seesTo).map(dict => dict.user); - this.entireGame.sendMessageToClients(userWhoOnlySeeFrom, { - type: "remove-units", - regionId: from.id, - unitIds: armyLeft.map(u => u.id), - animate: false - }); - - const userWhoOnlySeeTo = userVisibilityList.filter(dict => !dict.seesFrom && dict.seesTo).map(dict => dict.user); - this.entireGame.sendMessageToClients(userWhoOnlySeeTo, { - type: "add-units", - regionId: to.id, - units: armyLeft.map(u => u.serializeToClient()) - }); - } + // As the army units are necessary in the world + // to deserialize combat state properly, + // we add the chosen retreat region to public visible regions + // and clear this list afer combat. + this.ingame.addPublicVisibleRegions(this.retreatRegion); + this.ingame.updateVisibleRegions(); + + this.entireGame.broadcastToClients({ + type: "move-units", + from: from.id, + to: this.retreatRegion.id, + units: armyLeft.map(u => u.id), + isRetreat: true + }); } this.postCombat.onResolveRetreatFinish(); diff --git a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/ArianneMartellHouseCardAbility.ts b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/ArianneMartellHouseCardAbility.ts index a1c7952ab..f98c965a7 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/ArianneMartellHouseCardAbility.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/ArianneMartellHouseCardAbility.ts @@ -18,9 +18,18 @@ export default class ArianneMartellHouseCardAbility extends HouseCardAbility { } forcesRetreatOfVictoriousDefender(postCombat: PostCombatGameState, house: House, houseCard: HouseCard): boolean { - return houseCard.id == "arianne-martell-asos" && + const result = houseCard.id == "arianne-martell-asos" && postCombat.attacker == house && postCombat.loser == house && Math.abs(postCombat.combat.stats[0].total - postCombat.combat.stats[1].total) <= 2; + + if (result) { + postCombat.combat.ingameGameState.log({ + type: "arianne-martell-force-retreat", + house: postCombat.loser.id, + enemyHouse: postCombat.winner.id + }); + } + return result; } }