From 88bc4f2170564a5ffabf1d2a220ff69f74686da1 Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Thu, 9 Jul 2026 21:05:01 +0200 Subject: [PATCH] fix bug where selecting the same ship again in a shipyard clears the layout and resets the progress --- src/lib/sim/BuildingSystem.cpp | 12 ++++++++++++ src/test/ShipModuleTest.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/lib/sim/BuildingSystem.cpp b/src/lib/sim/BuildingSystem.cpp index ba86d05..87d11c0 100644 --- a/src/lib/sim/BuildingSystem.cpp +++ b/src/lib/sim/BuildingSystem.cpp @@ -419,6 +419,12 @@ void BuildingSystem::setRecipe(BuildingId id, const std::string& recipeId) { if (site.id == id) { + // No-op if the recipe is unchanged, so a redundant selection does + // not wipe an already-configured ship layout. + if (site.recipeId == recipeId) + { + return; + } site.recipeId = recipeId; site.shipLayout = std::nullopt; return; @@ -430,6 +436,12 @@ void BuildingSystem::setRecipe(BuildingId id, const std::string& recipeId) { if (building.id == id) { + // No-op if the recipe is unchanged, so a redundant selection does + // not wipe an already-configured ship layout or reset buffers. + if (building.recipeId == recipeId) + { + return; + } building.recipeId = recipeId; building.shipLayout = std::nullopt; building.inputBuffer.counts.clear(); diff --git a/src/test/ShipModuleTest.cpp b/src/test/ShipModuleTest.cpp index a9bf9c0..5ffcf9f 100644 --- a/src/test/ShipModuleTest.cpp +++ b/src/test/ShipModuleTest.cpp @@ -292,6 +292,38 @@ TEST_CASE("Shipyard: setRecipe clears ship layout", "[modules][shipyard]") CHECK_FALSE(b2->shipLayout.has_value()); } +TEST_CASE("Shipyard: setRecipe with unchanged recipe keeps ship layout", + "[modules][shipyard]") +{ + Simulation sim(loadConfig(), 42); + const BuildingDef* yardDef = findShipyardDef(sim.config()); + REQUIRE(yardDef != nullptr); + + const BuildingId yardId = placeShipyard(sim, *yardDef); + SimulationTestAccess::buildings(sim).setRecipe(yardId,"interceptor"); + + ShipLayoutConfig layout; + PlacedModule pm; + pm.moduleId = "armor_plate"; + pm.position = QPoint(0, 0); + pm.rotation = Rotation::East; + layout.placedModules.push_back(pm); + SimulationTestAccess::buildings(sim).setShipLayout(yardId, layout); + + const Building* b1 = sim.buildings().findBuilding(yardId); + REQUIRE(b1 != nullptr); + REQUIRE(b1->shipLayout.has_value()); + + // Re-selecting the same recipe must be a no-op and preserve the layout. + SimulationTestAccess::buildings(sim).setRecipe(yardId,"interceptor"); + + const Building* b2 = sim.buildings().findBuilding(yardId); + REQUIRE(b2 != nullptr); + REQUIRE(b2->shipLayout.has_value()); + REQUIRE(b2->shipLayout->placedModules.size() == 1); + CHECK(b2->shipLayout->placedModules[0].moduleId == "armor_plate"); +} + // --------------------------------------------------------------------------- // Weapon modifier simulation tests // ---------------------------------------------------------------------------