mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
This PR refactors the Doctrine class to load from YAML files in the resources folder instead of being hardcoded as a step towards making doctrines moddable (Issue #829). I haven't added anything to the changelog as a couple of things should get cleaned up first: - As far as I can tell, the flags in the Doctrine class (cap, cas, sead etc.) aren't used anywhere. Need to test further, and if they're truly not used, will remove them. - Probably need to update the Wiki
77 lines
2.6 KiB
Python
77 lines
2.6 KiB
Python
import json
|
|
from functools import cached_property
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from dcs.mapping import Point as DcsPoint, LatLng
|
|
from dcs.terrain import Terrain
|
|
from numpy import float64, array
|
|
from numpy._typing import NDArray
|
|
from shapely import transform
|
|
from shapely.geometry import shape
|
|
from shapely.geometry.base import BaseGeometry
|
|
|
|
from game.data.doctrine import Doctrine
|
|
from .ipsolver import IpSolver
|
|
from .waypointsolver import WaypointSolver
|
|
from ..theater.theaterloader import TERRAINS_BY_NAME
|
|
|
|
|
|
def doctrine_from_name(name: str) -> Doctrine:
|
|
return Doctrine.named(name)
|
|
|
|
|
|
def geometry_ll_to_xy(geometry: BaseGeometry, terrain: Terrain) -> BaseGeometry:
|
|
if geometry.is_empty:
|
|
return geometry
|
|
|
|
def ll_to_xy(points: NDArray[float64]) -> NDArray[float64]:
|
|
ll_points = []
|
|
for point in points:
|
|
# Longitude is unintuitively first because it's the "X" coordinate:
|
|
# https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.1
|
|
p = DcsPoint.from_latlng(LatLng(point[1], point[0]), terrain)
|
|
ll_points.append([p.x, p.y])
|
|
return array(ll_points)
|
|
|
|
return transform(geometry, ll_to_xy)
|
|
|
|
|
|
class WaypointSolverLoader:
|
|
def __init__(self, debug_info_path: Path) -> None:
|
|
self.debug_info_path = debug_info_path
|
|
|
|
def load_data(self) -> dict[str, Any]:
|
|
with self.debug_info_path.open(encoding="utf-8") as debug_info_file:
|
|
return json.load(debug_info_file)
|
|
|
|
@staticmethod
|
|
def load_geometries(
|
|
feature_collection: dict[str, Any], terrain: Terrain
|
|
) -> dict[str, BaseGeometry]:
|
|
geometries = {}
|
|
for feature in feature_collection["features"]:
|
|
description = feature["properties"]["description"]
|
|
geometry = shape(feature["geometry"])
|
|
geometries[description] = geometry_ll_to_xy(geometry, terrain)
|
|
return geometries
|
|
|
|
@cached_property
|
|
def terrain(self) -> Terrain:
|
|
return TERRAINS_BY_NAME[self.load_data()["metadata"]["terrain"]]
|
|
|
|
def load(self) -> WaypointSolver:
|
|
data = self.load_data()
|
|
metadata = data["metadata"]
|
|
name = metadata.pop("name")
|
|
terrain_name = metadata.pop("terrain")
|
|
terrain = TERRAINS_BY_NAME[terrain_name]
|
|
if "doctrine" in metadata:
|
|
metadata["doctrine"] = doctrine_from_name(metadata["doctrine"])
|
|
geometries = self.load_geometries(data, terrain)
|
|
builder: type[WaypointSolver] = {
|
|
"IpSolver": IpSolver,
|
|
}[name]
|
|
metadata.update(geometries)
|
|
return builder(**metadata)
|