mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Completed backend for advanced RTS functions
This commit is contained in:
@@ -390,7 +390,7 @@ class DemoDataGenerator {
|
|||||||
startTime: 0
|
startTime: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.mission.RTSOptions = {
|
ret.mission.commandModeOptions = {
|
||||||
restrictSpawns: true,
|
restrictSpawns: true,
|
||||||
restrictToCoalition: true,
|
restrictToCoalition: true,
|
||||||
setupTime: 0,
|
setupTime: 0,
|
||||||
@@ -406,13 +406,13 @@ class DemoDataGenerator {
|
|||||||
var username = atob(auth.replace("Basic ", "")).split(":")[0];
|
var username = atob(auth.replace("Basic ", "")).split(":")[0];
|
||||||
switch (username) {
|
switch (username) {
|
||||||
case "admin":
|
case "admin":
|
||||||
ret.mission.RTSOptions.commandMode = "Game master";
|
ret.mission.commandModeOptions.commandMode = "Game master";
|
||||||
break
|
break
|
||||||
case "blue":
|
case "blue":
|
||||||
ret.mission.RTSOptions.commandMode = "Blue commander";
|
ret.mission.commandModeOptions.commandMode = "Blue commander";
|
||||||
break;
|
break;
|
||||||
case "red":
|
case "red":
|
||||||
ret.mission.RTSOptions.commandMode = "Red commander";
|
ret.mission.commandModeOptions.commandMode = "Red commander";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-toolbar {
|
#command-mode-toolbar {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -917,12 +917,12 @@ nav.ol-panel> :last-child {
|
|||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-phase::before {
|
#command-mode-phase::before {
|
||||||
content: "Time to start";
|
content: "Time to start";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-phase.setup-phase::after {
|
#command-mode-phase.setup-phase::after {
|
||||||
color: orange;
|
color: orange;
|
||||||
border: 1px solid orange;
|
border: 1px solid orange;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
@@ -933,7 +933,7 @@ nav.ol-panel> :last-child {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-phase.game-commenced {
|
#command-mode-phase.game-commenced {
|
||||||
background-color: var(--background-grey);
|
background-color: var(--background-grey);
|
||||||
color: lightgreen;
|
color: lightgreen;
|
||||||
border: 1px solid lightgreen;
|
border: 1px solid lightgreen;
|
||||||
@@ -944,31 +944,31 @@ nav.ol-panel> :last-child {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-phase.game-commenced::before {
|
#command-mode-phase.game-commenced::before {
|
||||||
content: "Game commenced";
|
content: "Game commenced";
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-phase.game-commenced::after {
|
#command-mode-phase.game-commenced::after {
|
||||||
content: "Spawn restrictions are being enforced";
|
content: "Spawn restrictions are being enforced";
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-toolbar .ol-button {
|
#command-mode-toolbar .ol-button {
|
||||||
border: 1px solid white;
|
border: 1px solid white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-toolbar .ol-button>svg {
|
#command-mode-toolbar .ol-button>svg {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
fill: white;
|
fill: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-settings-dialog {
|
#command-mode-settings-dialog {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-settings-dialog>.ol-dialog-content {
|
#command-mode-settings-dialog>.ol-dialog-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
@@ -978,11 +978,11 @@ nav.ol-panel> :last-child {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-settings-dialog>.ol-dialog-content .ol-group {
|
#command-mode-settings-dialog>.ol-dialog-content .ol-group {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rts-settings-dialog h4 {
|
#command-mode-settings-dialog h4 {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|||||||
2
client/src/@types/dom.d.ts
vendored
2
client/src/@types/dom.d.ts
vendored
@@ -19,7 +19,7 @@ interface CustomEventMap {
|
|||||||
"mapStateChanged": CustomEvent<string>,
|
"mapStateChanged": CustomEvent<string>,
|
||||||
"mapContextMenu": CustomEvent<>,
|
"mapContextMenu": CustomEvent<>,
|
||||||
"mapVisibilityOptionsChanged": CustomEvent<>,
|
"mapVisibilityOptionsChanged": CustomEvent<>,
|
||||||
"RTSOptionsChanged": CustomEvent<>,
|
"commandModeOptionsChanged": CustomEvent<>,
|
||||||
"contactsUpdated": CustomEvent<Unit>,
|
"contactsUpdated": CustomEvent<Unit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
client/src/@types/server.d.ts
vendored
4
client/src/@types/server.d.ts
vendored
@@ -14,13 +14,13 @@ interface MissionData {
|
|||||||
mission: {
|
mission: {
|
||||||
theatre: string,
|
theatre: string,
|
||||||
dateAndTime: DateAndTime;
|
dateAndTime: DateAndTime;
|
||||||
RTSOptions: RTSOptions;
|
commandModeOptions: CommandModeOptions;
|
||||||
}
|
}
|
||||||
time: number;
|
time: number;
|
||||||
sessionHash: string;
|
sessionHash: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RTSOptions {
|
interface CommandModeOptions {
|
||||||
commandMode: string;
|
commandMode: string;
|
||||||
restrictSpawns: boolean;
|
restrictSpawns: boolean;
|
||||||
restrictToCoalition: boolean;
|
restrictToCoalition: boolean;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getMap, getUnitsManager, setActiveCoalition } from "..";
|
import { getMap, getMissionHandler, getUnitsManager, setActiveCoalition } from "..";
|
||||||
import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "../constants/constants";
|
import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "../constants/constants";
|
||||||
import { Airbase } from "../missionhandler/airbase";
|
import { Airbase } from "../mission/airbase";
|
||||||
import { ContextMenu } from "./contextmenu";
|
import { ContextMenu } from "./contextmenu";
|
||||||
|
|
||||||
export class AirbaseContextMenu extends ContextMenu {
|
export class AirbaseContextMenu extends ContextMenu {
|
||||||
@@ -26,7 +26,7 @@ export class AirbaseContextMenu extends ContextMenu {
|
|||||||
this.setParkings(airbase.getParkings());
|
this.setParkings(airbase.getParkings());
|
||||||
this.setCoalition(airbase.getCoalition());
|
this.setCoalition(airbase.getCoalition());
|
||||||
this.enableLandButton(getUnitsManager().getSelectedUnitsTypes().length == 1 && ["Aircraft", "Helicopter"].includes(getUnitsManager().getSelectedUnitsTypes()[0]) && (getUnitsManager().getSelectedUnitsCoalition() === airbase.getCoalition() || airbase.getCoalition() === "neutral"))
|
this.enableLandButton(getUnitsManager().getSelectedUnitsTypes().length == 1 && ["Aircraft", "Helicopter"].includes(getUnitsManager().getSelectedUnitsTypes()[0]) && (getUnitsManager().getSelectedUnitsCoalition() === airbase.getCoalition() || airbase.getCoalition() === "neutral"))
|
||||||
this.enableSpawnButton(getUnitsManager().getCommandMode() == GAME_MASTER || this.#airbase.getCoalition() == getUnitsManager().getCommandedCoalition());
|
this.enableSpawnButton(getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || this.#airbase.getCoalition() == getMissionHandler().getCommandedCoalition());
|
||||||
}
|
}
|
||||||
|
|
||||||
setName(airbaseName: string) {
|
setName(airbaseName: string) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { LatLng } from "leaflet";
|
import { LatLng } from "leaflet";
|
||||||
import { getMap, getUnitsManager } from "..";
|
import { getMap, getMissionHandler, getUnitsManager } from "..";
|
||||||
import { GAME_MASTER, IADSTypes } from "../constants/constants";
|
import { GAME_MASTER, IADSTypes } from "../constants/constants";
|
||||||
import { CoalitionArea } from "../map/coalitionarea";
|
import { CoalitionArea } from "../map/coalitionarea";
|
||||||
import { ContextMenu } from "./contextmenu";
|
import { ContextMenu } from "./contextmenu";
|
||||||
@@ -81,7 +81,7 @@ export class CoalitionAreaContextMenu extends ContextMenu {
|
|||||||
return createCheckboxOption(range, `Add ${range} units to the IADS`);
|
return createCheckboxOption(range, `Add ${range} units to the IADS`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (getUnitsManager().getCommandMode() !== GAME_MASTER)
|
if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER)
|
||||||
this.#coalitionSwitch.hide()
|
this.#coalitionSwitch.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ export class CoalitionAreaContextMenu extends ContextMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#onSwitchClick(value: boolean) {
|
#onSwitchClick(value: boolean) {
|
||||||
if (getUnitsManager().getCommandMode() == GAME_MASTER) {
|
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER) {
|
||||||
this.getCoalitionArea()?.setCoalition(value ? "red" : "blue");
|
this.getCoalitionArea()?.setCoalition(value ? "red" : "blue");
|
||||||
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => {
|
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => {
|
||||||
element.setAttribute("data-coalition", this.getCoalitionArea()?.getCoalition())
|
element.setAttribute("data-coalition", this.getCoalitionArea()?.getCoalition())
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ export class MapContextMenu extends ContextMenu {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("RTSOptionsChanged", (e: any) => {
|
document.addEventListener("commandModeOptionsChanged", (e: any) => {
|
||||||
this.#refreshOptions();
|
this.#refreshOptions();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ export class MapContextMenu extends ContextMenu {
|
|||||||
else
|
else
|
||||||
this.#coalitionSwitch.setValue(undefined);
|
this.#coalitionSwitch.setValue(undefined);
|
||||||
|
|
||||||
if (getUnitsManager().getCommandMode() !== GAME_MASTER)
|
if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER)
|
||||||
this.#coalitionSwitch.hide()
|
this.#coalitionSwitch.hide()
|
||||||
|
|
||||||
this.getContainer()?.querySelector("#coalition-area-button")?.classList.toggle("hide", true);
|
this.getContainer()?.querySelector("#coalition-area-button")?.classList.toggle("hide", true);
|
||||||
@@ -562,26 +562,26 @@ export class MapContextMenu extends ContextMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#computeSpawnPoints() {
|
#computeSpawnPoints() {
|
||||||
if (getMissionHandler() && getUnitsManager().getCommandMode() !== GAME_MASTER){
|
if (getMissionHandler() && getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER){
|
||||||
var aircraftCount = parseInt(this.#aircraftCountDropdown.getValue());
|
var aircraftCount = parseInt(this.#aircraftCountDropdown.getValue());
|
||||||
var aircraftSpawnPoints = aircraftCount * aircraftDatabase.getSpawnPointsByLabel(this.#aircraftLabelDropdown.getValue());
|
var aircraftSpawnPoints = aircraftCount * aircraftDatabase.getSpawnPointsByLabel(this.#aircraftLabelDropdown.getValue());
|
||||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${aircraftSpawnPoints}`;
|
(<HTMLButtonElement>this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${aircraftSpawnPoints}`;
|
||||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = aircraftSpawnPoints > getMissionHandler().getAvailableSpawnPoints();
|
(<HTMLButtonElement>this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = aircraftSpawnPoints >= getMissionHandler().getAvailableSpawnPoints();
|
||||||
|
|
||||||
var helicopterCount = parseInt(this.#helicopterCountDropdown.getValue());
|
var helicopterCount = parseInt(this.#helicopterCountDropdown.getValue());
|
||||||
var helicopterSpawnPoints = helicopterCount * helicopterDatabase.getSpawnPointsByLabel(this.#helicopterLabelDropdown.getValue());
|
var helicopterSpawnPoints = helicopterCount * helicopterDatabase.getSpawnPointsByLabel(this.#helicopterLabelDropdown.getValue());
|
||||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#helicopter-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${helicopterSpawnPoints}`;
|
(<HTMLButtonElement>this.getContainer()?.querySelector("#helicopter-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${helicopterSpawnPoints}`;
|
||||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#helicopter-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = helicopterSpawnPoints > getMissionHandler().getAvailableSpawnPoints();
|
(<HTMLButtonElement>this.getContainer()?.querySelector("#helicopter-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = helicopterSpawnPoints >= getMissionHandler().getAvailableSpawnPoints();
|
||||||
|
|
||||||
var groundUnitCount = parseInt(this.#groundUnitCountDropdown.getValue());
|
var groundUnitCount = parseInt(this.#groundUnitCountDropdown.getValue());
|
||||||
var groundUnitSpawnPoints = groundUnitCount * groundUnitDatabase.getSpawnPointsByLabel(this.#groundUnitLabelDropdown.getValue());
|
var groundUnitSpawnPoints = groundUnitCount * groundUnitDatabase.getSpawnPointsByLabel(this.#groundUnitLabelDropdown.getValue());
|
||||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#groundunit-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${groundUnitSpawnPoints}`;
|
(<HTMLButtonElement>this.getContainer()?.querySelector("#groundunit-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${groundUnitSpawnPoints}`;
|
||||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#groundunit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = groundUnitSpawnPoints > getMissionHandler().getAvailableSpawnPoints();
|
(<HTMLButtonElement>this.getContainer()?.querySelector("#groundunit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = groundUnitSpawnPoints >= getMissionHandler().getAvailableSpawnPoints();
|
||||||
|
|
||||||
var navyUnitCount = parseInt(this.#navyUnitCountDropdown.getValue());
|
var navyUnitCount = parseInt(this.#navyUnitCountDropdown.getValue());
|
||||||
var navyUnitSpawnPoints = navyUnitCount * navyUnitDatabase.getSpawnPointsByLabel(this.#navyUnitLabelDropdown.getValue());
|
var navyUnitSpawnPoints = navyUnitCount * navyUnitDatabase.getSpawnPointsByLabel(this.#navyUnitLabelDropdown.getValue());
|
||||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#navyunit-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${navyUnitSpawnPoints}`;
|
(<HTMLButtonElement>this.getContainer()?.querySelector("#navyunit-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${navyUnitSpawnPoints}`;
|
||||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#navyunit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = navyUnitSpawnPoints > getMissionHandler().getAvailableSpawnPoints();
|
(<HTMLButtonElement>this.getContainer()?.querySelector("#navyunit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = navyUnitSpawnPoints >= getMissionHandler().getAvailableSpawnPoints();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ import { Map } from "./map/map"
|
|||||||
import { UnitsManager } from "./units/unitsmanager";
|
import { UnitsManager } from "./units/unitsmanager";
|
||||||
import { UnitInfoPanel } from "./panels/unitinfopanel";
|
import { UnitInfoPanel } from "./panels/unitinfopanel";
|
||||||
import { ConnectionStatusPanel } from "./panels/connectionstatuspanel";
|
import { ConnectionStatusPanel } from "./panels/connectionstatuspanel";
|
||||||
import { MissionHandler } from "./missionhandler/missionhandler";
|
import { MissionHandler } from "./mission/missionhandler";
|
||||||
import { UnitControlPanel } from "./panels/unitcontrolpanel";
|
import { UnitControlPanel } from "./panels/unitcontrolpanel";
|
||||||
import { MouseInfoPanel } from "./panels/mouseinfopanel";
|
import { MouseInfoPanel } from "./panels/mouseinfopanel";
|
||||||
import { AIC } from "./aic/aic";
|
import { AIC } from "./aic/aic";
|
||||||
@@ -255,17 +255,17 @@ export function getHotgroupPanel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function setActiveCoalition(newActiveCoalition: string) {
|
export function setActiveCoalition(newActiveCoalition: string) {
|
||||||
if (getUnitsManager().getCommandMode() == GAME_MASTER)
|
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER)
|
||||||
activeCoalition = newActiveCoalition;
|
activeCoalition = newActiveCoalition;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getActiveCoalition() {
|
export function getActiveCoalition() {
|
||||||
if (getUnitsManager().getCommandMode() == GAME_MASTER)
|
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER)
|
||||||
return activeCoalition;
|
return activeCoalition;
|
||||||
else {
|
else {
|
||||||
if (getUnitsManager().getCommandMode() == BLUE_COMMANDER)
|
if (getMissionHandler().getCommandModeOptions().commandMode == BLUE_COMMANDER)
|
||||||
return "blue";
|
return "blue";
|
||||||
else if (getUnitsManager().getCommandMode() == RED_COMMANDER)
|
else if (getMissionHandler().getCommandModeOptions().commandMode == RED_COMMANDER)
|
||||||
return "red";
|
return "red";
|
||||||
else
|
else
|
||||||
return "neutral";
|
return "neutral";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DomUtil, LatLng, LatLngExpression, Map, Point, Polygon, PolylineOptions } from "leaflet";
|
import { DomUtil, LatLng, LatLngExpression, Map, Point, Polygon, PolylineOptions } from "leaflet";
|
||||||
import { getMap, getUnitsManager } from "..";
|
import { getMap, getMissionHandler, getUnitsManager } from "..";
|
||||||
import { CoalitionAreaHandle } from "./coalitionareahandle";
|
import { CoalitionAreaHandle } from "./coalitionareahandle";
|
||||||
import { CoalitionAreaMiddleHandle } from "./coalitionareamiddlehandle";
|
import { CoalitionAreaMiddleHandle } from "./coalitionareamiddlehandle";
|
||||||
import { BLUE_COMMANDER, RED_COMMANDER } from "../constants/constants";
|
import { BLUE_COMMANDER, RED_COMMANDER } from "../constants/constants";
|
||||||
@@ -23,8 +23,8 @@ export class CoalitionArea extends Polygon {
|
|||||||
this.#setColors();
|
this.#setColors();
|
||||||
this.#registerCallbacks();
|
this.#registerCallbacks();
|
||||||
|
|
||||||
if ([BLUE_COMMANDER, RED_COMMANDER].includes(getUnitsManager().getCommandMode()))
|
if ([BLUE_COMMANDER, RED_COMMANDER].includes(getMissionHandler().getCommandModeOptions().commandMode))
|
||||||
this.setCoalition(getUnitsManager().getCommandedCoalition());
|
this.setCoalition(getMissionHandler().getCommandedCoalition());
|
||||||
}
|
}
|
||||||
|
|
||||||
setCoalition(coalition: string) {
|
setCoalition(coalition: string) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { MapContextMenu } from "../controls/mapcontextmenu";
|
|||||||
import { UnitContextMenu } from "../controls/unitcontextmenu";
|
import { UnitContextMenu } from "../controls/unitcontextmenu";
|
||||||
import { AirbaseContextMenu } from "../controls/airbasecontextmenu";
|
import { AirbaseContextMenu } from "../controls/airbasecontextmenu";
|
||||||
import { Dropdown } from "../controls/dropdown";
|
import { Dropdown } from "../controls/dropdown";
|
||||||
import { Airbase } from "../missionhandler/airbase";
|
import { Airbase } from "../mission/airbase";
|
||||||
import { Unit } from "../units/unit";
|
import { Unit } from "../units/unit";
|
||||||
import { bearing, createCheckboxOption } from "../other/utils";
|
import { bearing, createCheckboxOption } from "../other/utils";
|
||||||
import { DestinationPreviewMarker } from "./destinationpreviewmarker";
|
import { DestinationPreviewMarker } from "./destinationpreviewmarker";
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { getInfoPopup, getMap, getUnitsManager } from "..";
|
|||||||
import { Airbase } from "./airbase";
|
import { Airbase } from "./airbase";
|
||||||
import { Bullseye } from "./bullseye";
|
import { Bullseye } from "./bullseye";
|
||||||
import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "../constants/constants";
|
import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "../constants/constants";
|
||||||
import { setRTSOptions } from "../server/server";
|
import { setCommandModeOptions } from "../server/server";
|
||||||
import { Dropdown } from "../controls/dropdown";
|
import { Dropdown } from "../controls/dropdown";
|
||||||
import { groundUnitDatabase } from "../units/groundunitdatabase";
|
import { groundUnitDatabase } from "../units/groundunitdatabase";
|
||||||
import { createCheckboxOption, getCheckboxOptions } from "../other/utils";
|
import { createCheckboxOption, getCheckboxOptions } from "../other/utils";
|
||||||
@@ -16,20 +16,20 @@ export class MissionHandler {
|
|||||||
#airbases: { [name: string]: Airbase } = {};
|
#airbases: { [name: string]: Airbase } = {};
|
||||||
#theatre: string = "";
|
#theatre: string = "";
|
||||||
#dateAndTime: DateAndTime = {date: {Year: 0, Month: 0, Day: 0}, time: {h: 0, m: 0, s: 0}, startTime: 0, elapsedTime: 0};
|
#dateAndTime: DateAndTime = {date: {Year: 0, Month: 0, Day: 0}, time: {h: 0, m: 0, s: 0}, startTime: 0, elapsedTime: 0};
|
||||||
#RTSOptions: RTSOptions = {commandMode: "Hide all", restrictSpawns: false, restrictToCoalition: false, setupTime: Infinity, spawnPoints: {red: Infinity, blue: Infinity}, eras: []};
|
#commandModeOptions: CommandModeOptions = {commandMode: "Hide all", restrictSpawns: false, restrictToCoalition: false, setupTime: Infinity, spawnPoints: {red: Infinity, blue: Infinity}, eras: []};
|
||||||
#remainingSetupTime: number = 0;
|
#remainingSetupTime: number = 0;
|
||||||
#spentSpawnPoint: number = 0;
|
#spentSpawnPoint: number = 0;
|
||||||
#RTSSettingsDialog: HTMLElement;
|
#commandModeDialog: HTMLElement;
|
||||||
#rtsErasDropdown: Dropdown;
|
#commandModeErasDropdown: Dropdown;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
document.addEventListener("showRTSSettingsDialog", () => this.showRTSSettingsDialog());
|
document.addEventListener("showCommandModeDialog", () => this.showCommandModeDialog());
|
||||||
document.addEventListener("applyRTSOptions", () => this.#applyRTSOptions());
|
document.addEventListener("applycommandModeOptions", () => this.#applycommandModeOptions());
|
||||||
|
|
||||||
/* RTS settings dialog */
|
/* command-mode settings dialog */
|
||||||
this.#RTSSettingsDialog = <HTMLElement> document.querySelector("#rts-settings-dialog");
|
this.#commandModeDialog = <HTMLElement> document.querySelector("#command-mode-settings-dialog");
|
||||||
|
|
||||||
this.#rtsErasDropdown = new Dropdown("rts-era-options", () => {});
|
this.#commandModeErasDropdown = new Dropdown("command-mode-era-options", () => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBullseyes(data: BullseyesData) {
|
updateBullseyes(data: BullseyesData) {
|
||||||
@@ -65,27 +65,28 @@ export class MissionHandler {
|
|||||||
|
|
||||||
updateMission(data: MissionData) {
|
updateMission(data: MissionData) {
|
||||||
if (data.mission) {
|
if (data.mission) {
|
||||||
|
/* Set the mission theatre */
|
||||||
if (data.mission.theatre != this.#theatre) {
|
if (data.mission.theatre != this.#theatre) {
|
||||||
this.#theatre = data.mission.theatre;
|
this.#theatre = data.mission.theatre;
|
||||||
getMap().setTheatre(this.#theatre);
|
getMap().setTheatre(this.#theatre);
|
||||||
getInfoPopup().setText("Map set to " + this.#theatre);
|
getInfoPopup().setText("Map set to " + this.#theatre);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the date and time data */
|
||||||
this.#dateAndTime = data.mission.dateAndTime;
|
this.#dateAndTime = data.mission.dateAndTime;
|
||||||
|
|
||||||
this.#setRTSOptions(data.mission.RTSOptions);
|
/* Set the command mode options */
|
||||||
getUnitsManager().setCommandMode(this.#RTSOptions.commandMode);
|
this.#setcommandModeOptions(data.mission.commandModeOptions);
|
||||||
|
this.#remainingSetupTime = this.getCommandModeOptions().setupTime - this.getDateAndTime().elapsedTime;
|
||||||
this.#remainingSetupTime = this.#RTSOptions.setupTime - this.getDateAndTime().elapsedTime;
|
var commandModePhaseEl = document.querySelector("#command-mode-phase") as HTMLElement;
|
||||||
var RTSPhaseEl = document.querySelector("#rts-phase") as HTMLElement;
|
if (commandModePhaseEl) {
|
||||||
if (RTSPhaseEl) {
|
|
||||||
if (this.#remainingSetupTime > 0) {
|
if (this.#remainingSetupTime > 0) {
|
||||||
var remainingTime = `-${new Date(this.#remainingSetupTime * 1000).toISOString().substring(14, 19)}`;
|
var remainingTime = `-${new Date(this.#remainingSetupTime * 1000).toISOString().substring(14, 19)}`;
|
||||||
RTSPhaseEl.dataset.remainingTime = remainingTime;
|
commandModePhaseEl.dataset.remainingTime = remainingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTSPhaseEl.classList.toggle("setup-phase", this.#remainingSetupTime > 0);
|
commandModePhaseEl.classList.toggle("setup-phase", this.#remainingSetupTime > 0);
|
||||||
RTSPhaseEl.classList.toggle("game-commenced", this.#remainingSetupTime <= 0);
|
commandModePhaseEl.classList.toggle("game-commenced", this.#remainingSetupTime <= 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,8 +99,8 @@ export class MissionHandler {
|
|||||||
return this.#airbases;
|
return this.#airbases;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRTSOptions() {
|
getCommandModeOptions() {
|
||||||
return this.#RTSOptions;
|
return this.#commandModeOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDateAndTime() {
|
getDateAndTime() {
|
||||||
@@ -111,16 +112,25 @@ export class MissionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAvailableSpawnPoints() {
|
getAvailableSpawnPoints() {
|
||||||
if (getUnitsManager().getCommandMode() === GAME_MASTER)
|
if (this.getCommandModeOptions().commandMode === GAME_MASTER)
|
||||||
return Infinity;
|
return Infinity;
|
||||||
else if (getUnitsManager().getCommandMode() === BLUE_COMMANDER)
|
else if (this.getCommandModeOptions().commandMode === BLUE_COMMANDER)
|
||||||
return this.getRTSOptions().spawnPoints.blue - this.#spentSpawnPoint;
|
return this.getCommandModeOptions().spawnPoints.blue - this.#spentSpawnPoint;
|
||||||
else if (getUnitsManager().getCommandMode() === RED_COMMANDER)
|
else if (this.getCommandModeOptions().commandMode === RED_COMMANDER)
|
||||||
return this.getRTSOptions().spawnPoints.red - this.#spentSpawnPoint;
|
return this.getCommandModeOptions().spawnPoints.red - this.#spentSpawnPoint;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCommandedCoalition() {
|
||||||
|
if (this.getCommandModeOptions().commandMode === BLUE_COMMANDER)
|
||||||
|
return "blue";
|
||||||
|
else if (this.getCommandModeOptions().commandMode === RED_COMMANDER)
|
||||||
|
return "red";
|
||||||
|
else
|
||||||
|
return "all";
|
||||||
|
}
|
||||||
|
|
||||||
refreshSpawnPoints() {
|
refreshSpawnPoints() {
|
||||||
var spawnPointsEl = document.querySelector("#spawn-points");
|
var spawnPointsEl = document.querySelector("#spawn-points");
|
||||||
if (spawnPointsEl) {
|
if (spawnPointsEl) {
|
||||||
@@ -133,68 +143,68 @@ export class MissionHandler {
|
|||||||
this.refreshSpawnPoints();
|
this.refreshSpawnPoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
showRTSSettingsDialog() {
|
showCommandModeDialog() {
|
||||||
/* Create the checkboxes to select the unit eras */
|
/* Create the checkboxes to select the unit eras */
|
||||||
var eras = aircraftDatabase.getEras().concat(helicopterDatabase.getEras()).concat(groundUnitDatabase.getEras()).concat(navyUnitDatabase.getEras());
|
var eras = aircraftDatabase.getEras().concat(helicopterDatabase.getEras()).concat(groundUnitDatabase.getEras()).concat(navyUnitDatabase.getEras());
|
||||||
eras = eras.filter((item: string, index: number) => eras.indexOf(item) === index).sort();
|
eras = eras.filter((item: string, index: number) => eras.indexOf(item) === index).sort();
|
||||||
this.#rtsErasDropdown.setOptionsElements(eras.map((era: string) => {
|
this.#commandModeErasDropdown.setOptionsElements(eras.map((era: string) => {
|
||||||
return createCheckboxOption(era, `Enable ${era} units spawns`, this.#RTSOptions.eras.includes(era));
|
return createCheckboxOption(era, `Enable ${era} units spawns`, this.getCommandModeOptions().eras.includes(era));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.#RTSSettingsDialog.classList.remove("hide");
|
this.#commandModeDialog.classList.remove("hide");
|
||||||
|
|
||||||
const restrictSpawnsCheckbox = this.#RTSSettingsDialog.querySelector("#restrict-spawns")?.querySelector("input") as HTMLInputElement;
|
const restrictSpawnsCheckbox = this.#commandModeDialog.querySelector("#restrict-spawns")?.querySelector("input") as HTMLInputElement;
|
||||||
const restrictToCoalitionCheckbox = this.#RTSSettingsDialog.querySelector("#restrict-to-coalition")?.querySelector("input") as HTMLInputElement;
|
const restrictToCoalitionCheckbox = this.#commandModeDialog.querySelector("#restrict-to-coalition")?.querySelector("input") as HTMLInputElement;
|
||||||
const blueSpawnPointsInput = this.#RTSSettingsDialog.querySelector("#blue-spawn-points")?.querySelector("input") as HTMLInputElement;
|
const blueSpawnPointsInput = this.#commandModeDialog.querySelector("#blue-spawn-points")?.querySelector("input") as HTMLInputElement;
|
||||||
const redSpawnPointsInput = this.#RTSSettingsDialog.querySelector("#red-spawn-points")?.querySelector("input") as HTMLInputElement;
|
const redSpawnPointsInput = this.#commandModeDialog.querySelector("#red-spawn-points")?.querySelector("input") as HTMLInputElement;
|
||||||
const setupTimeInput = this.#RTSSettingsDialog.querySelector("#setup-time")?.querySelector("input") as HTMLInputElement;
|
const setupTimeInput = this.#commandModeDialog.querySelector("#setup-time")?.querySelector("input") as HTMLInputElement;
|
||||||
|
|
||||||
restrictSpawnsCheckbox.checked = this.#RTSOptions.restrictSpawns;
|
restrictSpawnsCheckbox.checked = this.getCommandModeOptions().restrictSpawns;
|
||||||
restrictToCoalitionCheckbox.checked = this.#RTSOptions.restrictToCoalition;
|
restrictToCoalitionCheckbox.checked = this.getCommandModeOptions().restrictToCoalition;
|
||||||
blueSpawnPointsInput.value = String(this.#RTSOptions.spawnPoints.blue);
|
blueSpawnPointsInput.value = String(this.getCommandModeOptions().spawnPoints.blue);
|
||||||
redSpawnPointsInput.value = String(this.#RTSOptions.spawnPoints.red);
|
redSpawnPointsInput.value = String(this.getCommandModeOptions().spawnPoints.red);
|
||||||
setupTimeInput.value = String(Math.floor(this.#RTSOptions.setupTime / 60.0));
|
setupTimeInput.value = String(Math.floor(this.getCommandModeOptions().setupTime / 60.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#applyRTSOptions() {
|
#applycommandModeOptions() {
|
||||||
this.#RTSSettingsDialog.classList.add("hide");
|
this.#commandModeDialog.classList.add("hide");
|
||||||
|
|
||||||
const restrictSpawnsCheckbox = this.#RTSSettingsDialog.querySelector("#restrict-spawns")?.querySelector("input") as HTMLInputElement;
|
const restrictSpawnsCheckbox = this.#commandModeDialog.querySelector("#restrict-spawns")?.querySelector("input") as HTMLInputElement;
|
||||||
const restrictToCoalitionCheckbox = this.#RTSSettingsDialog.querySelector("#restrict-to-coalition")?.querySelector("input") as HTMLInputElement;
|
const restrictToCoalitionCheckbox = this.#commandModeDialog.querySelector("#restrict-to-coalition")?.querySelector("input") as HTMLInputElement;
|
||||||
const blueSpawnPointsInput = this.#RTSSettingsDialog.querySelector("#blue-spawn-points")?.querySelector("input") as HTMLInputElement;
|
const blueSpawnPointsInput = this.#commandModeDialog.querySelector("#blue-spawn-points")?.querySelector("input") as HTMLInputElement;
|
||||||
const redSpawnPointsInput = this.#RTSSettingsDialog.querySelector("#red-spawn-points")?.querySelector("input") as HTMLInputElement;
|
const redSpawnPointsInput = this.#commandModeDialog.querySelector("#red-spawn-points")?.querySelector("input") as HTMLInputElement;
|
||||||
const setupTimeInput = this.#RTSSettingsDialog.querySelector("#setup-time")?.querySelector("input") as HTMLInputElement;
|
const setupTimeInput = this.#commandModeDialog.querySelector("#setup-time")?.querySelector("input") as HTMLInputElement;
|
||||||
|
|
||||||
var eras: string[] = [];
|
var eras: string[] = [];
|
||||||
const enabledEras = getCheckboxOptions(this.#rtsErasDropdown);
|
const enabledEras = getCheckboxOptions(this.#commandModeErasDropdown);
|
||||||
Object.keys(enabledEras).forEach((key: string) => {if (enabledEras[key]) eras.push(key)});
|
Object.keys(enabledEras).forEach((key: string) => {if (enabledEras[key]) eras.push(key)});
|
||||||
setRTSOptions(restrictSpawnsCheckbox.checked, restrictToCoalitionCheckbox.checked, {blue: parseInt(blueSpawnPointsInput.value), red: parseInt(redSpawnPointsInput.value)}, eras, parseInt(setupTimeInput.value) * 60);
|
setCommandModeOptions(restrictSpawnsCheckbox.checked, restrictToCoalitionCheckbox.checked, {blue: parseInt(blueSpawnPointsInput.value), red: parseInt(redSpawnPointsInput.value)}, eras, parseInt(setupTimeInput.value) * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
#setRTSOptions(RTSOptions: RTSOptions) {
|
#setcommandModeOptions(commandModeOptions: CommandModeOptions) {
|
||||||
var RTSOptionsChanged = (!RTSOptions.eras.every((value: string, idx: number) => {return value === this.#RTSOptions.eras[idx]}) ||
|
var commandModeOptionsChanged = (!commandModeOptions.eras.every((value: string, idx: number) => {return value === this.getCommandModeOptions().eras[idx]}) ||
|
||||||
RTSOptions.spawnPoints.red !== this.#RTSOptions.spawnPoints.red ||
|
commandModeOptions.spawnPoints.red !== this.getCommandModeOptions().spawnPoints.red ||
|
||||||
RTSOptions.spawnPoints.blue !== this.#RTSOptions.spawnPoints.blue ||
|
commandModeOptions.spawnPoints.blue !== this.getCommandModeOptions().spawnPoints.blue ||
|
||||||
RTSOptions.restrictSpawns !== this.#RTSOptions.restrictSpawns ||
|
commandModeOptions.restrictSpawns !== this.getCommandModeOptions().restrictSpawns ||
|
||||||
RTSOptions.restrictToCoalition !== this.#RTSOptions.restrictToCoalition);
|
commandModeOptions.restrictToCoalition !== this.getCommandModeOptions().restrictToCoalition);
|
||||||
|
|
||||||
this.#RTSOptions = RTSOptions;
|
this.#commandModeOptions = commandModeOptions;
|
||||||
this.setSpentSpawnPoints(0);
|
this.setSpentSpawnPoints(0);
|
||||||
this.refreshSpawnPoints();
|
this.refreshSpawnPoints();
|
||||||
|
|
||||||
if (RTSOptionsChanged) {
|
if (commandModeOptionsChanged) {
|
||||||
document.dispatchEvent(new CustomEvent("RTSOptionsChanged", { detail: this }));
|
document.dispatchEvent(new CustomEvent("commandModeOptionsChanged", { detail: this }));
|
||||||
|
|
||||||
document.getElementById("rts-toolbar")?.classList.remove("hide");
|
document.getElementById("command-mode-toolbar")?.classList.remove("hide");
|
||||||
const el = document.getElementById("command-mode");
|
const el = document.getElementById("command-mode");
|
||||||
if (el) {
|
if (el) {
|
||||||
el.dataset.mode = RTSOptions.commandMode;
|
el.dataset.mode = commandModeOptions.commandMode;
|
||||||
el.textContent = RTSOptions.commandMode.toUpperCase();
|
el.textContent = commandModeOptions.commandMode.toUpperCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelector("#spawn-points-container")?.classList.toggle("hide", getUnitsManager().getCommandMode() === GAME_MASTER);
|
document.querySelector("#spawn-points-container")?.classList.toggle("hide", this.getCommandModeOptions().commandMode === GAME_MASTER || !this.getCommandModeOptions().restrictSpawns);
|
||||||
document.querySelector("#rts-settings-button")?.classList.toggle("hide", getUnitsManager().getCommandMode() !== GAME_MASTER);
|
document.querySelector("#command-mode-settings-button")?.classList.toggle("hide", this.getCommandModeOptions().commandMode !== GAME_MASTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
#onAirbaseClick(e: any) {
|
#onAirbaseClick(e: any) {
|
||||||
@@ -4,6 +4,7 @@ export class LogPanel extends Panel {
|
|||||||
#open: boolean = false;
|
#open: boolean = false;
|
||||||
#queuedMessages: number = 0;
|
#queuedMessages: number = 0;
|
||||||
#scrolledDown: boolean = true;
|
#scrolledDown: boolean = true;
|
||||||
|
#logs: {[key: string]: string} = {};
|
||||||
|
|
||||||
constructor(ID: string) {
|
constructor(ID: string) {
|
||||||
super(ID);
|
super(ID);
|
||||||
@@ -26,8 +27,13 @@ export class LogPanel extends Panel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appendLogs(logs: string[]) {
|
appendLogs(logs: {[key: string]: string}) {
|
||||||
logs.forEach((log: string) => this.appendLog(log));
|
Object.keys(logs).forEach((key: string) => {
|
||||||
|
if (!(key in this.#logs)) {
|
||||||
|
this.#logs[key] = logs[key];
|
||||||
|
this.appendLog(logs[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
appendLog(log: string) {
|
appendLog(log: string) {
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ export function setAdvacedOptions(ID: number, isTanker: boolean, isAWACS: boolea
|
|||||||
POST(data, () => { });
|
POST(data, () => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setRTSOptions(restrictSpawns: boolean, restrictToCoalition: boolean, spawnPoints: {blue: number, red: number}, eras: string[], setupTime: number) {
|
export function setCommandModeOptions(restrictSpawns: boolean, restrictToCoalition: boolean, spawnPoints: {blue: number, red: number}, eras: string[], setupTime: number) {
|
||||||
var command = {
|
var command = {
|
||||||
"restrictSpawns": restrictSpawns,
|
"restrictSpawns": restrictSpawns,
|
||||||
"restrictToCoalition": restrictToCoalition,
|
"restrictToCoalition": restrictToCoalition,
|
||||||
@@ -329,7 +329,7 @@ export function setRTSOptions(restrictSpawns: boolean, restrictToCoalition: bool
|
|||||||
"setupTime": setupTime
|
"setupTime": setupTime
|
||||||
};
|
};
|
||||||
|
|
||||||
var data = { "setRTSOptions": command };
|
var data = { "setCommandModeOptions": command };
|
||||||
POST(data, () => { });
|
POST(data, () => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +351,7 @@ export function startUpdate() {
|
|||||||
return data.time;
|
return data.time;
|
||||||
});
|
});
|
||||||
getLogs((data: any) => {
|
getLogs((data: any) => {
|
||||||
getLogPanel().appendLogs(Object.values(data.logs))
|
getLogPanel().appendLogs(data.logs)
|
||||||
return data.time;
|
return data.time;
|
||||||
});
|
});
|
||||||
getUnits((buffer: ArrayBuffer) => {return getUnitsManager()?.update(buffer), true /* Does a full refresh */});
|
getUnits((buffer: ArrayBuffer) => {return getUnitsManager()?.update(buffer), true /* Does a full refresh */});
|
||||||
@@ -389,7 +389,7 @@ export function requestRefresh() {
|
|||||||
return data.time;
|
return data.time;
|
||||||
});
|
});
|
||||||
getLogs((data: any) => {
|
getLogs((data: any) => {
|
||||||
getLogPanel().appendLogs(Object.values(data.logs))
|
getLogPanel().appendLogs(data.logs)
|
||||||
return data.time;
|
return data.time;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getUnitsManager } from "..";
|
import { getMissionHandler } from "..";
|
||||||
import { GAME_MASTER } from "../constants/constants";
|
import { GAME_MASTER } from "../constants/constants";
|
||||||
import { UnitDatabase } from "./unitdatabase"
|
import { UnitDatabase } from "./unitdatabase"
|
||||||
|
|
||||||
@@ -3982,7 +3982,7 @@ export class AircraftDatabase extends UnitDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSpawnPointsByName(name: string) {
|
getSpawnPointsByName(name: string) {
|
||||||
if (getUnitsManager().getCommandMode() == GAME_MASTER)
|
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const blueprint = this.getByName(name);
|
const blueprint = this.getByName(name);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getUnitsManager } from "..";
|
import { getMissionHandler} from "..";
|
||||||
import { GAME_MASTER } from "../constants/constants";
|
import { GAME_MASTER } from "../constants/constants";
|
||||||
import { UnitDatabase } from "./unitdatabase"
|
import { UnitDatabase } from "./unitdatabase"
|
||||||
|
|
||||||
@@ -1463,7 +1463,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSpawnPointsByName(name: string) {
|
getSpawnPointsByName(name: string) {
|
||||||
if (getUnitsManager().getCommandMode() == GAME_MASTER)
|
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const blueprint = this.getByName(name);
|
const blueprint = this.getByName(name);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getUnitsManager } from "..";
|
import { getMissionHandler } from "..";
|
||||||
import { GAME_MASTER } from "../constants/constants";
|
import { GAME_MASTER } from "../constants/constants";
|
||||||
import { UnitDatabase } from "./unitdatabase"
|
import { UnitDatabase } from "./unitdatabase"
|
||||||
|
|
||||||
@@ -595,7 +595,7 @@ export class HelicopterDatabase extends UnitDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSpawnPointsByName(name: string) {
|
getSpawnPointsByName(name: string) {
|
||||||
if (getUnitsManager().getCommandMode() == GAME_MASTER)
|
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const blueprint = this.getByName(name);
|
const blueprint = this.getByName(name);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getUnitsManager } from "..";
|
import { getMissionHandler } from "..";
|
||||||
import { GAME_MASTER } from "../constants/constants";
|
import { GAME_MASTER } from "../constants/constants";
|
||||||
import { UnitDatabase } from "./unitdatabase"
|
import { UnitDatabase } from "./unitdatabase"
|
||||||
|
|
||||||
@@ -461,7 +461,7 @@ export class NavyUnitDatabase extends UnitDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSpawnPointsByName(name: string) {
|
getSpawnPointsByName(name: string) {
|
||||||
if (getUnitsManager().getCommandMode() == GAME_MASTER)
|
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const blueprint = this.getByName(name);
|
const blueprint = this.getByName(name);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map, Point } from 'leaflet';
|
import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map, Point } from 'leaflet';
|
||||||
import { getMap, getUnitsManager } from '..';
|
import { getMap, getMissionHandler, getUnitsManager } from '..';
|
||||||
import { enumToCoalition, enumToEmissioNCountermeasure, getMarkerCategoryByName, enumToROE, enumToReactionToThreat, enumToState, getUnitDatabaseByCategory, mToFt, msToKnots, rad2deg, bearing, deg2rad } from '../other/utils';
|
import { enumToCoalition, enumToEmissioNCountermeasure, getMarkerCategoryByName, enumToROE, enumToReactionToThreat, enumToState, getUnitDatabaseByCategory, mToFt, msToKnots, rad2deg, bearing, deg2rad } from '../other/utils';
|
||||||
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures, setSpeedType, setAltitudeType, setOnOff, setFollowRoads, bombPoint, carpetBomb, bombBuilding, fireAtArea } from '../server/server';
|
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures, setSpeedType, setAltitudeType, setOnOff, setFollowRoads, bombPoint, carpetBomb, bombBuilding, fireAtArea } from '../server/server';
|
||||||
import { CustomMarker } from '../map/custommarker';
|
import { CustomMarker } from '../map/custommarker';
|
||||||
@@ -336,7 +336,7 @@ export class Unit extends CustomMarker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.getElement()?.querySelector(`.unit`)?.toggleAttribute("data-is-selected", selected);
|
this.getElement()?.querySelector(`.unit`)?.toggleAttribute("data-is-selected", selected);
|
||||||
if (getMap().getZoom() < 13) {
|
if (this.getCategory() === "GroundUnit" && getMap().getZoom() < 13) {
|
||||||
if (this.#isLeader)
|
if (this.#isLeader)
|
||||||
this.getGroupMembers().forEach((unit: Unit) => unit.setSelected(selected));
|
this.getGroupMembers().forEach((unit: Unit) => unit.setSelected(selected));
|
||||||
else
|
else
|
||||||
@@ -384,7 +384,7 @@ export class Unit extends CustomMarker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
belongsToCommandedCoalition() {
|
belongsToCommandedCoalition() {
|
||||||
if (getUnitsManager().getCommandMode() !== GAME_MASTER && getUnitsManager().getCommandedCoalition() !== this.#coalition)
|
if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER && getMissionHandler().getCommandedCoalition() !== this.#coalition)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1019,7 +1019,7 @@ export class Unit extends CustomMarker {
|
|||||||
}
|
}
|
||||||
else if (this.#targetID != 0 && getMap().getVisibilityOptions()[SHOW_UNIT_TARGETS]) {
|
else if (this.#targetID != 0 && getMap().getVisibilityOptions()[SHOW_UNIT_TARGETS]) {
|
||||||
const target = getUnitsManager().getUnitByID(this.#targetID);
|
const target = getUnitsManager().getUnitByID(this.#targetID);
|
||||||
if (target && (getUnitsManager().getCommandMode() == GAME_MASTER || (this.belongsToCommandedCoalition() && getUnitsManager().getUnitDetectedMethods(target).some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))))) {
|
if (target && (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || (this.belongsToCommandedCoalition() && getUnitsManager().getUnitDetectedMethods(target).some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))))) {
|
||||||
this.#drawTargetPosition(target.getPosition());
|
this.#drawTargetPosition(target.getPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,15 +30,15 @@ export class UnitDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBlueprints() {
|
getBlueprints() {
|
||||||
if (getUnitsManager().getCommandMode() == GAME_MASTER || !getMissionHandler().getRTSOptions().restrictSpawns)
|
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns)
|
||||||
return this.blueprints;
|
return this.blueprints;
|
||||||
else {
|
else {
|
||||||
var filteredBlueprints: { [key: string]: UnitBlueprint } = {};
|
var filteredBlueprints: { [key: string]: UnitBlueprint } = {};
|
||||||
for (let unit in this.blueprints) {
|
for (let unit in this.blueprints) {
|
||||||
const blueprint = this.blueprints[unit];
|
const blueprint = this.blueprints[unit];
|
||||||
if (this.getSpawnPointsByName(blueprint.name) < getMissionHandler().getAvailableSpawnPoints() &&
|
if (this.getSpawnPointsByName(blueprint.name) <= getMissionHandler().getAvailableSpawnPoints() &&
|
||||||
getMissionHandler().getRTSOptions().eras.includes(blueprint.era) &&
|
getMissionHandler().getCommandModeOptions().eras.includes(blueprint.era) &&
|
||||||
(!getMissionHandler().getRTSOptions().restrictToCoalition || blueprint.coalition === getUnitsManager().getCommandedCoalition())) {
|
(!getMissionHandler().getCommandModeOptions().restrictToCoalition || blueprint.coalition === getMissionHandler().getCommandedCoalition())) {
|
||||||
filteredBlueprints[unit] = blueprint;
|
filteredBlueprints[unit] = blueprint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cloneUnit, deleteUnit, spawnAircrafts, spawnGroundUnits, spawnHelicopte
|
|||||||
import { bearingAndDistanceToLatLng, deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils";
|
import { bearingAndDistanceToLatLng, deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils";
|
||||||
import { CoalitionArea } from "../map/coalitionarea";
|
import { CoalitionArea } from "../map/coalitionarea";
|
||||||
import { groundUnitDatabase } from "./groundunitdatabase";
|
import { groundUnitDatabase } from "./groundunitdatabase";
|
||||||
import { BLUE_COMMANDER, DataIndexes, GAME_MASTER, IADSDensities, IDLE, MOVE_UNIT, NONE, RED_COMMANDER } from "../constants/constants";
|
import { DataIndexes, GAME_MASTER, IADSDensities, IDLE, MOVE_UNIT, NONE } from "../constants/constants";
|
||||||
import { DataExtractor } from "./dataextractor";
|
import { DataExtractor } from "./dataextractor";
|
||||||
import { Contact } from "../@types/unit";
|
import { Contact } from "../@types/unit";
|
||||||
import { citiesDatabase } from "./citiesdatabase";
|
import { citiesDatabase } from "./citiesdatabase";
|
||||||
@@ -19,7 +19,6 @@ export class UnitsManager {
|
|||||||
#selectionEventDisabled: boolean = false;
|
#selectionEventDisabled: boolean = false;
|
||||||
#pasteDisabled: boolean = false;
|
#pasteDisabled: boolean = false;
|
||||||
#hiddenTypes: string[] = [];
|
#hiddenTypes: string[] = [];
|
||||||
#commandMode: string = NONE;
|
|
||||||
#requestDetectionUpdate: boolean = false;
|
#requestDetectionUpdate: boolean = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -36,6 +35,7 @@ export class UnitsManager {
|
|||||||
document.addEventListener('exportToFile', () => this.exportToFile());
|
document.addEventListener('exportToFile', () => this.exportToFile());
|
||||||
document.addEventListener('importFromFile', () => this.importFromFile());
|
document.addEventListener('importFromFile', () => this.importFromFile());
|
||||||
document.addEventListener('contactsUpdated', (e: CustomEvent) => {this.#requestDetectionUpdate = true});
|
document.addEventListener('contactsUpdated', (e: CustomEvent) => {this.#requestDetectionUpdate = true});
|
||||||
|
document.addEventListener("commandModeOptionsChanged", () => {Object.values(this.#units).forEach((unit: Unit) => unit.updateVisibility())});
|
||||||
}
|
}
|
||||||
|
|
||||||
getSelectableAircraft() {
|
getSelectableAircraft() {
|
||||||
@@ -96,7 +96,7 @@ export class UnitsManager {
|
|||||||
this.#units[ID]?.setData(dataExtractor);
|
this.#units[ID]?.setData(dataExtractor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.#requestDetectionUpdate && this.getCommandMode() != GAME_MASTER) {
|
if (this.#requestDetectionUpdate && getMissionHandler().getCommandModeOptions().commandMode != GAME_MASTER) {
|
||||||
for (let ID in this.#units) {
|
for (let ID in this.#units) {
|
||||||
var unit = this.#units[ID];
|
var unit = this.#units[ID];
|
||||||
if (!unit.belongsToCommandedCoalition())
|
if (!unit.belongsToCommandedCoalition())
|
||||||
@@ -127,28 +127,6 @@ export class UnitsManager {
|
|||||||
return this.#hiddenTypes;
|
return this.#hiddenTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCommandMode(newCommandMode: string) {
|
|
||||||
if (newCommandMode !== this.#commandMode) {
|
|
||||||
document.dispatchEvent(new CustomEvent("commandModeChanged", { detail: this }));
|
|
||||||
this.#commandMode = newCommandMode;
|
|
||||||
for (let ID in this.#units)
|
|
||||||
this.#units[ID].updateVisibility();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCommandMode() {
|
|
||||||
return this.#commandMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
getCommandedCoalition() {
|
|
||||||
if (this.getCommandMode() === BLUE_COMMANDER)
|
|
||||||
return "blue";
|
|
||||||
else if (this.getCommandMode() === RED_COMMANDER)
|
|
||||||
return "red";
|
|
||||||
else
|
|
||||||
return "all";
|
|
||||||
}
|
|
||||||
|
|
||||||
selectUnit(ID: number, deselectAllUnits: boolean = true) {
|
selectUnit(ID: number, deselectAllUnits: boolean = true) {
|
||||||
if (deselectAllUnits)
|
if (deselectAllUnits)
|
||||||
this.getSelectedUnits().filter((unit: Unit) => unit.ID !== ID).forEach((unit: Unit) => unit.setSelected(false));
|
this.getSelectedUnits().filter((unit: Unit) => unit.ID !== ID).forEach((unit: Unit) => unit.setSelected(false));
|
||||||
@@ -573,7 +551,7 @@ export class UnitsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pasteUnits() {
|
pasteUnits() {
|
||||||
if (!this.#pasteDisabled && getUnitsManager().getCommandMode() == GAME_MASTER) {
|
if (!this.#pasteDisabled && getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER) {
|
||||||
/* Compute the position of the center of the copied units */
|
/* Compute the position of the center of the copied units */
|
||||||
var nUnits = this.#copiedUnits.length;
|
var nUnits = this.#copiedUnits.length;
|
||||||
var avgLat = 0;
|
var avgLat = 0;
|
||||||
@@ -613,7 +591,7 @@ export class UnitsManager {
|
|||||||
getInfoPopup().setText(`${this.#copiedUnits.length - 1} units pasted`);
|
getInfoPopup().setText(`${this.#copiedUnits.length - 1} units pasted`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
getInfoPopup().setText(`Unit cloning is disabled in ${getUnitsManager().getCommandMode()} mode`);
|
getInfoPopup().setText(`Unit cloning is disabled in ${getMissionHandler().getCommandModeOptions().commandMode} mode`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,34 +668,35 @@ export class UnitsManager {
|
|||||||
spawnUnits(category: string, units: any, coalition: string = "blue", immediate: boolean = true, airbase: string = "") {
|
spawnUnits(category: string, units: any, coalition: string = "blue", immediate: boolean = true, airbase: string = "") {
|
||||||
var spawnPoints = 0;
|
var spawnPoints = 0;
|
||||||
if (category === "Aircraft") {
|
if (category === "Aircraft") {
|
||||||
if (airbase == "" && getMissionHandler().getRemainingSetupTime() < 0 && this.getCommandMode() !== GAME_MASTER) {
|
if (airbase == "" && getMissionHandler().getRemainingSetupTime() < 0 && getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER) {
|
||||||
getInfoPopup().setText("Aircrafts can be air spawned during the SETUP phase only");
|
getInfoPopup().setText("Aircrafts can be air spawned during the SETUP phase only");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
spawnPoints = units.reduce((points: number, unit: any) => {return points + aircraftDatabase.getSpawnPointsByName(unit.unitType)}, 0);
|
spawnPoints = units.reduce((points: number, unit: any) => {return points + aircraftDatabase.getSpawnPointsByName(unit.unitType)}, 0);
|
||||||
spawnAircrafts(units, coalition, airbase, immediate, spawnPoints);
|
spawnAircrafts(units, coalition, airbase, immediate, spawnPoints);
|
||||||
} else if (category === "Helicopter") {
|
} else if (category === "Helicopter") {
|
||||||
if (airbase == "" && getMissionHandler().getRemainingSetupTime() < 0 && this.getCommandMode() !== GAME_MASTER) {
|
if (airbase == "" && getMissionHandler().getRemainingSetupTime() < 0 && getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER) {
|
||||||
getInfoPopup().setText("Helicopters can be air spawned during the SETUP phase only");
|
getInfoPopup().setText("Helicopters can be air spawned during the SETUP phase only");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
spawnPoints = units.reduce((points: number, unit: any) => {return points + helicopterDatabase.getSpawnPointsByName(unit.unitType)}, 0);
|
spawnPoints = units.reduce((points: number, unit: any) => {return points + helicopterDatabase.getSpawnPointsByName(unit.unitType)}, 0);
|
||||||
spawnHelicopters(units, coalition, airbase, immediate, spawnPoints);
|
spawnHelicopters(units, coalition, airbase, immediate, spawnPoints);
|
||||||
} else if (category === "GroundUnit") {
|
} else if (category === "GroundUnit") {
|
||||||
if (getMissionHandler().getRemainingSetupTime() < 0 && this.getCommandMode() !== GAME_MASTER) {
|
if (getMissionHandler().getRemainingSetupTime() < 0 && getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER) {
|
||||||
getInfoPopup().setText("Ground units can be spawned during the SETUP phase only");
|
getInfoPopup().setText("Ground units can be spawned during the SETUP phase only");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
spawnPoints = units.reduce((points: number, unit: any) => {return points + groundUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0);
|
spawnPoints = units.reduce((points: number, unit: any) => {return points + groundUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0);
|
||||||
spawnGroundUnits(units, coalition, immediate, spawnPoints);
|
spawnGroundUnits(units, coalition, immediate, spawnPoints);
|
||||||
} else if (category === "NavyUnit") {
|
} else if (category === "NavyUnit") {
|
||||||
if (getMissionHandler().getRemainingSetupTime() < 0 && this.getCommandMode() !== GAME_MASTER) {
|
if (getMissionHandler().getRemainingSetupTime() < 0 && getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER) {
|
||||||
getInfoPopup().setText("Navy units can be spawned during the SETUP phase only");
|
getInfoPopup().setText("Navy units can be spawned during the SETUP phase only");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
spawnPoints = units.reduce((points: number, unit: any) => {return points + navyUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0);
|
spawnPoints = units.reduce((points: number, unit: any) => {return points + navyUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0);
|
||||||
spawnNavyUnits(units, coalition, immediate, spawnPoints);
|
spawnNavyUnits(units, coalition, immediate, spawnPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spawnPoints <= getMissionHandler().getAvailableSpawnPoints()) {
|
if (spawnPoints <= getMissionHandler().getAvailableSpawnPoints()) {
|
||||||
getMissionHandler().setSpentSpawnPoints(spawnPoints);
|
getMissionHandler().setSpentSpawnPoints(spawnPoints);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<div id="toolbar-container">
|
<div id="toolbar-container">
|
||||||
<%- include('toolbars/primary.ejs') %>
|
<%- include('toolbars/primary.ejs') %>
|
||||||
<%- include('toolbars/rts.ejs') %>
|
<%- include('toolbars/commandmode.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%- include('other/dialogs.ejs') %>
|
<%- include('other/dialogs.ejs') %>
|
||||||
|
|||||||
@@ -233,11 +233,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="rts-settings-dialog" class="ol-panel ol-dialog olympus-dialog-close hide" oncontextmenu="return false;">
|
<div id="command-mode-settings-dialog" class="ol-panel ol-dialog olympus-dialog-close hide" oncontextmenu="return false;">
|
||||||
<div class="ol-dialog-close" data-on-click="closeDialog"></div>
|
<div class="ol-dialog-close" data-on-click="closeDialog"></div>
|
||||||
|
|
||||||
<div class="ol-dialog-header">
|
<div class="ol-dialog-header">
|
||||||
<h3 id="unit-name">RTS mode settings</h3>
|
<h3 id="unit-name">command-mode mode settings</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ol-dialog-content">
|
<div class="ol-dialog-content">
|
||||||
@@ -269,7 +269,7 @@
|
|||||||
<div class="ol-group">
|
<div class="ol-group">
|
||||||
<label>Available eras: </label>
|
<label>Available eras: </label>
|
||||||
|
|
||||||
<div id="rts-era-options" class="ol-select">
|
<div id="command-mode-era-options" class="ol-select">
|
||||||
<div class="ol-select-value">Select eras</div>
|
<div class="ol-select-value">Select eras</div>
|
||||||
<div class="ol-select-options">
|
<div class="ol-select-options">
|
||||||
<!-- This is where all the available era buttons will be shown-->
|
<!-- This is where all the available era buttons will be shown-->
|
||||||
@@ -299,7 +299,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ol-dialog-footer ol-group">
|
<div class="ol-dialog-footer ol-group">
|
||||||
<button class="ol-button-apply" data-on-click="applyRTSOptions">Apply</button>
|
<button class="ol-button-apply" data-on-click="applycommandModeOptions">Apply</button>
|
||||||
<button class="ol-button-close" data-on-click="closeDialog">Close</button>
|
<button class="ol-button-close" data-on-click="closeDialog">Close</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
6
client/views/toolbars/commandmode.ejs
Normal file
6
client/views/toolbars/commandmode.ejs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<nav id="command-mode-toolbar" class="ol-panel hide" oncontextmenu="return false;">
|
||||||
|
<span id="command-mode"></span>
|
||||||
|
<div id="spawn-points-container">Spawn points<span id="spawn-points"></span></div>
|
||||||
|
<span id="command-mode-phase"></span>
|
||||||
|
<button id="command-mode-settings-button" class="ol-button" data-on-click="showCommandModeDialog"><img src="/resources/theme/images/icons/gears-solid.svg" inject-svg>Settings</button>
|
||||||
|
</nav>
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<nav id="rts-toolbar" class="ol-panel hide" oncontextmenu="return false;">
|
|
||||||
<span id="command-mode"></span>
|
|
||||||
<div id="spawn-points-container">Spawn points<span id="spawn-points"></span></div>
|
|
||||||
<span id="rts-phase"></span>
|
|
||||||
<button id="rts-settings-button" class="ol-button" data-on-click="showRTSSettingsDialog"><img src="/resources/theme/images/icons/gears-solid.svg" inject-svg>Settings</button>
|
|
||||||
</nav>
|
|
||||||
@@ -11,24 +11,27 @@ public:
|
|||||||
|
|
||||||
void appendCommand(Command* command);
|
void appendCommand(Command* command);
|
||||||
void execute(lua_State* L);
|
void execute(lua_State* L);
|
||||||
void handleRequest(string key, json::value value);
|
void handleRequest(string key, json::value value, string username);
|
||||||
|
bool checkSpawnPoints(int spawnPoints, string coalition);
|
||||||
|
|
||||||
void setFrameRate(double newFrameRate) { frameRate = newFrameRate; }
|
void setFrameRate(double newFrameRate) { frameRate = newFrameRate; }
|
||||||
void setRestrictSpawns(bool newRestrictSpawns) { restrictSpawns = newRestrictSpawns; }
|
void setRestrictSpawns(bool newRestrictSpawns) { restrictSpawns = newRestrictSpawns; }
|
||||||
void setRestrictToCoalition(bool newRestrictToCoalition) { restrictSpawns = newRestrictToCoalition; }
|
void setRestrictToCoalition(bool newRestrictToCoalition) { restrictToCoalition = newRestrictToCoalition; }
|
||||||
void setSetupTime(unsigned int newSetupTime) { setupTime = newSetupTime; }
|
void setSetupTime(unsigned int newSetupTime) { setupTime = newSetupTime; }
|
||||||
void setBlueSpawnPoints(unsigned int newBlueSpawnPoints) { blueSpawnPoints = newBlueSpawnPoints; }
|
void setBlueSpawnPoints(unsigned int newBlueSpawnPoints) { blueSpawnPoints = newBlueSpawnPoints; }
|
||||||
void setRedSpawnPoints(unsigned int newRedSpawnPoints) { redSpawnPoints = newRedSpawnPoints; }
|
void setRedSpawnPoints(unsigned int newRedSpawnPoints) { redSpawnPoints = newRedSpawnPoints; }
|
||||||
void setEras(vector<string> newEras) { eras = newEras; }
|
void setEras(vector<string> newEras) { eras = newEras; }
|
||||||
|
void setCommandModeOptions(json::value newOptions);
|
||||||
|
|
||||||
int getFrameRate() { return frameRate; };
|
int getFrameRate() { return frameRate; };
|
||||||
int getLoad();
|
int getLoad();
|
||||||
bool getRestrictSpawns() { return restrictSpawns; }
|
bool getRestrictSpawns() { return restrictSpawns; }
|
||||||
bool getRestrictToCoalition() { return restrictSpawns; }
|
bool getRestrictToCoalition() { return restrictToCoalition; }
|
||||||
unsigned int getSetupTime() { return setupTime; }
|
unsigned int getSetupTime() { return setupTime; }
|
||||||
unsigned int getBlueSpawnPoints() { return blueSpawnPoints; }
|
unsigned int getBlueSpawnPoints() { return blueSpawnPoints; }
|
||||||
unsigned int getRedSpawnPoints() { return redSpawnPoints; }
|
unsigned int getRedSpawnPoints() { return redSpawnPoints; }
|
||||||
vector<string> getEras() { return eras; }
|
vector<string> getEras() { return eras; }
|
||||||
|
json::value getCommandModeOptions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
list<Command*> commands;
|
list<Command*> commands;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ private:
|
|||||||
void handle_request(http_request request, function<void(json::value const&, json::value&)> action);
|
void handle_request(http_request request, function<void(json::value const&, json::value&)> action);
|
||||||
void handle_put(http_request request);
|
void handle_put(http_request request);
|
||||||
|
|
||||||
|
string extractUsername(http_request& request);
|
||||||
string extractPassword(http_request& request);
|
string extractPassword(http_request& request);
|
||||||
|
|
||||||
void task();
|
void task();
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ extern "C" DllExport int coreFrame(lua_State* L)
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
/* Lock for thread safety */
|
||||||
|
lock_guard<mutex> guard(mutexLock);
|
||||||
|
|
||||||
frameCounter++;
|
frameCounter++;
|
||||||
|
|
||||||
const std::chrono::duration<double> executionDuration = std::chrono::system_clock::now() - lastExecution;
|
const std::chrono::duration<double> executionDuration = std::chrono::system_clock::now() - lastExecution;
|
||||||
@@ -91,9 +94,9 @@ extern "C" DllExport int coreUnitsData(lua_State * L)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
/* Lock for thread safety */
|
/* Lock for thread safety */
|
||||||
json::value unitsData = json::value::object();
|
|
||||||
|
|
||||||
lock_guard<mutex> guard(mutexLock);
|
lock_guard<mutex> guard(mutexLock);
|
||||||
|
|
||||||
|
json::value unitsData = json::value::object();
|
||||||
lua_getglobal(L, "Olympus");
|
lua_getglobal(L, "Olympus");
|
||||||
lua_getfield(L, -1, "unitsData");
|
lua_getfield(L, -1, "unitsData");
|
||||||
luaTableToJSON(L, -1, unitsData);
|
luaTableToJSON(L, -1, unitsData);
|
||||||
@@ -115,6 +118,7 @@ extern "C" DllExport int coreMissionData(lua_State * L)
|
|||||||
|
|
||||||
/* Lock for thread safety */
|
/* Lock for thread safety */
|
||||||
lock_guard<mutex> guard(mutexLock);
|
lock_guard<mutex> guard(mutexLock);
|
||||||
|
|
||||||
lua_getglobal(L, "Olympus");
|
lua_getglobal(L, "Olympus");
|
||||||
lua_getfield(L, -1, "missionData");
|
lua_getfield(L, -1, "missionData");
|
||||||
luaTableToJSON(L, -1, missionData);
|
luaTableToJSON(L, -1, missionData);
|
||||||
|
|||||||
@@ -68,12 +68,79 @@ void Scheduler::execute(lua_State* L)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::handleRequest(string key, json::value value)
|
void Scheduler::setCommandModeOptions(json::value value) {
|
||||||
|
if (value.has_boolean_field(L"restrictSpawns"))
|
||||||
|
setRestrictSpawns(value[L"restrictSpawns"].as_bool());
|
||||||
|
if (value.has_boolean_field(L"restrictToCoalition"))
|
||||||
|
setRestrictToCoalition(value[L"restrictToCoalition"].as_bool());
|
||||||
|
if (value.has_number_field(L"setupTime"))
|
||||||
|
setSetupTime(value[L"setupTime"].as_number().to_int32());
|
||||||
|
if (value.has_object_field(L"spawnPoints")) {
|
||||||
|
if (value[L"spawnPoints"].has_number_field(L"blue"))
|
||||||
|
setBlueSpawnPoints(value[L"spawnPoints"][L"blue"].as_number().to_int32());
|
||||||
|
if (value[L"spawnPoints"].has_number_field(L"red"))
|
||||||
|
setRedSpawnPoints(value[L"spawnPoints"][L"red"].as_number().to_int32());
|
||||||
|
}
|
||||||
|
if (value.has_array_field(L"eras")) {
|
||||||
|
int length = value[L"eras"].as_array().size();
|
||||||
|
vector<string> newEras;
|
||||||
|
for (int idx = 0; idx < length; idx++)
|
||||||
|
newEras.push_back(to_string(value[L"eras"].as_array().at(idx)));
|
||||||
|
setEras(newEras);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json::value Scheduler::getCommandModeOptions() {
|
||||||
|
json::value json = json::value::object();
|
||||||
|
|
||||||
|
json[L"restrictSpawns"] = json::value(getRestrictSpawns());
|
||||||
|
json[L"restrictToCoalition"] = json::value(getRestrictToCoalition());
|
||||||
|
json[L"setupTime"] = json::value(getSetupTime());
|
||||||
|
json[L"spawnPoints"] = json::value::object();
|
||||||
|
json[L"spawnPoints"][L"blue"] = json::value(getBlueSpawnPoints());
|
||||||
|
json[L"spawnPoints"][L"red"] = json::value(getRedSpawnPoints());
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
json[L"eras"] = json::value::array();
|
||||||
|
for (string era : getEras())
|
||||||
|
json[L"eras"][idx++] = json::value(to_wstring(era));
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scheduler::checkSpawnPoints(int spawnPoints, string coalition)
|
||||||
|
{
|
||||||
|
if (!getRestrictSpawns()) return true;
|
||||||
|
|
||||||
|
if (coalition.compare("blue") == 0) {
|
||||||
|
if (getBlueSpawnPoints() - spawnPoints >= 0) {
|
||||||
|
setBlueSpawnPoints(getBlueSpawnPoints() - spawnPoints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log("Not enough blue coalition spawn points available. Available: " + to_string(getBlueSpawnPoints()) + ", required: " + to_string(spawnPoints));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (coalition.compare("red") == 0) {
|
||||||
|
if (getRedSpawnPoints() - spawnPoints >= 0) {
|
||||||
|
setRedSpawnPoints(getRedSpawnPoints() - spawnPoints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log("Not enough red coalition spawn points available. Available: " + to_string(getRedSpawnPoints()) + ", required: " + to_string(spawnPoints));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::handleRequest(string key, json::value value, string username)
|
||||||
{
|
{
|
||||||
Command* command = nullptr;
|
Command* command = nullptr;
|
||||||
|
|
||||||
log("Received request with ID: " + key);
|
log("Received request with ID: " + key);
|
||||||
log(value.serialize());
|
log(L"Incoming command raw value: " + value.serialize());
|
||||||
|
|
||||||
if (key.compare("setPath") == 0)
|
if (key.compare("setPath") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
@@ -89,14 +156,13 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
string WP = to_string(i);
|
string WP = to_string(i);
|
||||||
double lat = path[i][L"lat"].as_double();
|
double lat = path[i][L"lat"].as_double();
|
||||||
double lng = path[i][L"lng"].as_double();
|
double lng = path[i][L"lng"].as_double();
|
||||||
log(unitName + " set path destination " + WP + " (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
||||||
Coords dest; dest.lat = lat; dest.lng = lng;
|
Coords dest; dest.lat = lat; dest.lng = lng;
|
||||||
newPath.push_back(dest);
|
newPath.push_back(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
unit->setActivePath(newPath);
|
unit->setActivePath(newPath);
|
||||||
unit->setState(State::REACH_DESTINATION);
|
unit->setState(State::REACH_DESTINATION);
|
||||||
log(unitName + " new path set successfully");
|
log(username + " updated destination path for unit " + unitName, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key.compare("smoke") == 0)
|
else if (key.compare("smoke") == 0)
|
||||||
@@ -104,7 +170,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
string color = to_string(value[L"color"]);
|
string color = to_string(value[L"color"]);
|
||||||
double lat = value[L"location"][L"lat"].as_double();
|
double lat = value[L"location"][L"lat"].as_double();
|
||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
log("Adding " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")");
|
log(username + " added a " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")", true);
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
command = dynamic_cast<Command*>(new Smoke(color, loc));
|
command = dynamic_cast<Command*>(new Smoke(color, loc));
|
||||||
}
|
}
|
||||||
@@ -114,6 +180,9 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
string coalition = to_string(value[L"coalition"]);
|
string coalition = to_string(value[L"coalition"]);
|
||||||
string airbaseName = to_string(value[L"airbaseName"]);
|
string airbaseName = to_string(value[L"airbaseName"]);
|
||||||
|
|
||||||
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
||||||
|
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
||||||
|
|
||||||
vector<string> unitTypes;
|
vector<string> unitTypes;
|
||||||
vector<Coords> locations;
|
vector<Coords> locations;
|
||||||
vector<string> loadouts;
|
vector<string> loadouts;
|
||||||
@@ -125,10 +194,10 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
|
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
|
||||||
string loadout = to_string(unit[L"loadout"]);
|
string loadout = to_string(unit[L"loadout"]);
|
||||||
|
|
||||||
log("Spawning " + coalition + " aircraft of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
||||||
unitTypes.push_back(unitType);
|
unitTypes.push_back(unitType);
|
||||||
locations.push_back(location);
|
locations.push_back(location);
|
||||||
loadouts.push_back(loadout);
|
loadouts.push_back(loadout);
|
||||||
|
log(username + " spawned a " + coalition + " " + unitType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
command = dynamic_cast<Command*>(new SpawnAircrafts(coalition, unitTypes, locations, loadouts, airbaseName, immediate));
|
command = dynamic_cast<Command*>(new SpawnAircrafts(coalition, unitTypes, locations, loadouts, airbaseName, immediate));
|
||||||
@@ -139,6 +208,9 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
string coalition = to_string(value[L"coalition"]);
|
string coalition = to_string(value[L"coalition"]);
|
||||||
string airbaseName = to_string(value[L"airbaseName"]);
|
string airbaseName = to_string(value[L"airbaseName"]);
|
||||||
|
|
||||||
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
||||||
|
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
||||||
|
|
||||||
vector<string> unitTypes;
|
vector<string> unitTypes;
|
||||||
vector<Coords> locations;
|
vector<Coords> locations;
|
||||||
vector<string> loadouts;
|
vector<string> loadouts;
|
||||||
@@ -150,10 +222,10 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
|
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
|
||||||
string loadout = to_string(unit[L"loadout"]);
|
string loadout = to_string(unit[L"loadout"]);
|
||||||
|
|
||||||
log("Spawning " + coalition + " helicopter of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
||||||
unitTypes.push_back(unitType);
|
unitTypes.push_back(unitType);
|
||||||
locations.push_back(location);
|
locations.push_back(location);
|
||||||
loadouts.push_back(loadout);
|
loadouts.push_back(loadout);
|
||||||
|
log(username + " spawned a " + coalition + " " + unitType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
command = dynamic_cast<Command*>(new SpawnHelicopters(coalition, unitTypes, locations, loadouts, airbaseName, immediate));
|
command = dynamic_cast<Command*>(new SpawnHelicopters(coalition, unitTypes, locations, loadouts, airbaseName, immediate));
|
||||||
@@ -163,6 +235,9 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
bool immediate = value[L"immediate"].as_bool();
|
bool immediate = value[L"immediate"].as_bool();
|
||||||
string coalition = to_string(value[L"coalition"]);
|
string coalition = to_string(value[L"coalition"]);
|
||||||
|
|
||||||
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
||||||
|
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
||||||
|
|
||||||
vector<string> unitTypes;
|
vector<string> unitTypes;
|
||||||
vector<Coords> locations;
|
vector<Coords> locations;
|
||||||
for (auto unit : value[L"units"].as_array()) {
|
for (auto unit : value[L"units"].as_array()) {
|
||||||
@@ -170,9 +245,10 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
double lat = unit[L"location"][L"lat"].as_double();
|
double lat = unit[L"location"][L"lat"].as_double();
|
||||||
double lng = unit[L"location"][L"lng"].as_double();
|
double lng = unit[L"location"][L"lng"].as_double();
|
||||||
Coords location; location.lat = lat; location.lng = lng;
|
Coords location; location.lat = lat; location.lng = lng;
|
||||||
log("Spawning " + coalition + " GroundUnit of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
||||||
unitTypes.push_back(unitType);
|
unitTypes.push_back(unitType);
|
||||||
locations.push_back(location);
|
locations.push_back(location);
|
||||||
|
log(username + " spawned a " + coalition + " " + unitType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
command = dynamic_cast<Command*>(new SpawnGroundUnits(coalition, unitTypes, locations, immediate));
|
command = dynamic_cast<Command*>(new SpawnGroundUnits(coalition, unitTypes, locations, immediate));
|
||||||
@@ -182,6 +258,9 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
bool immediate = value[L"immediate"].as_bool();
|
bool immediate = value[L"immediate"].as_bool();
|
||||||
string coalition = to_string(value[L"coalition"]);
|
string coalition = to_string(value[L"coalition"]);
|
||||||
|
|
||||||
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
||||||
|
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
||||||
|
|
||||||
vector<string> unitTypes;
|
vector<string> unitTypes;
|
||||||
vector<Coords> locations;
|
vector<Coords> locations;
|
||||||
for (auto unit : value[L"units"].as_array()) {
|
for (auto unit : value[L"units"].as_array()) {
|
||||||
@@ -189,9 +268,10 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
double lat = unit[L"location"][L"lat"].as_double();
|
double lat = unit[L"location"][L"lat"].as_double();
|
||||||
double lng = unit[L"location"][L"lng"].as_double();
|
double lng = unit[L"location"][L"lng"].as_double();
|
||||||
Coords location; location.lat = lat; location.lng = lng;
|
Coords location; location.lat = lat; location.lng = lng;
|
||||||
log("Spawning " + coalition + " NavyUnit of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
||||||
unitTypes.push_back(unitType);
|
unitTypes.push_back(unitType);
|
||||||
locations.push_back(location);
|
locations.push_back(location);
|
||||||
|
log(username + " spawned a " + coalition + " " + unitType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
command = dynamic_cast<Command*>(new SpawnNavyUnits(coalition, unitTypes, locations, immediate));
|
command = dynamic_cast<Command*>(new SpawnNavyUnits(coalition, unitTypes, locations, immediate));
|
||||||
@@ -218,7 +298,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log("Unit " + unitName + " attacking unit " + targetName);
|
log(username + " tasked unit " + unitName + " to attack unit " + targetName, true);
|
||||||
unit->setTargetID(targetID);
|
unit->setTargetID(targetID);
|
||||||
unit->setState(State::ATTACK);
|
unit->setState(State::ATTACK);
|
||||||
}
|
}
|
||||||
@@ -247,7 +327,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log("Unit " + unitName + " following unit " + leaderName);
|
log(username + " tasked unit " + unitName + " to follow unit " + leaderName, true);
|
||||||
unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ));
|
unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ));
|
||||||
unit->setLeaderID(leaderID);
|
unit->setLeaderID(leaderID);
|
||||||
unit->setState(State::FOLLOW);
|
unit->setState(State::FOLLOW);
|
||||||
@@ -307,7 +387,6 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
command = dynamic_cast<Command*>(new Clone(ID, loc));
|
command = dynamic_cast<Command*>(new Clone(ID, loc));
|
||||||
log("Cloning unit " + to_string(ID));
|
|
||||||
}
|
}
|
||||||
else if (key.compare("setROE") == 0)
|
else if (key.compare("setROE") == 0)
|
||||||
{
|
{
|
||||||
@@ -316,6 +395,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unsigned char ROE = value[L"ROE"].as_number().to_uint32();
|
unsigned char ROE = value[L"ROE"].as_number().to_uint32();
|
||||||
unit->setROE(ROE);
|
unit->setROE(ROE);
|
||||||
|
log(username + " set unit " + unit->getName() + " ROE to " + to_string(ROE), true);
|
||||||
}
|
}
|
||||||
else if (key.compare("setReactionToThreat") == 0)
|
else if (key.compare("setReactionToThreat") == 0)
|
||||||
{
|
{
|
||||||
@@ -324,6 +404,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().to_uint32();
|
unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().to_uint32();
|
||||||
unit->setReactionToThreat(reactionToThreat);
|
unit->setReactionToThreat(reactionToThreat);
|
||||||
|
log(username + " set unit " + unit->getName() + " reaction to threat to " + to_string(reactionToThreat), true);
|
||||||
}
|
}
|
||||||
else if (key.compare("setEmissionsCountermeasures") == 0)
|
else if (key.compare("setEmissionsCountermeasures") == 0)
|
||||||
{
|
{
|
||||||
@@ -332,6 +413,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().to_uint32();
|
unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().to_uint32();
|
||||||
unit->setEmissionsCountermeasures(emissionsCountermeasures);
|
unit->setEmissionsCountermeasures(emissionsCountermeasures);
|
||||||
|
log(username + " set unit " + unit->getName() + " emissions and countermeasures to " + to_string(emissionsCountermeasures), true);
|
||||||
}
|
}
|
||||||
else if (key.compare("landAt") == 0)
|
else if (key.compare("landAt") == 0)
|
||||||
{
|
{
|
||||||
@@ -342,6 +424,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
unit->landAt(loc);
|
unit->landAt(loc);
|
||||||
|
log(username + " tasked unit " + unit->getName() + " to land", true);
|
||||||
}
|
}
|
||||||
else if (key.compare("deleteUnit") == 0)
|
else if (key.compare("deleteUnit") == 0)
|
||||||
{
|
{
|
||||||
@@ -349,6 +432,8 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
bool explosion = value[L"explosion"].as_bool();
|
bool explosion = value[L"explosion"].as_bool();
|
||||||
bool immediate = value[L"immediate"].as_bool();
|
bool immediate = value[L"immediate"].as_bool();
|
||||||
unitsManager->deleteUnit(ID, explosion, immediate);
|
unitsManager->deleteUnit(ID, explosion, immediate);
|
||||||
|
Unit* unit = unitsManager->getUnit(ID);
|
||||||
|
log(username + " deleted unit " + unit->getName(), true);
|
||||||
}
|
}
|
||||||
else if (key.compare("refuel") == 0)
|
else if (key.compare("refuel") == 0)
|
||||||
{
|
{
|
||||||
@@ -356,6 +441,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::REFUEL);
|
unit->setState(State::REFUEL);
|
||||||
|
log(username + " tasked unit " + unit->getName() + " to refuel", true);
|
||||||
}
|
}
|
||||||
else if (key.compare("setAdvancedOptions") == 0)
|
else if (key.compare("setAdvancedOptions") == 0)
|
||||||
{
|
{
|
||||||
@@ -433,6 +519,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::BOMB_POINT);
|
unit->setState(State::BOMB_POINT);
|
||||||
unit->setTargetPosition(loc);
|
unit->setTargetPosition(loc);
|
||||||
|
log(username + " tasked unit " + unit->getName() + " to bomb a point", true);
|
||||||
}
|
}
|
||||||
else if (key.compare("carpetBomb") == 0)
|
else if (key.compare("carpetBomb") == 0)
|
||||||
{
|
{
|
||||||
@@ -444,6 +531,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::CARPET_BOMB);
|
unit->setState(State::CARPET_BOMB);
|
||||||
unit->setTargetPosition(loc);
|
unit->setTargetPosition(loc);
|
||||||
|
log(username + " tasked unit " + unit->getName() + " to perform carpet bombing", true);
|
||||||
}
|
}
|
||||||
else if (key.compare("bombBuilding") == 0)
|
else if (key.compare("bombBuilding") == 0)
|
||||||
{
|
{
|
||||||
@@ -466,6 +554,11 @@ void Scheduler::handleRequest(string key, json::value value)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::FIRE_AT_AREA);
|
unit->setState(State::FIRE_AT_AREA);
|
||||||
unit->setTargetPosition(loc);
|
unit->setTargetPosition(loc);
|
||||||
|
log(username + " tasked unit " + unit->getName() + " to fire at area", true);
|
||||||
|
}
|
||||||
|
else if (key.compare("setCommandModeOptions") == 0) {
|
||||||
|
setCommandModeOptions(value);
|
||||||
|
log(username + " updated the Command Mode Options", true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ void Server::handle_get(http_request request)
|
|||||||
if (path.size() > 0)
|
if (path.size() > 0)
|
||||||
{
|
{
|
||||||
string URI = to_string(path[0]);
|
string URI = to_string(path[0]);
|
||||||
|
/* Units data. This is the only binary format data transmitted, all others are transmitted as text json for simplicity */
|
||||||
if (URI.compare(UNITS_URI) == 0)
|
if (URI.compare(UNITS_URI) == 0)
|
||||||
{
|
{
|
||||||
unsigned long long updateTime = ms.count();
|
unsigned long long updateTime = ms.count();
|
||||||
@@ -103,39 +104,36 @@ void Server::handle_get(http_request request)
|
|||||||
response.set_body(concurrency::streams::bytestream::open_istream(ss.str()));
|
response.set_body(concurrency::streams::bytestream::open_istream(ss.str()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/* Logs data*/
|
||||||
if (URI.compare(LOGS_URI) == 0)
|
if (URI.compare(LOGS_URI) == 0)
|
||||||
{
|
{
|
||||||
auto logs = json::value::object();
|
auto logs = json::value::object();
|
||||||
getLogsJSON(logs, time);
|
getLogsJSON(logs, time);
|
||||||
answer[L"logs"] = logs;
|
answer[L"logs"] = logs;
|
||||||
}
|
}
|
||||||
|
/* Airbases data */
|
||||||
else if (URI.compare(AIRBASES_URI) == 0 && missionData.has_object_field(L"airbases"))
|
else if (URI.compare(AIRBASES_URI) == 0 && missionData.has_object_field(L"airbases"))
|
||||||
answer[L"airbases"] = missionData[L"airbases"];
|
answer[L"airbases"] = missionData[L"airbases"];
|
||||||
|
/* Bullseyes data */
|
||||||
else if (URI.compare(BULLSEYE_URI) == 0 && missionData.has_object_field(L"bullseyes"))
|
else if (URI.compare(BULLSEYE_URI) == 0 && missionData.has_object_field(L"bullseyes"))
|
||||||
answer[L"bullseyes"] = missionData[L"bullseyes"];
|
answer[L"bullseyes"] = missionData[L"bullseyes"];
|
||||||
|
/* Mission data */
|
||||||
else if (URI.compare(MISSION_URI) == 0 && missionData.has_object_field(L"mission")) {
|
else if (URI.compare(MISSION_URI) == 0 && missionData.has_object_field(L"mission")) {
|
||||||
answer[L"mission"] = missionData[L"mission"];
|
answer[L"mission"] = missionData[L"mission"];
|
||||||
answer[L"mission"][L"RTSOptions"] = json::value::object();
|
answer[L"mission"][L"commandModeOptions"] = scheduler->getCommandModeOptions();
|
||||||
|
|
||||||
|
/* The active mode is determined by the inserted password*/
|
||||||
if (password.compare(gameMasterPassword) == 0)
|
if (password.compare(gameMasterPassword) == 0)
|
||||||
answer[L"mission"][L"RTSOptions"][L"commandMode"] = json::value(L"Game master");
|
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Game master");
|
||||||
else if (password.compare(blueCommanderPassword) == 0)
|
else if (password.compare(blueCommanderPassword) == 0)
|
||||||
answer[L"mission"][L"RTSOptions"][L"commandMode"] = json::value(L"Blue commander");
|
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Blue commander");
|
||||||
else if (password.compare(redCommanderPassword) == 0)
|
else if (password.compare(redCommanderPassword) == 0)
|
||||||
answer[L"mission"][L"RTSOptions"][L"commandMode"] = json::value(L"Red commander");
|
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Red commander");
|
||||||
|
else
|
||||||
answer[L"mission"][L"RTSOptions"][L"restrictSpawns"] = json::value(scheduler->getRestrictSpawns());
|
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Observer");
|
||||||
answer[L"mission"][L"RTSOptions"][L"restrictToCoalition"] = json::value(scheduler->getRestrictToCoalition());
|
|
||||||
answer[L"mission"][L"RTSOptions"][L"setupTime"] = json::value(scheduler->getSetupTime());
|
|
||||||
answer[L"mission"][L"RTSOptions"][L"spawnPoints"] = json::value::object();
|
|
||||||
answer[L"mission"][L"RTSOptions"][L"spawnPoints"][L"blue"] = json::value(scheduler->getBlueSpawnPoints());
|
|
||||||
answer[L"mission"][L"RTSOptions"][L"spawnPoints"][L"red"] = json::value(scheduler->getRedSpawnPoints());
|
|
||||||
|
|
||||||
int idx = 0;
|
|
||||||
answer[L"mission"][L"RTSOptions"][L"eras"] = json::value::array();
|
|
||||||
for (string era : scheduler->getEras())
|
|
||||||
answer[L"mission"][L"RTSOptions"][L"eras"].as_array()[idx++] = json::value(to_wstring(era));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Common data */
|
||||||
answer[L"time"] = json::value::string(to_wstring(ms.count()));
|
answer[L"time"] = json::value::string(to_wstring(ms.count()));
|
||||||
answer[L"sessionHash"] = json::value::string(to_wstring(sessionHash));
|
answer[L"sessionHash"] = json::value::string(to_wstring(sessionHash));
|
||||||
answer[L"load"] = scheduler->getLoad();
|
answer[L"load"] = scheduler->getLoad();
|
||||||
@@ -199,9 +197,10 @@ void Server::handle_request(http_request request, function<void(json::value cons
|
|||||||
|
|
||||||
void Server::handle_put(http_request request)
|
void Server::handle_put(http_request request)
|
||||||
{
|
{
|
||||||
|
string username = extractUsername(request);
|
||||||
handle_request(
|
handle_request(
|
||||||
request,
|
request,
|
||||||
[](json::value const& jvalue, json::value& answer)
|
[username](json::value const& jvalue, json::value& answer)
|
||||||
{
|
{
|
||||||
/* Lock for thread safety */
|
/* Lock for thread safety */
|
||||||
lock_guard<mutex> guard(mutexLock);
|
lock_guard<mutex> guard(mutexLock);
|
||||||
@@ -210,9 +209,10 @@ void Server::handle_put(http_request request)
|
|||||||
{
|
{
|
||||||
auto key = e.first;
|
auto key = e.first;
|
||||||
auto value = e.second;
|
auto value = e.second;
|
||||||
|
|
||||||
std::exception_ptr eptr;
|
std::exception_ptr eptr;
|
||||||
try {
|
try {
|
||||||
scheduler->handleRequest(to_string(key), value);
|
scheduler->handleRequest(to_string(key), value, username);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
eptr = std::current_exception(); // capture
|
eptr = std::current_exception(); // capture
|
||||||
@@ -222,6 +222,30 @@ void Server::handle_put(http_request request)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string Server::extractUsername(http_request& request) {
|
||||||
|
if (request.headers().has(L"Authorization")) {
|
||||||
|
string authorization = to_string(request.headers().find(L"Authorization")->second);
|
||||||
|
string s = "Basic ";
|
||||||
|
string::size_type i = authorization.find(s);
|
||||||
|
|
||||||
|
if (i != std::string::npos)
|
||||||
|
authorization.erase(i, s.length());
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
|
||||||
|
string decoded = from_base64(authorization);
|
||||||
|
i = decoded.find(":");
|
||||||
|
if (i != string::npos && i <= decoded.length())
|
||||||
|
decoded.erase(i, decoded.length() - i);
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
string Server::extractPassword(http_request& request) {
|
string Server::extractPassword(http_request& request) {
|
||||||
if (request.headers().has(L"Authorization")) {
|
if (request.headers().has(L"Authorization")) {
|
||||||
string authorization = to_string(request.headers().find(L"Authorization")->second);
|
string authorization = to_string(request.headers().find(L"Authorization")->second);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
|
|
||||||
void DllExport log(const std::string& sMessage);
|
void DllExport log(const std::string& sMessage, bool addToJSON = false);
|
||||||
void DllExport log(const std::wstring& sMessage);
|
void DllExport log(const std::wstring& sMessage, bool addToJSON = false);
|
||||||
void DllExport getLogsJSON(json::value& json, unsigned long long time);
|
void DllExport getLogsJSON(json::value& json, unsigned long long time);
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
class Logger
|
class Logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void log(const string& sMessage);
|
void log(const string& sMessage, bool addToJSON);
|
||||||
void log(const wstring& sMessage);
|
void log(const wstring& sMessage, bool addToJSON);
|
||||||
void toJSON(json::value& json, unsigned long long time);
|
void toJSON(json::value& json, unsigned long long time);
|
||||||
|
|
||||||
static Logger* GetLogger();
|
static Logger* GetLogger();
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
#define LOGGER Logger::GetLogger()
|
#define LOGGER Logger::GetLogger()
|
||||||
|
|
||||||
void log(const string& message)
|
void log(const string& message, bool addToJSON)
|
||||||
{
|
{
|
||||||
LOGGER->log(message);
|
LOGGER->log(message, addToJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(const wstring& message)
|
void log(const wstring& message, bool addToJSON)
|
||||||
{
|
{
|
||||||
LOGGER->log(message);
|
LOGGER->log(message, addToJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getLogsJSON(json::value& json, unsigned long long time)
|
void getLogsJSON(json::value& json, unsigned long long time)
|
||||||
|
|||||||
@@ -47,24 +47,26 @@ void Logger::toJSON(json::value& json, unsigned long long time)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::log(const string& message)
|
void Logger::log(const string& message, bool addToJSON)
|
||||||
{
|
{
|
||||||
lock_guard<mutex> guard(mutexLock);
|
lock_guard<mutex> guard(mutexLock);
|
||||||
Open();
|
Open();
|
||||||
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
||||||
m_Logfile << CurrentDateTime() << ":\t";
|
m_Logfile << CurrentDateTime() << ":\t";
|
||||||
m_Logfile << message << "\n";
|
m_Logfile << message << "\n";
|
||||||
m_logs[static_cast<unsigned long long>(ms.count())] = CurrentDateTime() + ": " + message;
|
if (addToJSON)
|
||||||
|
m_logs[static_cast<unsigned long long>(ms.count())] = message;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::log(const wstring& message)
|
void Logger::log(const wstring& message, bool addToJSON)
|
||||||
{
|
{
|
||||||
lock_guard<mutex> guard(mutexLock);
|
lock_guard<mutex> guard(mutexLock);
|
||||||
Open();
|
Open();
|
||||||
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
||||||
m_Logfile << CurrentDateTime() << ":\t";
|
m_Logfile << CurrentDateTime() << ":\t";
|
||||||
m_Logfile << to_string(message) << "\n";
|
m_Logfile << to_string(message) << "\n";
|
||||||
m_logs[static_cast<unsigned long long>(ms.count())] = CurrentDateTime() + ": " + to_string(message);
|
if (addToJSON)
|
||||||
|
m_logs[static_cast<unsigned long long>(ms.count())] = to_string(message);
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user