mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Move FlightJs out of MapModel.
This commit is contained in:
@@ -17,8 +17,13 @@ class AirTaskingOrder:
|
||||
|
||||
def remove_package(self, package: Package) -> None:
|
||||
"""Removes a package from the ATO."""
|
||||
# Remove all the flights individually so the database gets updated.
|
||||
for flight in list(package.flights):
|
||||
package.remove_flight(flight)
|
||||
self.packages.remove(package)
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Removes all packages from the ATO."""
|
||||
self.packages.clear()
|
||||
# Remove all packages individually so the database gets updated.
|
||||
for package in self.packages:
|
||||
self.remove_package(package)
|
||||
|
||||
@@ -22,7 +22,7 @@ class Navigating(InFlight):
|
||||
self, events: GameUpdateEvents, time: datetime, duration: timedelta
|
||||
) -> None:
|
||||
super().on_game_tick(events, time, duration)
|
||||
events.update_flight(self.flight, self.estimate_position())
|
||||
events.update_flight_position(self.flight, self.estimate_position())
|
||||
|
||||
def progress(self) -> float:
|
||||
return (
|
||||
|
||||
@@ -129,6 +129,9 @@ class Package:
|
||||
"""Removes a flight from the package."""
|
||||
self.flights.remove(flight)
|
||||
self._db.remove(flight.id)
|
||||
flight.return_pilots_and_aircraft()
|
||||
if flight.cargo is not None:
|
||||
flight.cargo.transport = None
|
||||
if not self.flights:
|
||||
self.waypoints = None
|
||||
|
||||
|
||||
@@ -92,5 +92,4 @@ class PackageBuilder:
|
||||
"""Returns any planned flights to the inventory."""
|
||||
flights = list(self.package.flights)
|
||||
for flight in flights:
|
||||
flight.return_pilots_and_aircraft()
|
||||
self.package.remove_flight(flight)
|
||||
|
||||
@@ -6,6 +6,7 @@ from uuid import UUID
|
||||
from pydantic import BaseModel
|
||||
|
||||
from game.server.combat.models import FrozenCombatJs
|
||||
from game.server.flights.models import FlightJs
|
||||
from game.server.leaflet import LeafletLatLon
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -14,18 +15,24 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class GameUpdateEventsJs(BaseModel):
|
||||
updated_flights: dict[UUID, LeafletLatLon]
|
||||
new_combats: list[FrozenCombatJs] = []
|
||||
updated_combats: list[FrozenCombatJs] = []
|
||||
navmesh_updates: set[bool] = set()
|
||||
unculled_zones_updated: bool = False
|
||||
threat_zones_updated: bool = False
|
||||
updated_flight_positions: dict[UUID, LeafletLatLon]
|
||||
new_combats: list[FrozenCombatJs]
|
||||
updated_combats: list[FrozenCombatJs]
|
||||
navmesh_updates: set[bool]
|
||||
unculled_zones_updated: bool
|
||||
threat_zones_updated: bool
|
||||
new_flights: list[FlightJs]
|
||||
updated_flights: set[UUID]
|
||||
deleted_flights: set[UUID]
|
||||
selected_flight: UUID | None
|
||||
deselected_flight: bool
|
||||
|
||||
@classmethod
|
||||
def from_events(cls, events: GameUpdateEvents, game: Game) -> GameUpdateEventsJs:
|
||||
return GameUpdateEventsJs(
|
||||
updated_flights={
|
||||
f[0].id: f[1].latlng().as_list() for f in events.updated_flights
|
||||
updated_flight_positions={
|
||||
f[0].id: f[1].latlng().as_list()
|
||||
for f in events.updated_flight_positions
|
||||
},
|
||||
new_combats=[
|
||||
FrozenCombatJs.for_combat(c, game.theater) for c in events.new_combats
|
||||
@@ -37,4 +44,9 @@ class GameUpdateEventsJs(BaseModel):
|
||||
navmesh_updates=events.navmesh_updates,
|
||||
unculled_zones_updated=events.unculled_zones_updated,
|
||||
threat_zones_updated=events.threat_zones_updated,
|
||||
new_flights=[FlightJs.for_flight(f) for f in events.new_flights],
|
||||
updated_flights=events.updated_flights,
|
||||
deleted_flights=events.deleted_flights,
|
||||
selected_flight=events.selected_flight,
|
||||
deselected_flight=events.deselected_flight,
|
||||
)
|
||||
|
||||
26
game/server/flights/models.py
Normal file
26
game/server/flights/models.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
from dcs.mapping import LatLng
|
||||
from pydantic import BaseModel
|
||||
|
||||
from game.ato import Flight
|
||||
from game.ato.flightstate import InFlight
|
||||
|
||||
|
||||
class FlightJs(BaseModel):
|
||||
id: UUID
|
||||
blue: bool
|
||||
position: LatLng | None
|
||||
|
||||
@staticmethod
|
||||
def for_flight(flight: Flight) -> FlightJs:
|
||||
# Don't provide a location for aircraft that aren't in the air. Later we can
|
||||
# expand the model to include the state data for the UI so that it can make its
|
||||
# own decisions about whether or not to draw the aircraft, but for now we'll
|
||||
# filter here.
|
||||
position = None
|
||||
if isinstance(flight.state, InFlight):
|
||||
position = flight.position().latlng()
|
||||
return FlightJs(id=flight.id, blue=flight.blue, position=position)
|
||||
@@ -4,13 +4,30 @@ from fastapi import APIRouter, Depends
|
||||
from shapely.geometry import LineString, Point as ShapelyPoint
|
||||
|
||||
from game import Game
|
||||
from game.server import GameContext
|
||||
from game.server.leaflet import LeafletPoly, ShapelyUtil
|
||||
from game.ato.flightplan import CasFlightPlan, PatrollingFlightPlan
|
||||
from game.server import GameContext
|
||||
from game.server.flights.models import FlightJs
|
||||
from game.server.leaflet import LeafletPoly, ShapelyUtil
|
||||
|
||||
router: APIRouter = APIRouter(prefix="/flights")
|
||||
|
||||
|
||||
@router.get("/")
|
||||
def list_flights(game: Game = Depends(GameContext.get)) -> list[FlightJs]:
|
||||
flights = []
|
||||
for coalition in game.coalitions:
|
||||
for package in coalition.ato.packages:
|
||||
for flight in package.flights:
|
||||
flights.append(FlightJs.for_flight(flight))
|
||||
return flights
|
||||
|
||||
|
||||
@router.get("/{flight_id}")
|
||||
def get_flight(flight_id: UUID, game: Game = Depends(GameContext.get)) -> FlightJs:
|
||||
flight = game.db.flights.get(flight_id)
|
||||
return FlightJs.for_flight(flight)
|
||||
|
||||
|
||||
@router.get("/{flight_id}/commit-boundary")
|
||||
def commit_boundary(
|
||||
flight_id: UUID, game: Game = Depends(GameContext.get)
|
||||
|
||||
@@ -1,55 +1,91 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import TYPE_CHECKING
|
||||
from uuid import UUID
|
||||
|
||||
from dcs import Point
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.ato import Flight
|
||||
from game.ato import Flight, Package
|
||||
from game.sim.combat import FrozenCombat
|
||||
|
||||
|
||||
@dataclass
|
||||
class GameUpdateEvents:
|
||||
def __init__(self) -> None:
|
||||
self.simulation_complete = False
|
||||
self.new_combats: list[FrozenCombat] = []
|
||||
self.updated_combats: list[FrozenCombat] = []
|
||||
self.updated_flights: list[tuple[Flight, Point]] = []
|
||||
self.navmesh_updates: set[bool] = set()
|
||||
self.unculled_zones_updated: bool = False
|
||||
self.threat_zones_updated: bool = False
|
||||
simulation_complete = False
|
||||
new_combats: list[FrozenCombat] = field(default_factory=list)
|
||||
updated_combats: list[FrozenCombat] = field(default_factory=list)
|
||||
updated_flight_positions: list[tuple[Flight, Point]] = field(default_factory=list)
|
||||
navmesh_updates: set[bool] = field(default_factory=set)
|
||||
unculled_zones_updated: bool = False
|
||||
threat_zones_updated: bool = False
|
||||
new_flights: set[Flight] = field(default_factory=set)
|
||||
updated_flights: set[UUID] = field(default_factory=set)
|
||||
deleted_flights: set[UUID] = field(default_factory=set)
|
||||
selected_flight: UUID | None = None
|
||||
deselected_flight: bool = False
|
||||
|
||||
@property
|
||||
def empty(self) -> bool:
|
||||
return not any(
|
||||
[
|
||||
self.simulation_complete,
|
||||
self.new_combats,
|
||||
self.updated_combats,
|
||||
self.updated_flights,
|
||||
self.navmesh_updates,
|
||||
self.unculled_zones_updated,
|
||||
self.threat_zones_updated,
|
||||
]
|
||||
)
|
||||
return self == GameUpdateEvents()
|
||||
|
||||
def complete_simulation(self) -> None:
|
||||
def complete_simulation(self) -> GameUpdateEvents:
|
||||
self.simulation_complete = True
|
||||
return self
|
||||
|
||||
def new_combat(self, combat: FrozenCombat) -> None:
|
||||
def new_combat(self, combat: FrozenCombat) -> GameUpdateEvents:
|
||||
self.new_combats.append(combat)
|
||||
return self
|
||||
|
||||
def update_combat(self, combat: FrozenCombat) -> None:
|
||||
def update_combat(self, combat: FrozenCombat) -> GameUpdateEvents:
|
||||
self.updated_combats.append(combat)
|
||||
return self
|
||||
|
||||
def update_flight(self, flight: Flight, new_position: Point) -> None:
|
||||
self.updated_flights.append((flight, new_position))
|
||||
def update_flight_position(
|
||||
self, flight: Flight, new_position: Point
|
||||
) -> GameUpdateEvents:
|
||||
self.updated_flight_positions.append((flight, new_position))
|
||||
return self
|
||||
|
||||
def update_navmesh(self, player: bool) -> None:
|
||||
def update_navmesh(self, player: bool) -> GameUpdateEvents:
|
||||
self.navmesh_updates.add(player)
|
||||
return self
|
||||
|
||||
def update_unculled_zones(self) -> None:
|
||||
def update_unculled_zones(self) -> GameUpdateEvents:
|
||||
self.unculled_zones_updated = True
|
||||
return self
|
||||
|
||||
def update_threat_zones(self) -> None:
|
||||
def update_threat_zones(self) -> GameUpdateEvents:
|
||||
self.threat_zones_updated = True
|
||||
return self
|
||||
|
||||
def new_flight(self, flight: Flight) -> GameUpdateEvents:
|
||||
self.new_flights.add(flight)
|
||||
return self
|
||||
|
||||
def update_flight(self, flight: Flight) -> GameUpdateEvents:
|
||||
self.updated_flights.add(flight.id)
|
||||
return self
|
||||
|
||||
def update_flights_in_package(self, package: Package) -> GameUpdateEvents:
|
||||
self.updated_flights.update({f.id for f in package.flights})
|
||||
return self
|
||||
|
||||
def delete_flight(self, flight: Flight) -> GameUpdateEvents:
|
||||
self.deleted_flights.add(flight.id)
|
||||
return self
|
||||
|
||||
def delete_flights_in_package(self, package: Package) -> GameUpdateEvents:
|
||||
self.deleted_flights.update({f.id for f in package.flights})
|
||||
return self
|
||||
|
||||
def select_flight(self, flight: Flight) -> GameUpdateEvents:
|
||||
self.selected_flight = flight.id
|
||||
self.deselected_flight = False
|
||||
return self
|
||||
|
||||
def deselect_flight(self) -> GameUpdateEvents:
|
||||
self.deselected_flight = True
|
||||
self.selected_flight = None
|
||||
return self
|
||||
|
||||
@@ -9,8 +9,8 @@ from typing import Optional, Sequence, TYPE_CHECKING
|
||||
from faker import Faker
|
||||
|
||||
from game.ato import Flight, FlightType, Package
|
||||
from game.settings import AutoAtoBehavior, Settings
|
||||
from game.ato.flightplan import FlightPlanBuilder
|
||||
from game.settings import AutoAtoBehavior, Settings
|
||||
from .pilot import Pilot, PilotStatus
|
||||
from ..db.database import Database
|
||||
from ..utils import meters
|
||||
@@ -381,7 +381,6 @@ class Squadron:
|
||||
for flight in list(package.flights):
|
||||
if flight.squadron == self and flight.flight_type is FlightType.FERRY:
|
||||
package.remove_flight(flight)
|
||||
flight.return_pilots_and_aircraft()
|
||||
if not package.flights:
|
||||
self.coalition.ato.remove_package(package)
|
||||
|
||||
|
||||
@@ -40,7 +40,10 @@ from typing import Generic, Iterator, List, Optional, Sequence, TYPE_CHECKING, T
|
||||
|
||||
from dcs.mapping import Point
|
||||
|
||||
from game.ato.ai_flight_planner_db import aircraft_for_task
|
||||
from game.ato.closestairfields import ObjectiveDistanceCache
|
||||
from game.ato.flight import Flight
|
||||
from game.ato.flightplan import FlightPlanBuilder
|
||||
from game.ato.flighttype import FlightType
|
||||
from game.ato.package import Package
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
@@ -53,9 +56,6 @@ from game.theater.transitnetwork import (
|
||||
TransitNetwork,
|
||||
)
|
||||
from game.utils import meters, nautical_miles
|
||||
from game.ato.ai_flight_planner_db import aircraft_for_task
|
||||
from game.ato.closestairfields import ObjectiveDistanceCache
|
||||
from game.ato.flightplan import FlightPlanBuilder
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
@@ -635,7 +635,6 @@ class PendingTransfers:
|
||||
flight.package.remove_flight(flight)
|
||||
if not flight.package.flights:
|
||||
self.game.ato_for(self.player).remove_package(flight.package)
|
||||
flight.return_pilots_and_aircraft()
|
||||
|
||||
@cancel_transport.register
|
||||
def _cancel_transport_convoy(
|
||||
|
||||
Reference in New Issue
Block a user