Allow factions to use YAML.

Comments! No more failures because you accidentally used a trailing
comma!

JSON still supported since it's basically free, but we should probably
remove that in 8 just so the docs can be less confusing for users who
will be confused if only one format is documented (and we definitely
won't maintain duplicate docs).
This commit is contained in:
Dan Albert 2023-04-17 22:14:44 -07:00
parent 42e9a6294b
commit 652e7d8d7b
4 changed files with 40 additions and 41 deletions

View File

@ -12,6 +12,7 @@ Saves from 6.x are not compatible with 7.0.
* **[Mission Generation]** The A-10C II now uses separate radios for inter- and intra-flight comms (similar to other modern aircraft).
* **[Modding]** Updated Community A-4E-C mod version support to 2.1.0 release.
* **[Modding]** Add support for VSN F-4B and F-4C mod.
* **[Modding]** Custom factions can now be defined in YAML as well as JSON. JSON support may be removed in the future if having both formats causes confusion.
## Fixes

View File

@ -4,33 +4,32 @@ import itertools
import logging
from dataclasses import dataclass, field
from functools import cached_property
from typing import Optional, Dict, Type, List, Any, Iterator, TYPE_CHECKING
from typing import Any, Dict, Iterator, List, Optional, TYPE_CHECKING, Type
import dcs
from dcs.countries import country_dict
from dcs.unittype import ShipType, StaticType
from dcs.unittype import UnitType as DcsUnitType
from dcs.unittype import ShipType, StaticType, UnitType as DcsUnitType
from game.armedforces.forcegroup import ForceGroup
from game.data.building_data import (
WW2_ALLIES_BUILDINGS,
DEFAULT_AVAILABLE_BUILDINGS,
WW2_GERMANY_BUILDINGS,
WW2_FREE,
REQUIRED_BUILDINGS,
IADS_BUILDINGS,
REQUIRED_BUILDINGS,
WW2_ALLIES_BUILDINGS,
WW2_FREE,
WW2_GERMANY_BUILDINGS,
)
from game.data.doctrine import (
COLDWAR_DOCTRINE,
Doctrine,
MODERN_DOCTRINE,
COLDWAR_DOCTRINE,
WWII_DOCTRINE,
)
from game.data.units import UnitClass
from game.data.groups import GroupRole
from game.data.units import UnitClass
from game.dcs.aircrafttype import AircraftType
from game.dcs.groundunittype import GroundUnitType
from game.dcs.shipunittype import ShipUnitType
from game.armedforces.forcegroup import ForceGroup
from game.dcs.unittype import UnitType
if TYPE_CHECKING:
@ -168,7 +167,7 @@ class Faction:
return sorted(air_defenses)
@classmethod
def from_json(cls: Type[Faction], json: Dict[str, Any]) -> Faction:
def from_dict(cls: Type[Faction], json: Dict[str, Any]) -> Faction:
faction = Faction(locales=json.get("locales"))
faction.country = json.get("country", "/")

View File

@ -5,6 +5,8 @@ import logging
from collections.abc import Iterator
from pathlib import Path
import yaml
from game import persistence
from .faction import Faction
@ -22,6 +24,7 @@ class Factions:
@staticmethod
def iter_faction_files_in(path: Path) -> Iterator[Path]:
yield from path.glob("*.json")
yield from path.glob("*.yaml")
@classmethod
def iter_faction_files(cls) -> Iterator[Path]:
@ -36,8 +39,11 @@ class Factions:
for path in cls.iter_faction_files():
try:
with path.open("r", encoding="utf-8") as fdata:
data = json.load(fdata)
faction = Faction.from_json(data)
if path.suffix == ".yaml":
data = yaml.safe_load(fdata)
else:
data = json.load(fdata)
faction = Faction.from_dict(data)
factions[faction.name] = faction
logging.info("Loaded faction from %s", path)
except Exception:

View File

@ -1,40 +1,33 @@
import json
from pathlib import Path
import unittest
import pytest
from pathlib import Path
from dcs.helicopters import UH_1H, AH_64A
import pytest
from dcs.helicopters import AH_64A, UH_1H
from dcs.planes import (
F_15C,
F_15E,
F_14B,
FA_18C_hornet,
F_16C_50,
A_10A,
AV8BNA,
B_52H,
B_1B,
F_117A,
MQ_9_Reaper,
E_3A,
E_2C,
KC130,
KC_135,
A_10A,
A_10C,
A_10C_2,
B_1B,
B_52H,
E_2C,
E_3A,
FA_18C_hornet,
F_117A,
F_14B,
F_15C,
F_15E,
F_16C_50,
KC130,
KC_135,
MQ_9_Reaper,
)
from dcs.ships import (
Stennis,
LHA_Tarawa,
PERRY,
USS_Arleigh_Burke_IIa,
TICONDEROG,
)
from dcs.vehicles import Armor, Unarmed, Infantry, Artillery
from dcs.ships import LHA_Tarawa, Stennis
from dcs.vehicles import Armor, Artillery, Infantry, Unarmed
from game.factions.faction import Faction
THIS_DIR = Path(__file__).parent
RESOURCES_DIR = THIS_DIR / "resources"
@ -46,7 +39,7 @@ class TestFactionLoader(unittest.TestCase):
@pytest.mark.skip(reason="Faction unit names in the json files are outdated")
def test_load_valid_faction(self) -> None:
with (RESOURCES_DIR / "valid_faction.json").open("r") as data:
faction = Faction.from_json(json.load(data))
faction = Faction.from_dict(json.load(data))
self.assertEqual(faction.country, "USA")
self.assertEqual(faction.name, "USA 2005")
@ -109,7 +102,7 @@ class TestFactionLoader(unittest.TestCase):
with (RESOURCES_DIR / "invalid_faction_country.json").open("r") as data:
try:
Faction.from_json(json.load(data))
Faction.from_dict(json.load(data))
self.fail("Should have thrown assertion error")
except AssertionError as e:
pass