dcs-retribution/game/layout/layoutmapping.py
RndName 2c17a9a52e Refactor Templates to Layouts, Review and Cleanup
- Fix tgogenerator
- Fix UI for ForceGroup and Layouts
- Fix ammo depot handling
- Split bigger files in smaller meaningful files (TGO, layouts, forces)
- Renamed Template to Layout
- Renamed GroundGroup to TheaterGroup and GroundUnit to TheaterUnit
- Reorganize Layouts and UnitGroups to a ArmedForces class and ForceGroup similar to the AirWing and Squadron
- Reworded the UnitClass, GroupRole, GroupTask (adopted to PEP8) and reworked the connection from Role and Task
- added comments
- added missing unit classes
- added temp workaround for missing classes
- add repariable property to TheaterUnit
- Review and Cleanup

Added serialization for loaded templates

Loading the templates from the .miz files takes a lot of computation time and in the future there will be more templates added to the system. Therefore a local pickle serialization for the loaded templates was re-added:
- The pickle will be created the first time the TemplateLoader will be accessed
- Pickle is stored in Liberation SaveDir
- Added UI option to (re-)import templates
2022-02-21 20:45:41 +01:00

157 lines
5.0 KiB
Python

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Type
from dcs.unittype import UnitType as DcsUnitType
from game import db
from game.data.groups import GroupRole, GroupTask
from game.data.units import UnitClass
@dataclass
class GroupLayoutMapping:
# The group name used in the template.miz
name: str
# Defines if the group is required for the template or can be skipped
optional: bool = False
# All static units for the group
statics: list[str] = field(default_factory=list)
# Defines to which tgo group the groupTemplate will be added
# This allows to merge groups back together. Default: Merge all to group 1
group: int = field(default=1)
# How many units should be generated from the grouplayout. If only one value is
# added this will be an exact amount. If 2 values are used it will be a random
# amount between these values.
unit_count: list[int] = field(default_factory=list)
# All unit types the template supports.
unit_types: list[Type[DcsUnitType]] = field(default_factory=list)
# All unit classes the template supports.
unit_classes: list[UnitClass] = field(default_factory=list)
# TODO Clarify if this is required. Only used for EWRs to also Use SR when no
# dedicated EWRs are available to the faction
alternative_classes: list[UnitClass] = field(default_factory=list)
def to_dict(self) -> dict[str, Any]:
d = self.__dict__
if not self.optional:
d.pop("optional")
if not self.statics:
d.pop("statics")
if not self.unit_types:
d.pop("unit_types")
if not self.unit_classes:
d.pop("unit_classes")
else:
d["unit_classes"] = [unit_class.value for unit_class in self.unit_classes]
if not self.alternative_classes:
d.pop("alternative_classes")
else:
d["alternative_classes"] = [
unit_class.value for unit_class in self.alternative_classes
]
if not self.unit_count:
d.pop("unit_count")
return d
@staticmethod
def from_dict(d: dict[str, Any]) -> GroupLayoutMapping:
optional = d["optional"] if "optional" in d else False
statics = d["statics"] if "statics" in d else []
unit_count = d["unit_count"] if "unit_count" in d else []
unit_types = []
if "unit_types" in d:
for u in d["unit_types"]:
unit_type = db.unit_type_from_name(u)
if unit_type:
unit_types.append(unit_type)
group = d["group"] if "group" in d else 1
unit_classes = (
[UnitClass(u) for u in d["unit_classes"]] if "unit_classes" in d else []
)
alternative_classes = (
[UnitClass(u) for u in d["alternative_classes"]]
if "alternative_classes" in d
else []
)
return GroupLayoutMapping(
d["name"],
optional,
statics,
group,
unit_count,
unit_types,
unit_classes,
alternative_classes,
)
@dataclass
class LayoutMapping:
# The name of the Template
name: str
# An optional description to give more information about the template
description: str
# Optional field to define if the template can be used to create generic groups
generic: bool
# The role the template can be used for
role: GroupRole
# All taskings the template can be used for
tasks: list[GroupTask]
# All Groups the template has
groups: list[GroupLayoutMapping]
# Define the miz file for the template. Optional. If empty use the mapping name
layout_file: str
def to_dict(self) -> dict[str, Any]:
d = {
"name": self.name,
"description": self.description,
"generic": self.generic,
"role": self.role.value,
"tasks": [task.description for task in self.tasks],
"groups": [group.to_dict() for group in self.groups],
"layout_file": self.layout_file,
}
if not self.description:
d.pop("description")
if not self.generic:
# Only save if true
d.pop("generic")
if not self.layout_file:
d.pop("layout_file")
return d
@staticmethod
def from_dict(d: dict[str, Any], file_name: str) -> LayoutMapping:
groups = [GroupLayoutMapping.from_dict(group) for group in d["groups"]]
description = d["description"] if "description" in d else ""
generic = d["generic"] if "generic" in d else False
layout_file = (
d["layout_file"] if "layout_file" in d else file_name.replace("yaml", "miz")
)
tasks = [GroupTask.by_description(task) for task in d["tasks"]]
return LayoutMapping(
d["name"],
description,
generic,
GroupRole(d["role"]),
tasks,
groups,
layout_file,
)