From d0232ce1bce98ab802cf8c5b1337dec5b9cf44ae Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 22 Oct 2026 12:51:23 -0400 Subject: [PATCH] Remove planets that are not in the game only when the game is saved The repair ran on every load too, including the copy each queued render takes, so an ended game that nobody saves logged the same removals on every load without ever keeping them. It now runs only on save, where the removal is written and logged once. A player area skips a missing planet's card without logging. Co-Authored-By: Claude Opus 5.5 --- .../ti4/game/persistence/GameSaveService.java | 1 + .../persistence/TransientGameInfoUpdater.java | 3 +-- .../java/ti4/image/playerarea/PlanetCard.java | 7 +------ .../TransientGameInfoUpdaterTest.java | 18 ++++++++++++++++-- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/ti4/game/persistence/GameSaveService.java b/src/main/java/ti4/game/persistence/GameSaveService.java index c417967125..8af4abc0ef 100644 --- a/src/main/java/ti4/game/persistence/GameSaveService.java +++ b/src/main/java/ti4/game/persistence/GameSaveService.java @@ -99,6 +99,7 @@ private static boolean save(Game game) { } private static void updateBeforeSave(Game game) { + TransientGameInfoUpdater.removePlanetsMissingFromTheGame(game); TransientGameInfoUpdater.update(game); // Ugly fix to update seen tiles data for fog since doing it in diff --git a/src/main/java/ti4/game/persistence/TransientGameInfoUpdater.java b/src/main/java/ti4/game/persistence/TransientGameInfoUpdater.java index 52ed06b8f8..8efb36bc1b 100644 --- a/src/main/java/ti4/game/persistence/TransientGameInfoUpdater.java +++ b/src/main/java/ti4/game/persistence/TransientGameInfoUpdater.java @@ -22,7 +22,6 @@ class TransientGameInfoUpdater { static void update(Game game) { try { - removePlanetsMissingFromTheGame(game); ButtonHelperFactionSpecific.checkIihqAttachment(game); DiscordantStarsHelper.checkGardenWorlds(game); DiscordantStarsHelper.checkTFTerraform(game); @@ -46,7 +45,7 @@ static void update(Game game) { } } - private static void removePlanetsMissingFromTheGame(Game game) { + static void removePlanetsMissingFromTheGame(Game game) { Set knownPlanets = game.getPlanetsInfo().keySet(); for (Player player : game.getPlayers().values()) { for (String planet : new ArrayList<>(player.getPlanets())) { diff --git a/src/main/java/ti4/image/playerarea/PlanetCard.java b/src/main/java/ti4/image/playerarea/PlanetCard.java index c8eb66eb1d..f442deb8f9 100644 --- a/src/main/java/ti4/image/playerarea/PlanetCard.java +++ b/src/main/java/ti4/image/playerarea/PlanetCard.java @@ -55,12 +55,7 @@ static int draw(PlayerAreaContext ctx, Player player, String planetName, int x, List exhaustedPlanetsAbilities = player.getExhaustedPlanetsAbilities(); try { Planet planet = game.getPlanetsInfo().get(planetName); - if (planet == null) { - BotLogger.warning( - new LogOrigin(player), - "Planet " + planetName + " not found in game " + game.getName() + ". Skipping its card."); - return deltaX; - } + if (planet == null) return deltaX; PlanetModel planetModel = planet.getPlanetModel(); if (planetModel == null) return deltaX; diff --git a/src/test/java/ti4/game/persistence/TransientGameInfoUpdaterTest.java b/src/test/java/ti4/game/persistence/TransientGameInfoUpdaterTest.java index bcbaff63fe..20efa752e5 100644 --- a/src/test/java/ti4/game/persistence/TransientGameInfoUpdaterTest.java +++ b/src/test/java/ti4/game/persistence/TransientGameInfoUpdaterTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.StringWriter; import java.util.HashSet; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,13 +31,26 @@ void setUp() { } @Test - void planetsThatAreNotInTheGameAreRemovedFromThePlayersWhenTheGameIsUpdated() { + void planetsThatAreNotInTheGameAreRemovedFromThePlayers() { holder.addPlanet("quann"); holder.addPlanet("nosuchplanet"); - TransientGameInfoUpdater.update(game); + TransientGameInfoUpdater.removePlanetsMissingFromTheGame(game); assertTrue(holder.getPlanets().contains("quann")); assertFalse(holder.getPlanets().contains("nosuchplanet")); } + + // Loading runs on every read, including the copy each queued render takes, so it must leave the repair to the + // save; otherwise an ended game nobody saves logs the same removal on every load. + @Test + void loadingAGameKeepsPlanetsThatAreNotInTheGame() throws Exception { + holder.addPlanet("nosuchplanet"); + StringWriter saved = new StringWriter(); + GameSaveService.writeGame(game, saved); + + Game loaded = GameLoadService.readGame(saved.toString().lines().toList()); + + assertTrue(loaded.getPlayer("111").getPlanets().contains("nosuchplanet")); + } }