mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
A lot of campaigns want to define custom factions. This allows them to do so without us having to fill the built-in factions list with a bunch of campaign-specific factions. It also makes custom campaigns more portable as they don't need to also distribute the custom faction files.
71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
import itertools
|
|
import json
|
|
import logging
|
|
from collections.abc import Iterator
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
from game import persistence
|
|
from .faction import Faction
|
|
|
|
|
|
class Factions:
|
|
def __init__(self, factions: dict[str, Faction]) -> None:
|
|
self.factions = factions
|
|
self.campaign_defined_factions: dict[str, Faction] = {}
|
|
|
|
def get_by_name(self, name: str) -> Faction:
|
|
try:
|
|
return self.factions[name]
|
|
except KeyError:
|
|
return self.campaign_defined_factions[name]
|
|
|
|
def iter_faction_names(self) -> Iterator[str]:
|
|
# Campaign defined factions first so they show up at the top of the list in the
|
|
# UI.
|
|
return itertools.chain(self.campaign_defined_factions, self.factions)
|
|
|
|
def add_campaign_defined(self, faction: Faction) -> None:
|
|
if (
|
|
faction.name in self.factions
|
|
or faction.name in self.campaign_defined_factions
|
|
):
|
|
raise KeyError(f"Duplicate faction {faction.name}")
|
|
self.campaign_defined_factions[faction.name] = faction
|
|
|
|
def reset_campaign_defined(self) -> None:
|
|
self.campaign_defined_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]:
|
|
yield from cls.iter_faction_files_in(Path("resources/factions/"))
|
|
yield from cls.iter_faction_files_in(
|
|
Path(persistence.base_path()) / "Liberation/Factions"
|
|
)
|
|
|
|
@classmethod
|
|
def load(cls) -> Factions:
|
|
factions = {}
|
|
for path in cls.iter_faction_files():
|
|
try:
|
|
with path.open("r", encoding="utf-8") as fdata:
|
|
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:
|
|
logging.exception(f"Unable to load faction from %s", path)
|
|
|
|
return Factions(factions)
|