diff --git a/dcs/terrain/terrain.py b/dcs/terrain/terrain.py index ff79e6a3..49eb0df0 100644 --- a/dcs/terrain/terrain.py +++ b/dcs/terrain/terrain.py @@ -613,7 +613,14 @@ def __init__(self, terrain: Terrain): def load_dict(self, data): for x in data.get("airports", {}): - self.terrain.airport_by_id(x).load_from_dict(data["airports"][x]) + airport = self.terrain.airport_by_id(x) + if airport is None: + # Warehouse data references an airport id not present in the + # current terrain (e.g. a mission authored before a map update + # that renumbered or removed airports). Skip it rather than + # crash the whole load on None.load_from_dict(). + continue + airport.load_from_dict(data["airports"][x]) for uid, wh_data in data.get("warehouses", {}).items(): self.warehouses[int(uid)] = wh_data diff --git a/tests/test_terrain.py b/tests/test_terrain.py index 2516ab21..9d4d646e 100644 --- a/tests/test_terrain.py +++ b/tests/test_terrain.py @@ -111,6 +111,33 @@ def test_load_dict_reads_warehouses(self): self.assertEqual(m.warehouses.warehouses[4242]["coalition"], "BLUE") self.assertEqual(m.warehouses.warehouses[4242]["size"], 100) + def test_load_dict_skips_airport_absent_from_terrain(self): + # airport_by_id() returns None when warehouse data references an airport + # id not present in the current terrain (e.g. a mission authored before + # a map update that renumbered or removed airports). load_dict must + # skip the absent id instead of crashing on None.load_from_dict(), and + # must still load any valid airport entries in the same dict. + m = dcs.mission.Mission(terrain=dcs.terrain.Caucasus()) + + present = m.terrain.airport_by_id(12) # Anapa-Vityazevo + self.assertIsNotNone(present) + present_data = present.dict() + present_data["coalition"] = "BLUE" + present_data["size"] = 7777 + + # The absent id is iterated first, so the loop must continue past it to + # reach the present id. This must not raise. + m.warehouses.load_dict({ + "airports": { + 999999: {}, # not present in Caucasus -> airport_by_id() is None + 12: present_data, + }, + "warehouses": {}, + }) + + self.assertEqual(present.coalition, "BLUE") + self.assertEqual(present.size, 7777) + class NormandyTest(unittest.TestCase):