Move FlightPlan ownership from Flight to IBuilder.

The next step in splitting up the layout and scheduling phases. This
facilitates splitting flights into two classes where one has a full
flight plan, but one used in the earlier phases of planning has only a
layout. Layout-only flights won't need TOTs, which will make them much
easier to work with once we've migrated TOTs from timedeltas to
datetimes.

Layout-only flights of course aren't actually usable, but it lets us
avoid dealing with the current sim time until we're certain the Flight
will even survive planning.

I'm not actually sure if we'll be able to split the two phases any more,
but this ends up being a nice cleanup anyway.
This commit is contained in:
Dan Albert 2022-08-21 22:33:24 -07:00 committed by Raffson
parent 71f9c6c28c
commit 96a5a8e2ef
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
2 changed files with 37 additions and 32 deletions

View File

@ -7,13 +7,10 @@ from typing import Any, List, Optional, TYPE_CHECKING
from dcs import Point from dcs import Point
from dcs.planes import C_101CC, C_101EB, Su_33 from dcs.planes import C_101CC, C_101EB, Su_33
from .flightplans.planningerror import PlanningError
from .flightplans.waypointbuilder import WaypointBuilder
from .flightroster import FlightRoster from .flightroster import FlightRoster
from .flightstate import FlightState, Navigating, Uninitialized from .flightstate import FlightState, Navigating, Uninitialized
from .flightstate.killed import Killed from .flightstate.killed import Killed
from .loadouts import Loadout from .loadouts import Loadout
from .packagewaypoints import PackageWaypoints
from ..sidc import ( from ..sidc import (
Entity, Entity,
SidcDescribable, SidcDescribable,
@ -85,15 +82,13 @@ class Flight(SidcDescribable):
# Will be replaced with a more appropriate FlightPlan later, but start with a # Will be replaced with a more appropriate FlightPlan later, but start with a
# cheaply constructed one since adding more flights to the package may affect # cheaply constructed one since adding more flights to the package may affect
# the optimal layout. # the optimal layout.
from .flightplans.custom import CustomFlightPlan, CustomLayout from .flightplans.flightplanbuildertypes import FlightPlanBuilderTypes
self.flight_plan: FlightPlan[Any] = CustomFlightPlan( self._flight_plan_builder = FlightPlanBuilderTypes.for_flight(self)(self)
self,
CustomLayout( @property
departure=WaypointBuilder(self, self.coalition).takeoff(self.departure), def flight_plan(self) -> FlightPlan[Any]:
custom_waypoints=[], return self._flight_plan_builder.get_or_build()
),
)
def __getstate__(self) -> dict[str, Any]: def __getstate__(self) -> dict[str, Any]:
state = self.__dict__.copy() state = self.__dict__.copy()
@ -199,13 +194,14 @@ class Flight(SidcDescribable):
def abort(self) -> None: def abort(self) -> None:
from .flightplans.rtb import RtbFlightPlan from .flightplans.rtb import RtbFlightPlan
self.flight_plan = RtbFlightPlan.builder_type()(self).build() self._flight_plan_builder = RtbFlightPlan.builder_type()(self)
plan = self._flight_plan_builder.get_or_build()
self.set_state( self.set_state(
Navigating( Navigating(
self, self,
self.squadron.settings, self.squadron.settings,
self.flight_plan.abort_index, plan.abort_index,
has_aborted=True, has_aborted=True,
) )
) )
@ -250,22 +246,4 @@ class Flight(SidcDescribable):
results.kill_pilot(self, pilot) results.kill_pilot(self, pilot)
def recreate_flight_plan(self) -> None: def recreate_flight_plan(self) -> None:
self.flight_plan = self._make_flight_plan() self._flight_plan_builder.regenerate()
def _make_flight_plan(self) -> FlightPlan[Any]:
from game.navmesh import NavMeshError
from .flightplans.flightplanbuildertypes import FlightPlanBuilderTypes
try:
if self.package.waypoints is None:
self.package.waypoints = PackageWaypoints.create(
self.package, self.coalition
)
builder = FlightPlanBuilderTypes.for_flight(self)(self)
return builder.build()
except NavMeshError as ex:
color = "blue" if self.squadron.player else "red"
raise PlanningError(
f"Could not plan {color} {self.flight_type.value} from "
f"{self.departure} to {self.package.target}"
) from ex

View File

@ -3,7 +3,10 @@ from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, Generic, TYPE_CHECKING, TypeVar from typing import Any, Generic, TYPE_CHECKING, TypeVar
from game.navmesh import NavMeshError
from .flightplan import FlightPlan, Layout from .flightplan import FlightPlan, Layout
from .planningerror import PlanningError
from ..packagewaypoints import PackageWaypoints
if TYPE_CHECKING: if TYPE_CHECKING:
from game.coalition import Coalition from game.coalition import Coalition
@ -21,6 +24,30 @@ LayoutT = TypeVar("LayoutT", bound=Layout)
class IBuilder(ABC, Generic[FlightPlanT, LayoutT]): class IBuilder(ABC, Generic[FlightPlanT, LayoutT]):
def __init__(self, flight: Flight) -> None: def __init__(self, flight: Flight) -> None:
self.flight = flight self.flight = flight
self._flight_plan: FlightPlanT | None = None
def get_or_build(self) -> FlightPlanT:
if self._flight_plan is None:
self.regenerate()
assert self._flight_plan is not None
return self._flight_plan
def regenerate(self) -> None:
try:
self._generate_package_waypoints_if_needed()
self._flight_plan = self.build()
except NavMeshError as ex:
color = "blue" if self.flight.squadron.player else "red"
raise PlanningError(
f"Could not plan {color} {self.flight.flight_type.value} from "
f"{self.flight.departure} to {self.package.target}"
) from ex
def _generate_package_waypoints_if_needed(self) -> None:
if self.package.waypoints is None:
self.package.waypoints = PackageWaypoints.create(
self.package, self.coalition
)
@property @property
def theater(self) -> ConflictTheater: def theater(self) -> ConflictTheater: