Front-end 'push' updates for SupplyRoutes

This commit is contained in:
Raffson 2022-06-15 02:21:35 +02:00
parent 74142536e9
commit e9917ba00e
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
8 changed files with 62 additions and 11 deletions

View File

@ -22,6 +22,7 @@ import {
FrontLine,
IadsConnection,
NavMesh,
SupplyRoute,
Tgo,
ThreatZones,
UnculledZone,
@ -32,6 +33,8 @@ import { threatZonesUpdated } from "./threatZonesSlice";
import { unculledZonesUpdated } from "./unculledZonesSlice";
import { LatLng } from "leaflet";
import { updateIadsConnection, removeIadsConnection } from "./iadsNetworkSlice";
import { IadsConnection } from "./_liberationApi";
import { supplyRoutesUpdated } from "./supplyRoutesSlice";
interface GameUpdateEvents {
updated_flight_positions: { [id: string]: LatLng };
@ -52,6 +55,7 @@ interface GameUpdateEvents {
updated_control_points: ControlPoint[];
updated_iads: IadsConnection[];
deleted_iads: string[];
updated_supply_routes: SupplyRoute[];
reset_on_map_center: LatLng | null;
game_unloaded: boolean;
new_turn: boolean;
@ -135,6 +139,10 @@ export const handleStreamedEvents = (
dispatch(updateIadsConnection(events.updated_iads));
}
if (events.updated_supply_routes.length > 0) {
dispatch(supplyRoutesUpdated(events.updated_supply_routes));
}
if (events.reset_on_map_center != null) {
reloadGameState(dispatch);
}

View File

@ -1,26 +1,46 @@
import { RootState } from "../app/store";
import { gameLoaded, gameUnloaded } from "./actions";
import { SupplyRoute } from "./liberationApi";
import { createSlice } from "@reduxjs/toolkit";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface SupplyRoutesState {
routes: SupplyRoute[];
routes: { [id: string]: SupplyRoute };
}
const initialState: SupplyRoutesState = {
routes: [],
routes: {},
};
export const supplyRoutesSlice = createSlice({
name: "supplyRoutes",
initialState,
reducers: {},
reducers: {
updated: (state, action: PayloadAction<SupplyRoute[]>) => {
for (const route of action.payload) {
const id = route.id;
let points = route.points;
if (points.length > 0) {
state.routes[id] = route;
} else if (id in state.routes) {
points = state.routes[id].points;
state.routes[id] = route;
state.routes[id].points = points;
} else {
console.log("Trying to update a route that doesn't exist without points...");
}
}
},
},
extraReducers: (builder) => {
builder.addCase(gameLoaded, (state, action) => {
state.routes = action.payload.supply_routes;
state.routes = {}
for (const route of action.payload.supply_routes)
{
state.routes[route.id] = route;
}
});
builder.addCase(gameUnloaded, (state) => {
state.routes = [];
state.routes = {};
});
},
});
@ -28,3 +48,5 @@ export const supplyRoutesSlice = createSlice({
export const selectSupplyRoutes = (state: RootState) => state.supplyRoutes;
export default supplyRoutesSlice.reducer;
export const { updated: supplyRoutesUpdated } = supplyRoutesSlice.actions;

View File

@ -56,8 +56,7 @@ export default function SupplyRoute(props: SupplyRouteProps) {
return (
<Polyline
positions={props.route.points}
color={color}
weight={weight}
pathOptions={{ color: color, weight: weight}}
ref={(ref) => (path.current = ref)}
>
<SupplyRouteTooltip {...props} />

View File

@ -7,7 +7,7 @@ export default function SupplyRoutesLayer() {
const routes = useAppSelector(selectSupplyRoutes).routes;
return (
<LayerGroup>
{routes.map((route) => {
{Object.values(routes).map( route => {
return <SupplyRoute key={route.id} route={route} />;
})}
</LayerGroup>

View File

@ -15,6 +15,7 @@ from game.server.mapzones.models import ThreatZonesJs
from game.server.navmesh.models import NavMeshJs
from game.server.tgos.models import TgoJs
from game.server.mapzones.models import UnculledZoneJs
from game.server.supplyroutes.models import SupplyRouteJs
if TYPE_CHECKING:
from game import Game
@ -40,6 +41,7 @@ class GameUpdateEventsJs(BaseModel):
updated_control_points: list[ControlPointJs]
updated_iads: list[IadsConnectionJs]
deleted_iads: set[UUID]
updated_supply_routes: list[SupplyRouteJs]
reset_on_map_center: LeafletPoint | None
game_unloaded: bool
new_turn: bool
@ -57,6 +59,7 @@ class GameUpdateEventsJs(BaseModel):
updated_threat_zones = {}
updated_unculled_zones = []
updated_iads = []
updated_supply_routes = []
if game is not None:
new_combats = [
FrozenCombatJs.for_combat(c, game.theater) for c in events.new_combats
@ -76,6 +79,10 @@ class GameUpdateEventsJs(BaseModel):
updated_unculled_zones = UnculledZoneJs.from_game(game)
for node in events.updated_iads:
updated_iads.extend(IadsConnectionJs.connections_for_node(node))
if events.updated_supply_routes:
updated_supply_routes = SupplyRouteJs.all_in_game(game)
for route in updated_supply_routes:
route.points = []
return GameUpdateEventsJs(
updated_flight_positions={
@ -108,6 +115,7 @@ class GameUpdateEventsJs(BaseModel):
],
updated_iads=updated_iads,
deleted_iads=events.deleted_iads_connections,
updated_supply_routes=updated_supply_routes,
reset_on_map_center=events.reset_on_map_center,
game_unloaded=events.game_unloaded,
new_turn=events.new_turn,

View File

@ -64,7 +64,7 @@ class TransportFinder:
class SupplyRouteJs(BaseModel):
id: UUID
id: str
points: list[LeafletPoint]
front_active: bool
is_sea: bool
@ -91,7 +91,7 @@ class SupplyRouteJs(BaseModel):
#
# https://reactjs.org/docs/lists-and-keys.html#keys
# https://github.com/dcs-liberation/dcs_liberation/issues/2167
id=uuid.uuid4(),
id=f"{a}:{b}",
points=[p.latlng() for p in points],
front_active=not sea and a.front_is_active(b),
is_sea=sea,

View File

@ -38,6 +38,7 @@ class GameUpdateEvents:
updated_control_points: set[ControlPoint] = field(default_factory=set)
updated_iads: set[IadsNetworkNode] = field(default_factory=set)
deleted_iads_connections: set[UUID] = field(default_factory=set)
updated_supply_routes: bool = False
reset_on_map_center: LatLng | None = None
game_unloaded: bool = False
new_turn: bool = False
@ -133,6 +134,10 @@ class GameUpdateEvents:
def delete_iads_connection(self, connection_id: UUID) -> GameUpdateEvents:
self.deleted_iads_connections.add(connection_id)
return self.update_supply_routes()
def update_supply_routes(self) -> GameUpdateEvents:
self.updated_supply_routes = True
return self
def game_loaded(self, game: Game | None) -> GameUpdateEvents:

View File

@ -571,6 +571,12 @@ class PendingTransfers:
def __iter__(self) -> Iterator[TransferOrder]:
yield from self.pending_transfers
def _send_supply_route_event_stream_update(self) -> None:
from game.server import EventStream
with EventStream.event_context() as events:
events.update_supply_routes()
@property
def pending_transfer_count(self) -> int:
return len(self.pending_transfers)
@ -605,6 +611,7 @@ class PendingTransfers:
transfer.origin.base.commit_losses(transfer.units)
self.pending_transfers.append(transfer)
self.arrange_transport(transfer)
self._send_supply_route_event_stream_update()
def split_transfer(self, transfer: TransferOrder, size: int) -> TransferOrder:
"""Creates a smaller transfer that is a subset of the original."""
@ -659,6 +666,7 @@ class PendingTransfers:
self.cancel_transport(transfer.transport, transfer)
self.pending_transfers.remove(transfer)
transfer.origin.base.commission_units(transfer.units)
self._send_supply_route_event_stream_update()
def perform_transfers(self) -> None:
"""
@ -675,6 +683,7 @@ class PendingTransfers:
self.pending_transfers = incomplete
self.convoys.disband_all()
self.cargo_ships.disband_all()
self._send_supply_route_event_stream_update()
def plan_transports(self) -> None:
"""