diff --git a/dcs/mission.py b/dcs/mission.py index e237dfc5..e464d289 100644 --- a/dcs/mission.py +++ b/dcs/mission.py @@ -1022,6 +1022,10 @@ def _load_tasks(mp: MovingPoint, maintask: Type[task.MainTask]): def update_warehouses(self): """Some units need to have warehouse entries. This function updates warehouse entries based on units defined in the mission. + + Gap-fill only: units that need a warehouse entry but do not have one get a default, while existing entries + are preserved. Without this guard the entries were overwritten with defaults on every save, discarding any + customized warehouse configuration for ships and FARPs. """ coalition_to_warehouse_names = {'red': 'RED', 'blue': 'BLUE', 'neutrals': 'NEUTRAL'} for coalition_name in self.coalition: @@ -1030,13 +1034,13 @@ def update_warehouses(self): # Ships that can have aircraft parked need a warehouse entry. for ship_group in self.coalition[coalition_name].countries[country_name].ship_group: for unit_ in ship_group.units: - if ships.ship_map[unit_.type].parking > 0: + if ships.ship_map[unit_.type].parking > 0 and int(unit_.id) not in self.warehouses.warehouses: self.warehouses.warehouses[int(unit_.id)] = terrain_.terrain.Warehouse().dict() self.warehouses.warehouses[int(unit_.id)]['coalition'] = coalition_name_in_warehouse # FARPs need a warehouse entry. for static_group in self.coalition[coalition_name].countries[country_name].static_group: for unit_ in static_group.units: - if isinstance(unit_, unit.BaseFARP): + if isinstance(unit_, unit.BaseFARP) and int(unit_.id) not in self.warehouses.warehouses: self.warehouses.warehouses[int(unit_.id)] = terrain_.terrain.Warehouse().dict() self.warehouses.warehouses[int(unit_.id)]['coalition'] = coalition_name_in_warehouse diff --git a/tests/test_mission.py b/tests/test_mission.py index 4c86900b..591f3344 100644 --- a/tests/test_mission.py +++ b/tests/test_mission.py @@ -1476,3 +1476,39 @@ def test_ground_control_password(self) -> None: self.assertIn(Coalition.Blue.value, m2.groundControl.dict()["passwords"][GroundControlRole.OBSERVER.value]) self.assertIn(Coalition.Red.value, m2.groundControl.dict()["passwords"][GroundControlRole.JTAC.value]) + + +class UpdateWarehousesTest(unittest.TestCase): + + def _carrier_unit_id(self, m): + # A carrier is a ship whose type has parking > 0 -- exactly the unit + # class update_warehouses() creates warehouse entries for (FARPs are the + # other; the gap-fill logic is identical for both). + group = m.ship_group( + m.country("USA"), "CSG", dcs.ships.Stennis, + dcs.mapping.Point(-290000, 620000, m.terrain), + ) + return int(group.units[0].id) + + def test_update_warehouses_preserves_existing_entries(self): + # update_warehouses() runs on every Mission.save(). It must NOT overwrite + # an existing (possibly customized) ship/FARP warehouse entry with a fresh + # default; before the gap-fill guard, custom warehouse config was lost on + # every save. + m = dcs.mission.Mission(terrain=dcs.terrain.Caucasus()) + uid = self._carrier_unit_id(m) + + m.warehouses.warehouses[uid] = {"coalition": "BLUE", "size": 42} + m.update_warehouses() + + self.assertEqual(m.warehouses.warehouses[uid]["size"], 42) + self.assertEqual(m.warehouses.warehouses[uid]["coalition"], "BLUE") + + def test_update_warehouses_gap_fills_missing_entries(self): + # A unit that needs a warehouse but has none still gets a default entry. + m = dcs.mission.Mission(terrain=dcs.terrain.Caucasus()) + uid = self._carrier_unit_id(m) + + self.assertNotIn(uid, m.warehouses.warehouses) + m.update_warehouses() + self.assertIn(uid, m.warehouses.warehouses)