diff --git a/game/server/app.py b/game/server/app.py index 1a09f0b1..b503b08c 100644 --- a/game/server/app.py +++ b/game/server/app.py @@ -1,11 +1,12 @@ from fastapi import Depends, FastAPI -from . import debuggeometries, eventstream, flights, navmesh, waypoints +from . import debuggeometries, eventstream, flights, mapzones, navmesh, waypoints from .security import ApiKeyManager app = FastAPI(dependencies=[Depends(ApiKeyManager.verify)]) app.include_router(debuggeometries.router) app.include_router(eventstream.router) app.include_router(flights.router) +app.include_router(mapzones.router) app.include_router(navmesh.router) app.include_router(waypoints.router) diff --git a/game/server/mapzones/__init__.py b/game/server/mapzones/__init__.py new file mode 100644 index 00000000..3a27ef1c --- /dev/null +++ b/game/server/mapzones/__init__.py @@ -0,0 +1 @@ +from .routes import router diff --git a/game/server/mapzones/models.py b/game/server/mapzones/models.py new file mode 100644 index 00000000..bef8f364 --- /dev/null +++ b/game/server/mapzones/models.py @@ -0,0 +1,11 @@ +from __future__ import annotations + +from pydantic import BaseModel + +from game.server.leaflet import LeafletPoly + + +class MapZonesJs(BaseModel): + inclusion: list[LeafletPoly] + exclusion: list[LeafletPoly] + sea: list[LeafletPoly] diff --git a/game/server/mapzones/routes.py b/game/server/mapzones/routes.py new file mode 100644 index 00000000..c66ad007 --- /dev/null +++ b/game/server/mapzones/routes.py @@ -0,0 +1,21 @@ +from fastapi import APIRouter, Depends, HTTPException, status + +from game import Game +from game.server import GameContext +from .models import MapZonesJs +from ..leaflet import ShapelyUtil + +router: APIRouter = APIRouter(prefix="/map-zones") + + +@router.get("/") +def get(game: Game = Depends(GameContext.get)) -> MapZonesJs: + zones = game.theater.landmap + if zones is None: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) + + return MapZonesJs( + inclusion=ShapelyUtil.polys_to_leaflet(zones.inclusion_zones, game.theater), + exclusion=ShapelyUtil.polys_to_leaflet(zones.exclusion_zones, game.theater), + sea=ShapelyUtil.polys_to_leaflet(zones.sea_zones, game.theater), + ) diff --git a/qt_ui/widgets/map/model/mapmodel.py b/qt_ui/widgets/map/model/mapmodel.py index d173d590..0099ffc1 100644 --- a/qt_ui/widgets/map/model/mapmodel.py +++ b/qt_ui/widgets/map/model/mapmodel.py @@ -20,7 +20,6 @@ from .controlpointjs import ControlPointJs from .flightjs import FlightJs from .frontlinejs import FrontLineJs from .groundobjectjs import GroundObjectJs -from .mapzonesjs import MapZonesJs from .supplyroutejs import SupplyRouteJs from .threatzonecontainerjs import ThreatZoneContainerJs from .threatzonesjs import ThreatZonesJs @@ -54,7 +53,6 @@ class MapModel(QObject): flightsChanged = Signal() frontLinesChanged = Signal() threatZonesChanged = Signal() - mapZonesChanged = Signal() unculledZonesChanged = Signal() selectedFlightChanged = Signal(str) @@ -70,7 +68,6 @@ class MapModel(QObject): self._threat_zones = ThreatZoneContainerJs( ThreatZonesJs.empty(), ThreatZonesJs.empty() ) - self._map_zones = MapZonesJs([], [], []) self._unculled_zones = [] self._selected_flight_index: Optional[Tuple[int, int]] = None @@ -99,7 +96,6 @@ class MapModel(QObject): self._threat_zones = ThreatZoneContainerJs( ThreatZonesJs.empty(), ThreatZonesJs.empty() ) - self._map_zones = MapZonesJs([], [], []) self._unculled_zones = [] self.cleared.emit() @@ -164,7 +160,6 @@ class MapModel(QObject): self.reset_atos() self.reset_front_lines() self.reset_threat_zones() - self.reset_map_zones() self.reset_unculled_zones() def on_game_load(self, game: Optional[Game]) -> None: @@ -297,14 +292,6 @@ class MapModel(QObject): def threatZones(self) -> ThreatZoneContainerJs: return self._threat_zones - def reset_map_zones(self) -> None: - self._map_zones = MapZonesJs.from_game(self.game) - self.mapZonesChanged.emit() - - @Property(MapZonesJs, notify=mapZonesChanged) - def mapZones(self) -> MapZonesJs: - return self._map_zones - def on_package_change(self) -> None: self.reset_unculled_zones() diff --git a/qt_ui/widgets/map/model/mapzonesjs.py b/qt_ui/widgets/map/model/mapzonesjs.py deleted file mode 100644 index fe254df3..00000000 --- a/qt_ui/widgets/map/model/mapzonesjs.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import annotations - -from PySide2.QtCore import Property, QObject, Signal - -from game import Game -from game.server.leaflet import LeafletPoly, ShapelyUtil - - -class MapZonesJs(QObject): - inclusionZonesChanged = Signal() - exclusionZonesChanged = Signal() - seaZonesChanged = Signal() - - def __init__( - self, - inclusion_zones: list[LeafletPoly], - exclusion_zones: list[LeafletPoly], - sea_zones: list[LeafletPoly], - ) -> None: - super().__init__() - self._inclusion_zones = inclusion_zones - self._exclusion_zones = exclusion_zones - self._sea_zones = sea_zones - - @Property(list, notify=inclusionZonesChanged) - def inclusionZones(self) -> list[LeafletPoly]: - return self._inclusion_zones - - @Property(list, notify=exclusionZonesChanged) - def exclusionZones(self) -> list[LeafletPoly]: - return self._exclusion_zones - - @Property(list, notify=seaZonesChanged) - def seaZones(self) -> list[LeafletPoly]: - return self._sea_zones - - @classmethod - def from_game(cls, game: Game) -> MapZonesJs: - zones = game.theater.landmap - return MapZonesJs( - ShapelyUtil.polys_to_leaflet(zones.inclusion_zones, game.theater), - ShapelyUtil.polys_to_leaflet(zones.exclusion_zones, game.theater), - ShapelyUtil.polys_to_leaflet(zones.sea_zones, game.theater), - ) diff --git a/resources/ui/map/map.js b/resources/ui/map/map.js index 08a624a5..3ce9626b 100644 --- a/resources/ui/map/map.js +++ b/resources/ui/map/map.js @@ -1124,32 +1124,34 @@ function drawMapZones() { inclusionZones.clearLayers(); exclusionZones.clearLayers(); - for (const zone of game.mapZones.seaZones) { - L.polygon(zone, { - color: "#344455", - fillColor: "#344455", - fillOpacity: 1, - interactive: false, - }).addTo(seaZones); - } + getJson("/map-zones").then((zones) => { + for (const zone of zones.sea) { + L.polygon(zone, { + color: "#344455", + fillColor: "#344455", + fillOpacity: 1, + interactive: false, + }).addTo(seaZones); + } - for (const zone of game.mapZones.inclusionZones) { - L.polygon(zone, { - color: "#969696", - fillColor: "#4b4b4b", - fillOpacity: 1, - interactive: false, - }).addTo(inclusionZones); - } + for (const zone of zones.inclusion) { + L.polygon(zone, { + color: "#969696", + fillColor: "#4b4b4b", + fillOpacity: 1, + interactive: false, + }).addTo(inclusionZones); + } - for (const zone of game.mapZones.exclusionZones) { - L.polygon(zone, { - color: "#969696", - fillColor: "#303030", - fillOpacity: 1, - interactive: false, - }).addTo(exclusionZones); - } + for (const zone of zones.exclusion) { + L.polygon(zone, { + color: "#969696", + fillColor: "#303030", + fillOpacity: 1, + interactive: false, + }).addTo(exclusionZones); + } + }); } function drawUnculledZones() {