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 // ---------------------------------------------------------------------------