mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Draw front lines on the react map.
https://github.com/dcs-liberation/dcs_liberation/issues/2039
This commit is contained in:
parent
9a2c10a98f
commit
b39a44ae37
28
client/src/api/frontLinesSlice.ts
Normal file
28
client/src/api/frontLinesSlice.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
import FrontLine from "./frontline";
|
||||||
|
import { RootState } from "../app/store";
|
||||||
|
|
||||||
|
interface FrontLinesState {
|
||||||
|
fronts: FrontLine[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: FrontLinesState = {
|
||||||
|
fronts: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const frontLinesSlice = createSlice({
|
||||||
|
name: "frontLines",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setFrontLines: (state, action: PayloadAction<FrontLine[]>) => {
|
||||||
|
state.fronts = action.payload;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { setFrontLines } = frontLinesSlice.actions;
|
||||||
|
|
||||||
|
export const selectFrontLines = (state: RootState) => state.frontLines;
|
||||||
|
|
||||||
|
export default frontLinesSlice.reducer;
|
||||||
7
client/src/api/frontline.ts
Normal file
7
client/src/api/frontline.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { LatLng } from "leaflet";
|
||||||
|
|
||||||
|
export interface FrontLine {
|
||||||
|
extents: LatLng[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FrontLine;
|
||||||
@ -2,12 +2,14 @@ import { Action, ThunkAction, configureStore } from "@reduxjs/toolkit";
|
|||||||
|
|
||||||
import controlPointsReducer from "../api/controlPointsSlice";
|
import controlPointsReducer from "../api/controlPointsSlice";
|
||||||
import flightsReducer from "../api/flightsSlice";
|
import flightsReducer from "../api/flightsSlice";
|
||||||
|
import frontLinesReducer from "../api/frontLinesSlice";
|
||||||
import supplyRoutesReducer from "../api/supplyRoutesSlice";
|
import supplyRoutesReducer from "../api/supplyRoutesSlice";
|
||||||
import tgosReducer from "../api/tgosSlice";
|
import tgosReducer from "../api/tgosSlice";
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
flights: flightsReducer,
|
flights: flightsReducer,
|
||||||
|
frontLines: frontLinesReducer,
|
||||||
controlPoints: controlPointsReducer,
|
controlPoints: controlPointsReducer,
|
||||||
supplyRoutes: supplyRoutesReducer,
|
supplyRoutes: supplyRoutesReducer,
|
||||||
tgos: tgosReducer,
|
tgos: tgosReducer,
|
||||||
|
|||||||
14
client/src/components/frontline/FrontLine.tsx
Normal file
14
client/src/components/frontline/FrontLine.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { FrontLine as FrontLineModel } from "../../api/frontline";
|
||||||
|
import { Polyline } from "react-leaflet";
|
||||||
|
|
||||||
|
interface FrontLineProps {
|
||||||
|
front: FrontLineModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
function FrontLine(props: FrontLineProps) {
|
||||||
|
return (
|
||||||
|
<Polyline positions={props.front.extents} weight={8} color={"#fe7d0a"} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FrontLine;
|
||||||
1
client/src/components/frontline/index.ts
Normal file
1
client/src/components/frontline/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from "./FrontLine";
|
||||||
15
client/src/components/frontlineslayer/FrontLinesLayer.tsx
Normal file
15
client/src/components/frontlineslayer/FrontLinesLayer.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import FrontLine from "../frontline";
|
||||||
|
import { LayerGroup } from "react-leaflet";
|
||||||
|
import { selectFrontLines } from "../../api/frontLinesSlice";
|
||||||
|
import { useAppSelector } from "../../app/hooks";
|
||||||
|
|
||||||
|
export default function SupplyRoutesLayer() {
|
||||||
|
const fronts = useAppSelector(selectFrontLines).fronts;
|
||||||
|
return (
|
||||||
|
<LayerGroup>
|
||||||
|
{fronts.map((front, idx) => {
|
||||||
|
return <FrontLine key={idx} front={front} />;
|
||||||
|
})}
|
||||||
|
</LayerGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
1
client/src/components/frontlineslayer/index.ts
Normal file
1
client/src/components/frontlineslayer/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from "./FrontLinesLayer";
|
||||||
@ -6,6 +6,7 @@ import AirDefenseRangeLayer from "../airdefenserangelayer";
|
|||||||
import { BasemapLayer } from "react-esri-leaflet";
|
import { BasemapLayer } from "react-esri-leaflet";
|
||||||
import ControlPointsLayer from "../controlpointslayer";
|
import ControlPointsLayer from "../controlpointslayer";
|
||||||
import FlightPlansLayer from "../flightplanslayer";
|
import FlightPlansLayer from "../flightplanslayer";
|
||||||
|
import FrontLinesLayer from "../frontlineslayer";
|
||||||
import { LatLng } from "leaflet";
|
import { LatLng } from "leaflet";
|
||||||
import SupplyRoutesLayer from "../supplyrouteslayer";
|
import SupplyRoutesLayer from "../supplyrouteslayer";
|
||||||
import { TgoType } from "../../api/tgo";
|
import { TgoType } from "../../api/tgo";
|
||||||
@ -42,6 +43,9 @@ export default function LiberationMap(props: GameProps) {
|
|||||||
<LayersControl.Overlay name="Supply routes" checked>
|
<LayersControl.Overlay name="Supply routes" checked>
|
||||||
<SupplyRoutesLayer />
|
<SupplyRoutesLayer />
|
||||||
</LayersControl.Overlay>
|
</LayersControl.Overlay>
|
||||||
|
<LayersControl.Overlay name="Front lines" checked>
|
||||||
|
<FrontLinesLayer />
|
||||||
|
</LayersControl.Overlay>
|
||||||
<LayersControl.Overlay name="Enemy SAM threat range" checked>
|
<LayersControl.Overlay name="Enemy SAM threat range" checked>
|
||||||
<AirDefenseRangeLayer blue={false} />
|
<AirDefenseRangeLayer blue={false} />
|
||||||
</LayersControl.Overlay>
|
</LayersControl.Overlay>
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { ControlPoint } from "../api/controlpoint";
|
import { ControlPoint } from "../api/controlpoint";
|
||||||
import { Flight } from "../api/flight";
|
import { Flight } from "../api/flight";
|
||||||
|
import FrontLine from "../api/frontline";
|
||||||
import SupplyRoute from "../api/supplyroute";
|
import SupplyRoute from "../api/supplyroute";
|
||||||
import Tgo from "../api/tgo";
|
import Tgo from "../api/tgo";
|
||||||
import backend from "../api/backend";
|
import backend from "../api/backend";
|
||||||
import { registerFlight } from "../api/flightsSlice";
|
import { registerFlight } from "../api/flightsSlice";
|
||||||
import { setControlPoints } from "../api/controlPointsSlice";
|
import { setControlPoints } from "../api/controlPointsSlice";
|
||||||
|
import { setFrontLines } from "../api/frontLinesSlice";
|
||||||
import { setSupplyRoutes } from "../api/supplyRoutesSlice";
|
import { setSupplyRoutes } from "../api/supplyRoutesSlice";
|
||||||
import { setTgos } from "../api/tgosSlice";
|
import { setTgos } from "../api/tgosSlice";
|
||||||
import { useAppDispatch } from "../app/hooks";
|
import { useAppDispatch } from "../app/hooks";
|
||||||
@ -41,6 +43,14 @@ export const useInitialGameState = () => {
|
|||||||
dispatch(setSupplyRoutes(response.data as SupplyRoute[]));
|
dispatch(setSupplyRoutes(response.data as SupplyRoute[]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
backend
|
||||||
|
.get("/front-lines")
|
||||||
|
.catch((error) => console.log(`Error fetching front-lines: ${error}`))
|
||||||
|
.then((response) => {
|
||||||
|
if (response != null) {
|
||||||
|
dispatch(setFrontLines(response.data as FrontLine[]));
|
||||||
|
}
|
||||||
|
});
|
||||||
backend
|
backend
|
||||||
.get("/flights?with_waypoints=true")
|
.get("/flights?with_waypoints=true")
|
||||||
.catch((error) => console.log(`Error fetching flights: ${error}`))
|
.catch((error) => console.log(`Error fetching flights: ${error}`))
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from . import (
|
|||||||
debuggeometries,
|
debuggeometries,
|
||||||
eventstream,
|
eventstream,
|
||||||
flights,
|
flights,
|
||||||
|
frontlines,
|
||||||
mapzones,
|
mapzones,
|
||||||
navmesh,
|
navmesh,
|
||||||
supplyroutes,
|
supplyroutes,
|
||||||
@ -24,6 +25,7 @@ app.include_router(controlpoints.router)
|
|||||||
app.include_router(debuggeometries.router)
|
app.include_router(debuggeometries.router)
|
||||||
app.include_router(eventstream.router)
|
app.include_router(eventstream.router)
|
||||||
app.include_router(flights.router)
|
app.include_router(flights.router)
|
||||||
|
app.include_router(frontlines.router)
|
||||||
app.include_router(mapzones.router)
|
app.include_router(mapzones.router)
|
||||||
app.include_router(navmesh.router)
|
app.include_router(navmesh.router)
|
||||||
app.include_router(supplyroutes.router)
|
app.include_router(supplyroutes.router)
|
||||||
|
|||||||
1
game/server/frontlines/__init__.py
Normal file
1
game/server/frontlines/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .routes import router
|
||||||
9
game/server/frontlines/models.py
Normal file
9
game/server/frontlines/models.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from game.server.leaflet import LeafletPoint
|
||||||
|
|
||||||
|
|
||||||
|
class FrontLineJs(BaseModel):
|
||||||
|
extents: list[LeafletPoint]
|
||||||
22
game/server/frontlines/routes.py
Normal file
22
game/server/frontlines/routes.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
|
||||||
|
from game import Game
|
||||||
|
from game.utils import nautical_miles
|
||||||
|
from .models import FrontLineJs
|
||||||
|
from ..dependencies import GameContext
|
||||||
|
|
||||||
|
router: APIRouter = APIRouter(prefix="/front-lines")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/")
|
||||||
|
def list_front_lines(game: Game = Depends(GameContext.get)) -> list[FrontLineJs]:
|
||||||
|
front_lines = []
|
||||||
|
for front_line in game.theater.conflicts():
|
||||||
|
a = front_line.position.point_from_heading(
|
||||||
|
front_line.attack_heading.right.degrees, nautical_miles(2).meters
|
||||||
|
)
|
||||||
|
b = front_line.position.point_from_heading(
|
||||||
|
front_line.attack_heading.left.degrees, nautical_miles(2).meters
|
||||||
|
)
|
||||||
|
front_lines.append(FrontLineJs(extents=[a.latlng(), b.latlng()]))
|
||||||
|
return front_lines
|
||||||
Loading…
x
Reference in New Issue
Block a user