Sync MapZones when changing campaigns

This commit is contained in:
Raffson 2024-05-18 21:11:28 +02:00
parent 0f9781ff30
commit cbd90a5e36
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
6 changed files with 64 additions and 11 deletions

View File

@ -466,6 +466,7 @@ export type Game = {
navmeshes: NavMeshes; navmeshes: NavMeshes;
map_center?: LatLng; map_center?: LatLng;
unculled_zones: UnculledZone[]; unculled_zones: UnculledZone[];
map_zones: MapZones;
}; };
export type MapZones = { export type MapZones = {
inclusion: LatLng[][][]; inclusion: LatLng[][][];

View File

@ -0,0 +1,35 @@
import { RootState } from "../app/store";
import { gameLoaded, gameUnloaded } from "./actions";
import { createSlice } from "@reduxjs/toolkit";
import { LatLngLiteral } from "leaflet";
import { MapZones } from "./_liberationApi";
interface MapZonesState {
mapZones: MapZones;
}
const initialState: MapZonesState = {
mapZones: { inclusion: [], exclusion: [], sea: [] },
};
const mapZonesSlice = createSlice({
name: "map",
initialState: initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(gameLoaded, (state, action) => {
if (action.payload != null) {
state.mapZones.exclusion = action.payload.map_zones.exclusion;
state.mapZones.inclusion = action.payload.map_zones.inclusion;
state.mapZones.sea = action.payload.map_zones.sea;
}
});
builder.addCase(gameUnloaded, (state) => {
state.mapZones = initialState.mapZones;
});
},
});
export const selectMapZones = (state: RootState) => state.mapZones;
export default mapZonesSlice.reducer;

View File

@ -10,6 +10,7 @@ import supplyRoutesReducer from "../api/supplyRoutesSlice";
import tgosReducer from "../api/tgosSlice"; import tgosReducer from "../api/tgosSlice";
import threatZonesReducer from "../api/threatZonesSlice"; import threatZonesReducer from "../api/threatZonesSlice";
import unculledZonesReducer from "../api/unculledZonesSlice"; import unculledZonesReducer from "../api/unculledZonesSlice";
import mapZonesReducer from "../api/mapZonesSlice";
import { import {
Action, Action,
PreloadedState, PreloadedState,
@ -31,6 +32,7 @@ const rootReducer = combineReducers({
threatZones: threatZonesReducer, threatZones: threatZonesReducer,
[baseApi.reducerPath]: baseApi.reducer, [baseApi.reducerPath]: baseApi.reducer,
unculledZones: unculledZonesReducer, unculledZones: unculledZonesReducer,
mapZones: mapZonesReducer,
}); });
export function setupStore(preloadedState?: PreloadedState<RootState>) { export function setupStore(preloadedState?: PreloadedState<RootState>) {

View File

@ -1,6 +1,8 @@
import { useGetTerrainZonesQuery } from "../../api/liberationApi"; import { useGetTerrainZonesQuery } from "../../api/liberationApi";
import { useAppSelector } from "../../app/hooks";
import { LatLngLiteral } from "leaflet"; import { LatLngLiteral } from "leaflet";
import { LayerGroup, LayersControl, Polygon } from "react-leaflet"; import { LayerGroup, LayersControl, Polygon } from "react-leaflet";
import { selectMapZones } from "../../api/mapZonesSlice";
interface TerrainZoneLayerProps { interface TerrainZoneLayerProps {
zones: LatLngLiteral[][][]; zones: LatLngLiteral[][][];
@ -28,33 +30,28 @@ function TerrainZoneLayer(props: TerrainZoneLayerProps) {
} }
export default function TerrainZonesLayers() { export default function TerrainZonesLayers() {
const { data, error, isLoading } = useGetTerrainZonesQuery(); const zones = useAppSelector(selectMapZones).mapZones;
var exclusion = <></>; var exclusion = <></>;
var inclusion = <></>; var inclusion = <></>;
var sea = <></>; var sea = <></>;
if (error) { if (zones) {
console.error("Error while loading terrain zones", error);
} else if (isLoading) {
} else if (!data) {
console.log("Empty response when loading terrain zones");
} else {
exclusion = ( exclusion = (
<TerrainZoneLayer <TerrainZoneLayer
zones={data.exclusion} zones={zones.exclusion}
color="#969696" color="#969696"
fillColor="#303030" fillColor="#303030"
/> />
); );
inclusion = ( inclusion = (
<TerrainZoneLayer <TerrainZoneLayer
zones={data.inclusion} zones={zones.inclusion}
color="#969696" color="#969696"
fillColor="#4b4b4b" fillColor="#4b4b4b"
/> />
); );
sea = ( sea = (
<TerrainZoneLayer zones={data.sea} color="#344455" fillColor="#344455" /> <TerrainZoneLayer zones={zones.sea} color="#344455" fillColor="#344455" />
); );
} }
return ( return (

View File

@ -9,7 +9,11 @@ from game.server.flights.models import FlightJs
from game.server.frontlines.models import FrontLineJs from game.server.frontlines.models import FrontLineJs
from game.server.iadsnetwork.models import IadsNetworkJs from game.server.iadsnetwork.models import IadsNetworkJs
from game.server.leaflet import LeafletPoint from game.server.leaflet import LeafletPoint
from game.server.mapzones.models import ThreatZoneContainerJs, UnculledZoneJs from game.server.mapzones.models import (
ThreatZoneContainerJs,
UnculledZoneJs,
MapZonesJs,
)
from game.server.navmesh.models import NavMeshesJs from game.server.navmesh.models import NavMeshesJs
from game.server.supplyroutes.models import SupplyRouteJs from game.server.supplyroutes.models import SupplyRouteJs
from game.server.tgos.models import TgoJs from game.server.tgos.models import TgoJs
@ -29,6 +33,7 @@ class GameJs(BaseModel):
navmeshes: NavMeshesJs navmeshes: NavMeshesJs
map_center: LeafletPoint | None map_center: LeafletPoint | None
unculled_zones: list[UnculledZoneJs] unculled_zones: list[UnculledZoneJs]
map_zones: MapZonesJs
class Config: class Config:
title = "Game" title = "Game"
@ -46,4 +51,5 @@ class GameJs(BaseModel):
navmeshes=NavMeshesJs.from_game(game), navmeshes=NavMeshesJs.from_game(game),
map_center=game.theater.terrain.map_view_default.position.latlng(), map_center=game.theater.terrain.map_view_default.position.latlng(),
unculled_zones=UnculledZoneJs.from_game(game), unculled_zones=UnculledZoneJs.from_game(game),
map_zones=MapZonesJs.from_game(game),
) )

View File

@ -24,6 +24,18 @@ class MapZonesJs(BaseModel):
def empty(cls) -> MapZonesJs: def empty(cls) -> MapZonesJs:
return MapZonesJs(inclusion=[], exclusion=[], sea=[]) return MapZonesJs(inclusion=[], exclusion=[], sea=[])
@classmethod
def from_game(cls, game: Game) -> MapZonesJs:
zones = game.theater.landmap
if zones is None:
return cls.empty()
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),
)
class UnculledZoneJs(BaseModel): class UnculledZoneJs(BaseModel):
position: LeafletPoint position: LeafletPoint