mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Allow in-line definitions of campaign factions.
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.
This commit is contained in:
@@ -5,22 +5,24 @@ import logging
|
||||
from collections.abc import Iterator
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Tuple
|
||||
from typing import Any, Dict, TYPE_CHECKING, Tuple
|
||||
|
||||
import yaml
|
||||
from packaging.version import Version
|
||||
|
||||
from game import persistence
|
||||
from game.profiling import logged_duration
|
||||
from game.theater import (
|
||||
ConflictTheater,
|
||||
)
|
||||
from game.theater import ConflictTheater
|
||||
from game.theater.iadsnetwork.iadsnetwork import IadsNetwork
|
||||
from game.theater.theaterloader import TheaterLoader
|
||||
from game.version import CAMPAIGN_FORMAT_VERSION
|
||||
from .campaignairwingconfig import CampaignAirWingConfig
|
||||
from .factionrecommendation import FactionRecommendation
|
||||
from .mizcampaignloader import MizCampaignLoader
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.factions.factions import Factions
|
||||
|
||||
PERF_FRIENDLY = 0
|
||||
PERF_MEDIUM = 1
|
||||
PERF_HARD = 2
|
||||
@@ -40,8 +42,8 @@ class Campaign:
|
||||
#: selecting a campaign that is not up to date.
|
||||
version: Tuple[int, int]
|
||||
|
||||
recommended_player_faction: str
|
||||
recommended_enemy_faction: str
|
||||
recommended_player_faction: FactionRecommendation
|
||||
recommended_enemy_faction: FactionRecommendation
|
||||
recommended_start_date: datetime.date | None
|
||||
recommended_start_time: datetime.time | None
|
||||
|
||||
@@ -60,7 +62,6 @@ class Campaign:
|
||||
with path.open(encoding="utf-8") as campaign_file:
|
||||
data = yaml.safe_load(campaign_file)
|
||||
|
||||
sanitized_theater = data["theater"].replace(" ", "")
|
||||
version_field = data.get("version", "0")
|
||||
try:
|
||||
version = Version(version_field)
|
||||
@@ -93,8 +94,12 @@ class Campaign:
|
||||
data.get("authors", "???"),
|
||||
data.get("description", ""),
|
||||
(version.major, version.minor),
|
||||
data.get("recommended_player_faction", "USA 2005"),
|
||||
data.get("recommended_enemy_faction", "Russia 1990"),
|
||||
FactionRecommendation.from_field(
|
||||
data.get("recommended_player_faction"), player=True
|
||||
),
|
||||
FactionRecommendation.from_field(
|
||||
data.get("recommended_enemy_faction"), player=False
|
||||
),
|
||||
start_date,
|
||||
start_time,
|
||||
data.get("recommended_player_money", DEFAULT_BUDGET),
|
||||
@@ -163,6 +168,10 @@ class Campaign:
|
||||
return False
|
||||
return True
|
||||
|
||||
def register_campaign_specific_factions(self, factions: Factions) -> None:
|
||||
self.recommended_player_faction.register_campaign_specific_faction(factions)
|
||||
self.recommended_enemy_faction.register_campaign_specific_faction(factions)
|
||||
|
||||
@staticmethod
|
||||
def iter_campaigns_in_dir(path: Path) -> Iterator[Path]:
|
||||
yield from path.glob("*.yaml")
|
||||
|
||||
53
game/campaignloader/factionrecommendation.py
Normal file
53
game/campaignloader/factionrecommendation.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, TYPE_CHECKING
|
||||
|
||||
from game.factions import Faction
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.factions.factions import Factions
|
||||
|
||||
|
||||
class FactionRecommendation(ABC):
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
@abstractmethod
|
||||
def register_campaign_specific_faction(self, factions: Factions) -> None:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def get_faction(self, factions: Factions) -> Faction:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def from_field(
|
||||
data: str | dict[str, Any] | None, player: bool
|
||||
) -> FactionRecommendation:
|
||||
if data is None:
|
||||
name = "USA 2005" if player else "Russia 1990"
|
||||
return BuiltinFactionRecommendation(name)
|
||||
if isinstance(data, str):
|
||||
return BuiltinFactionRecommendation(data)
|
||||
return CampaignDefinedFactionRecommendation(Faction.from_dict(data))
|
||||
|
||||
|
||||
class BuiltinFactionRecommendation(FactionRecommendation):
|
||||
def register_campaign_specific_faction(self, factions: Factions) -> None:
|
||||
pass
|
||||
|
||||
def get_faction(self, factions: Factions) -> Faction:
|
||||
return factions.get_by_name(self.name)
|
||||
|
||||
|
||||
class CampaignDefinedFactionRecommendation(FactionRecommendation):
|
||||
def __init__(self, faction: Faction) -> None:
|
||||
super().__init__(faction.name)
|
||||
self.faction = faction
|
||||
|
||||
def register_campaign_specific_faction(self, factions: Factions) -> None:
|
||||
factions.add_campaign_defined(self.faction)
|
||||
|
||||
def get_faction(self, factions: Factions) -> Faction:
|
||||
return self.faction
|
||||
Reference in New Issue
Block a user