diff --git a/game/factions/__init__.py b/game/factions/__init__.py index a4d7fa86..6b678491 100644 --- a/game/factions/__init__.py +++ b/game/factions/__init__.py @@ -1,4 +1 @@ from .faction import Faction -from .factionloader import FactionLoader - -FACTIONS = FactionLoader() diff --git a/game/factions/factionloader.py b/game/factions/factionloader.py deleted file mode 100644 index d6b91518..00000000 --- a/game/factions/factionloader.py +++ /dev/null @@ -1,55 +0,0 @@ -from __future__ import annotations - -import json -import logging -from pathlib import Path -from typing import Dict, Iterator, List, Optional, Type - -from game import persistence -from game.factions.faction import Faction - -FACTION_DIRECTORY = Path("./resources/factions/") - - -class FactionLoader: - def __init__(self) -> None: - self._factions: Optional[Dict[str, Faction]] = None - - @property - def factions(self) -> Dict[str, Faction]: - self.initialize() - assert self._factions is not None - return self._factions - - def initialize(self) -> None: - if self._factions is None: - self._factions = self.load_factions() - - @staticmethod - def find_faction_files_in(path: Path) -> List[Path]: - return [f for f in path.glob("*.json") if f.is_file()] - - @classmethod - def load_factions(cls: Type[FactionLoader]) -> Dict[str, Faction]: - user_faction_path = Path(persistence.base_path()) / "Liberation/Factions" - files = cls.find_faction_files_in( - FACTION_DIRECTORY - ) + cls.find_faction_files_in(user_faction_path) - factions = {} - - for f in files: - try: - with f.open("r", encoding="utf-8") as fdata: - data = json.load(fdata) - factions[data["name"]] = Faction.from_json(data) - logging.info("Loaded faction : " + str(f)) - except Exception: - logging.exception(f"Unable to load faction : {f}") - - return factions - - def __getitem__(self, name: str) -> Faction: - return self.factions[name] - - def __iter__(self) -> Iterator[str]: - return iter(self.factions.keys()) diff --git a/game/factions/factions.py b/game/factions/factions.py new file mode 100644 index 00000000..c22a2cae --- /dev/null +++ b/game/factions/factions.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +import json +import logging +from collections.abc import Iterator +from pathlib import Path + +from game import persistence +from .faction import Faction + + +class Factions: + def __init__(self, factions: dict[str, Faction]) -> None: + self.factions = factions + + def get_by_name(self, name: str) -> Faction: + return self.factions[name] + + def iter_faction_names(self) -> Iterator[str]: + return iter(self.factions.keys()) + + @staticmethod + def iter_faction_files_in(path: Path) -> Iterator[Path]: + yield from path.glob("*.json") + + @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: + data = json.load(fdata) + faction = Faction.from_json(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) diff --git a/qt_ui/main.py b/qt_ui/main.py index 33630cdd..7ea181a1 100644 --- a/qt_ui/main.py +++ b/qt_ui/main.py @@ -17,7 +17,7 @@ from game import Game, VERSION, logging_config, persistence from game.campaignloader.campaign import Campaign, DEFAULT_BUDGET from game.data.weapons import Pylon, Weapon, WeaponGroup from game.dcs.aircrafttype import AircraftType -from game.factions import FACTIONS +from game.factions.factions import Factions from game.profiling import logged_duration from game.server import EventStream, Server from game.settings import Settings @@ -275,9 +275,10 @@ def create_game( inject_custom_payloads(Path(persistence.base_path())) campaign = Campaign.from_file(campaign_path) theater = campaign.load_theater(advanced_iads) + faction_loader = Factions.load() generator = GameGenerator( - FACTIONS[blue], - FACTIONS[red], + faction_loader.get_by_name(blue), + faction_loader.get_by_name(red), theater, campaign.load_air_wing_config(theater), Settings( diff --git a/qt_ui/windows/newgame/QNewGameWizard.py b/qt_ui/windows/newgame/QNewGameWizard.py index 531a7a08..d6a17732 100644 --- a/qt_ui/windows/newgame/QNewGameWizard.py +++ b/qt_ui/windows/newgame/QNewGameWizard.py @@ -10,7 +10,8 @@ from PySide6.QtWidgets import QCheckBox, QLabel, QTextEdit, QVBoxLayout from jinja2 import Environment, FileSystemLoader, select_autoescape from game.campaignloader.campaign import Campaign, DEFAULT_BUDGET -from game.factions import FACTIONS, Faction +from game.factions import Faction +from game.factions.factions import Factions from game.settings import Settings from game.theater.start_generator import GameGenerator, GeneratorSettings, ModSettings from qt_ui.widgets.QLiberationCalendar import QLiberationCalendar @@ -224,6 +225,8 @@ class FactionSelection(QtWidgets.QWizardPage): def __init__(self, parent=None): super(FactionSelection, self).__init__(parent) + self.factions = Factions.load() + self.setTitle("Faction selection") self.setSubTitle( "\nChoose the two opposing factions and select the player side." @@ -243,7 +246,7 @@ class FactionSelection(QtWidgets.QWizardPage): blueFaction = QtWidgets.QLabel("Player Faction :") self.blueFactionSelect = QtWidgets.QComboBox() - for f in FACTIONS: + for f in self.factions.iter_faction_names(): self.blueFactionSelect.addItem(f) blueFaction.setBuddy(self.blueFactionSelect) @@ -259,7 +262,7 @@ class FactionSelection(QtWidgets.QWizardPage): self.redFactionDescription.setReadOnly(True) # Setup default selected factions - for i, r in enumerate(FACTIONS): + for i, r in enumerate(self.factions.iter_faction_names()): self.redFactionSelect.addItem(r) if r == "Russia 1990": self.redFactionSelect.setCurrentIndex(i) @@ -305,10 +308,10 @@ class FactionSelection(QtWidgets.QWizardPage): self.blueFactionSelect.clear() self.redFactionSelect.clear() - for f in FACTIONS: + for f in self.factions.iter_faction_names(): self.blueFactionSelect.addItem(f) - for i, r in enumerate(FACTIONS): + for i, r in enumerate(self.factions.iter_faction_names()): self.redFactionSelect.addItem(r) if r == campaign.recommended_enemy_faction: self.redFactionSelect.setCurrentIndex(i) @@ -318,9 +321,8 @@ class FactionSelection(QtWidgets.QWizardPage): self.updateUnitRecap() def updateUnitRecap(self): - - red_faction = FACTIONS[self.redFactionSelect.currentText()] - blue_faction = FACTIONS[self.blueFactionSelect.currentText()] + red_faction = self.factions.get_by_name(self.redFactionSelect.currentText()) + blue_faction = self.factions.get_by_name(self.blueFactionSelect.currentText()) template = jinja_env.get_template("factiontemplate_EN.j2") @@ -332,11 +334,11 @@ class FactionSelection(QtWidgets.QWizardPage): @property def selected_blue_faction(self) -> Faction: - return FACTIONS[self.blueFactionSelect.currentText()] + return self.factions.get_by_name(self.blueFactionSelect.currentText()) @property def selected_red_faction(self) -> Faction: - return FACTIONS[self.redFactionSelect.currentText()] + return self.factions.get_by_name(self.redFactionSelect.currentText()) class TheaterConfiguration(QtWidgets.QWizardPage):