From 81871b596bfbfd3f2f2b1bd568baf82c1a12a0c2 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Sun, 23 Jul 2023 22:30:25 +0200 Subject: [PATCH] Completed backend for advanced RTS functions --- client/demo.js | 8 +- client/public/stylesheets/layout/layout.css | 2 +- client/public/stylesheets/olympus.css | 22 +-- client/src/@types/dom.d.ts | 2 +- client/src/@types/server.d.ts | 4 +- client/src/controls/airbasecontextmenu.ts | 6 +- .../src/controls/coalitionareacontextmenu.ts | 6 +- client/src/controls/mapcontextmenu.ts | 14 +- client/src/index.ts | 10 +- client/src/map/coalitionarea.ts | 6 +- client/src/map/map.ts | 2 +- .../{missionhandler => mission}/airbase.ts | 0 .../{missionhandler => mission}/bullseye.ts | 0 .../missionhandler.ts | 134 ++++++++++-------- client/src/panels/logpanel.ts | 10 +- client/src/server/server.ts | 8 +- client/src/units/aircraftdatabase.ts | 4 +- client/src/units/groundunitdatabase.ts | 4 +- client/src/units/helicopterdatabase.ts | 4 +- client/src/units/navyunitdatabase.ts | 4 +- client/src/units/unit.ts | 8 +- client/src/units/unitdatabase.ts | 8 +- client/src/units/unitsmanager.ts | 41 ++---- client/views/index.ejs | 2 +- client/views/other/dialogs.ejs | 8 +- client/views/toolbars/commandmode.ejs | 6 + client/views/toolbars/rts.ejs | 6 - src/core/include/scheduler.h | 9 +- src/core/include/server.h | 1 + src/core/src/core.cpp | 8 +- src/core/src/scheduler.cpp | 117 +++++++++++++-- src/core/src/server.cpp | 64 ++++++--- src/logger/include/interface.h | 4 +- src/logger/include/logger.h | 4 +- src/logger/src/interface.cpp | 8 +- src/logger/src/logger.cpp | 10 +- 36 files changed, 338 insertions(+), 216 deletions(-) rename client/src/{missionhandler => mission}/airbase.ts (100%) rename client/src/{missionhandler => mission}/bullseye.ts (100%) rename client/src/{missionhandler => mission}/missionhandler.ts (50%) create mode 100644 client/views/toolbars/commandmode.ejs delete mode 100644 client/views/toolbars/rts.ejs diff --git a/client/demo.js b/client/demo.js index 0b47a088..72b5a93c 100644 --- a/client/demo.js +++ b/client/demo.js @@ -390,7 +390,7 @@ class DemoDataGenerator { startTime: 0 } - ret.mission.RTSOptions = { + ret.mission.commandModeOptions = { restrictSpawns: true, restrictToCoalition: true, setupTime: 0, @@ -406,13 +406,13 @@ class DemoDataGenerator { var username = atob(auth.replace("Basic ", "")).split(":")[0]; switch (username) { case "admin": - ret.mission.RTSOptions.commandMode = "Game master"; + ret.mission.commandModeOptions.commandMode = "Game master"; break case "blue": - ret.mission.RTSOptions.commandMode = "Blue commander"; + ret.mission.commandModeOptions.commandMode = "Blue commander"; break; case "red": - ret.mission.RTSOptions.commandMode = "Red commander"; + ret.mission.commandModeOptions.commandMode = "Red commander"; break; } } diff --git a/client/public/stylesheets/layout/layout.css b/client/public/stylesheets/layout/layout.css index 58f34e74..b21074c9 100644 --- a/client/public/stylesheets/layout/layout.css +++ b/client/public/stylesheets/layout/layout.css @@ -20,7 +20,7 @@ display: flex; } -#rts-toolbar { +#command-mode-toolbar { align-items: center; display: flex; } diff --git a/client/public/stylesheets/olympus.css b/client/public/stylesheets/olympus.css index 1a1bcf21..d8e33fba 100644 --- a/client/public/stylesheets/olympus.css +++ b/client/public/stylesheets/olympus.css @@ -917,12 +917,12 @@ nav.ol-panel> :last-child { padding-right: 20px; } -#rts-phase::before { +#command-mode-phase::before { content: "Time to start"; font-size: 14px; } -#rts-phase.setup-phase::after { +#command-mode-phase.setup-phase::after { color: orange; border: 1px solid orange; border-radius: 999px; @@ -933,7 +933,7 @@ nav.ol-panel> :last-child { font-size: 14px; } -#rts-phase.game-commenced { +#command-mode-phase.game-commenced { background-color: var(--background-grey); color: lightgreen; border: 1px solid lightgreen; @@ -944,31 +944,31 @@ nav.ol-panel> :last-child { align-items: center; } -#rts-phase.game-commenced::before { +#command-mode-phase.game-commenced::before { content: "Game commenced"; font-weight: bold; } -#rts-phase.game-commenced::after { +#command-mode-phase.game-commenced::after { content: "Spawn restrictions are being enforced"; font-size: 10px; } -#rts-toolbar .ol-button { +#command-mode-toolbar .ol-button { border: 1px solid white; } -#rts-toolbar .ol-button>svg { +#command-mode-toolbar .ol-button>svg { width: 20px; height: 20px; fill: white; } -#rts-settings-dialog { +#command-mode-settings-dialog { width: 400px; } -#rts-settings-dialog>.ol-dialog-content { +#command-mode-settings-dialog>.ol-dialog-content { display: flex; flex-direction: column; flex-wrap: nowrap; @@ -978,11 +978,11 @@ nav.ol-panel> :last-child { width: 100%; } -#rts-settings-dialog>.ol-dialog-content .ol-group { +#command-mode-settings-dialog>.ol-dialog-content .ol-group { justify-content: space-between; } -#rts-settings-dialog h4 { +#command-mode-settings-dialog h4 { white-space: nowrap; width: fit-content; } diff --git a/client/src/@types/dom.d.ts b/client/src/@types/dom.d.ts index 212ebe96..a3712343 100644 --- a/client/src/@types/dom.d.ts +++ b/client/src/@types/dom.d.ts @@ -19,7 +19,7 @@ interface CustomEventMap { "mapStateChanged": CustomEvent, "mapContextMenu": CustomEvent<>, "mapVisibilityOptionsChanged": CustomEvent<>, - "RTSOptionsChanged": CustomEvent<>, + "commandModeOptionsChanged": CustomEvent<>, "contactsUpdated": CustomEvent, } diff --git a/client/src/@types/server.d.ts b/client/src/@types/server.d.ts index 3b1d3dfb..d023d211 100644 --- a/client/src/@types/server.d.ts +++ b/client/src/@types/server.d.ts @@ -14,13 +14,13 @@ interface MissionData { mission: { theatre: string, dateAndTime: DateAndTime; - RTSOptions: RTSOptions; + commandModeOptions: CommandModeOptions; } time: number; sessionHash: string; } -interface RTSOptions { +interface CommandModeOptions { commandMode: string; restrictSpawns: boolean; restrictToCoalition: boolean; diff --git a/client/src/controls/airbasecontextmenu.ts b/client/src/controls/airbasecontextmenu.ts index 06f74c65..beb6bd14 100644 --- a/client/src/controls/airbasecontextmenu.ts +++ b/client/src/controls/airbasecontextmenu.ts @@ -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 { Airbase } from "../missionhandler/airbase"; +import { Airbase } from "../mission/airbase"; import { ContextMenu } from "./contextmenu"; export class AirbaseContextMenu extends ContextMenu { @@ -26,7 +26,7 @@ export class AirbaseContextMenu extends ContextMenu { this.setParkings(airbase.getParkings()); this.setCoalition(airbase.getCoalition()); 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) { diff --git a/client/src/controls/coalitionareacontextmenu.ts b/client/src/controls/coalitionareacontextmenu.ts index ff474440..f7f36585 100644 --- a/client/src/controls/coalitionareacontextmenu.ts +++ b/client/src/controls/coalitionareacontextmenu.ts @@ -1,5 +1,5 @@ import { LatLng } from "leaflet"; -import { getMap, getUnitsManager } from ".."; +import { getMap, getMissionHandler, getUnitsManager } from ".."; import { GAME_MASTER, IADSTypes } from "../constants/constants"; import { CoalitionArea } from "../map/coalitionarea"; import { ContextMenu } from "./contextmenu"; @@ -81,7 +81,7 @@ export class CoalitionAreaContextMenu extends ContextMenu { return createCheckboxOption(range, `Add ${range} units to the IADS`); })); - if (getUnitsManager().getCommandMode() !== GAME_MASTER) + if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER) this.#coalitionSwitch.hide() } @@ -114,7 +114,7 @@ export class CoalitionAreaContextMenu extends ContextMenu { } #onSwitchClick(value: boolean) { - if (getUnitsManager().getCommandMode() == GAME_MASTER) { + if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER) { this.getCoalitionArea()?.setCoalition(value ? "red" : "blue"); this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", this.getCoalitionArea()?.getCoalition()) diff --git a/client/src/controls/mapcontextmenu.ts b/client/src/controls/mapcontextmenu.ts index cbf7fe50..9a362d42 100644 --- a/client/src/controls/mapcontextmenu.ts +++ b/client/src/controls/mapcontextmenu.ts @@ -169,7 +169,7 @@ export class MapContextMenu extends ContextMenu { } }); - document.addEventListener("RTSOptionsChanged", (e: any) => { + document.addEventListener("commandModeOptionsChanged", (e: any) => { this.#refreshOptions(); }); @@ -193,7 +193,7 @@ export class MapContextMenu extends ContextMenu { else this.#coalitionSwitch.setValue(undefined); - if (getUnitsManager().getCommandMode() !== GAME_MASTER) + if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER) this.#coalitionSwitch.hide() this.getContainer()?.querySelector("#coalition-area-button")?.classList.toggle("hide", true); @@ -562,26 +562,26 @@ export class MapContextMenu extends ContextMenu { } #computeSpawnPoints() { - if (getMissionHandler() && getUnitsManager().getCommandMode() !== GAME_MASTER){ + if (getMissionHandler() && getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER){ var aircraftCount = parseInt(this.#aircraftCountDropdown.getValue()); var aircraftSpawnPoints = aircraftCount * aircraftDatabase.getSpawnPointsByLabel(this.#aircraftLabelDropdown.getValue()); (this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${aircraftSpawnPoints}`; - (this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = aircraftSpawnPoints > getMissionHandler().getAvailableSpawnPoints(); + (this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = aircraftSpawnPoints >= getMissionHandler().getAvailableSpawnPoints(); var helicopterCount = parseInt(this.#helicopterCountDropdown.getValue()); var helicopterSpawnPoints = helicopterCount * helicopterDatabase.getSpawnPointsByLabel(this.#helicopterLabelDropdown.getValue()); (this.getContainer()?.querySelector("#helicopter-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${helicopterSpawnPoints}`; - (this.getContainer()?.querySelector("#helicopter-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = helicopterSpawnPoints > getMissionHandler().getAvailableSpawnPoints(); + (this.getContainer()?.querySelector("#helicopter-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = helicopterSpawnPoints >= getMissionHandler().getAvailableSpawnPoints(); var groundUnitCount = parseInt(this.#groundUnitCountDropdown.getValue()); var groundUnitSpawnPoints = groundUnitCount * groundUnitDatabase.getSpawnPointsByLabel(this.#groundUnitLabelDropdown.getValue()); (this.getContainer()?.querySelector("#groundunit-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${groundUnitSpawnPoints}`; - (this.getContainer()?.querySelector("#groundunit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = groundUnitSpawnPoints > getMissionHandler().getAvailableSpawnPoints(); + (this.getContainer()?.querySelector("#groundunit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = groundUnitSpawnPoints >= getMissionHandler().getAvailableSpawnPoints(); var navyUnitCount = parseInt(this.#navyUnitCountDropdown.getValue()); var navyUnitSpawnPoints = navyUnitCount * navyUnitDatabase.getSpawnPointsByLabel(this.#navyUnitLabelDropdown.getValue()); (this.getContainer()?.querySelector("#navyunit-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${navyUnitSpawnPoints}`; - (this.getContainer()?.querySelector("#navyunit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = navyUnitSpawnPoints > getMissionHandler().getAvailableSpawnPoints(); + (this.getContainer()?.querySelector("#navyunit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = navyUnitSpawnPoints >= getMissionHandler().getAvailableSpawnPoints(); } } } \ No newline at end of file diff --git a/client/src/index.ts b/client/src/index.ts index 4f528884..1a935ff9 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -2,7 +2,7 @@ import { Map } from "./map/map" import { UnitsManager } from "./units/unitsmanager"; import { UnitInfoPanel } from "./panels/unitinfopanel"; import { ConnectionStatusPanel } from "./panels/connectionstatuspanel"; -import { MissionHandler } from "./missionhandler/missionhandler"; +import { MissionHandler } from "./mission/missionhandler"; import { UnitControlPanel } from "./panels/unitcontrolpanel"; import { MouseInfoPanel } from "./panels/mouseinfopanel"; import { AIC } from "./aic/aic"; @@ -255,17 +255,17 @@ export function getHotgroupPanel() { } export function setActiveCoalition(newActiveCoalition: string) { - if (getUnitsManager().getCommandMode() == GAME_MASTER) + if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER) activeCoalition = newActiveCoalition; } export function getActiveCoalition() { - if (getUnitsManager().getCommandMode() == GAME_MASTER) + if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER) return activeCoalition; else { - if (getUnitsManager().getCommandMode() == BLUE_COMMANDER) + if (getMissionHandler().getCommandModeOptions().commandMode == BLUE_COMMANDER) return "blue"; - else if (getUnitsManager().getCommandMode() == RED_COMMANDER) + else if (getMissionHandler().getCommandModeOptions().commandMode == RED_COMMANDER) return "red"; else return "neutral"; diff --git a/client/src/map/coalitionarea.ts b/client/src/map/coalitionarea.ts index 102413ad..fe98daa9 100644 --- a/client/src/map/coalitionarea.ts +++ b/client/src/map/coalitionarea.ts @@ -1,5 +1,5 @@ import { DomUtil, LatLng, LatLngExpression, Map, Point, Polygon, PolylineOptions } from "leaflet"; -import { getMap, getUnitsManager } from ".."; +import { getMap, getMissionHandler, getUnitsManager } from ".."; import { CoalitionAreaHandle } from "./coalitionareahandle"; import { CoalitionAreaMiddleHandle } from "./coalitionareamiddlehandle"; import { BLUE_COMMANDER, RED_COMMANDER } from "../constants/constants"; @@ -23,8 +23,8 @@ export class CoalitionArea extends Polygon { this.#setColors(); this.#registerCallbacks(); - if ([BLUE_COMMANDER, RED_COMMANDER].includes(getUnitsManager().getCommandMode())) - this.setCoalition(getUnitsManager().getCommandedCoalition()); + if ([BLUE_COMMANDER, RED_COMMANDER].includes(getMissionHandler().getCommandModeOptions().commandMode)) + this.setCoalition(getMissionHandler().getCommandedCoalition()); } setCoalition(coalition: string) { diff --git a/client/src/map/map.ts b/client/src/map/map.ts index 98bf58cb..da49ea3d 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -5,7 +5,7 @@ import { MapContextMenu } from "../controls/mapcontextmenu"; import { UnitContextMenu } from "../controls/unitcontextmenu"; import { AirbaseContextMenu } from "../controls/airbasecontextmenu"; import { Dropdown } from "../controls/dropdown"; -import { Airbase } from "../missionhandler/airbase"; +import { Airbase } from "../mission/airbase"; import { Unit } from "../units/unit"; import { bearing, createCheckboxOption } from "../other/utils"; import { DestinationPreviewMarker } from "./destinationpreviewmarker"; diff --git a/client/src/missionhandler/airbase.ts b/client/src/mission/airbase.ts similarity index 100% rename from client/src/missionhandler/airbase.ts rename to client/src/mission/airbase.ts diff --git a/client/src/missionhandler/bullseye.ts b/client/src/mission/bullseye.ts similarity index 100% rename from client/src/missionhandler/bullseye.ts rename to client/src/mission/bullseye.ts diff --git a/client/src/missionhandler/missionhandler.ts b/client/src/mission/missionhandler.ts similarity index 50% rename from client/src/missionhandler/missionhandler.ts rename to client/src/mission/missionhandler.ts index 1ed4bcb6..8a6c515d 100644 --- a/client/src/missionhandler/missionhandler.ts +++ b/client/src/mission/missionhandler.ts @@ -3,7 +3,7 @@ import { getInfoPopup, getMap, getUnitsManager } from ".."; import { Airbase } from "./airbase"; import { Bullseye } from "./bullseye"; 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 { groundUnitDatabase } from "../units/groundunitdatabase"; import { createCheckboxOption, getCheckboxOptions } from "../other/utils"; @@ -16,20 +16,20 @@ export class MissionHandler { #airbases: { [name: string]: Airbase } = {}; #theatre: string = ""; #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; #spentSpawnPoint: number = 0; - #RTSSettingsDialog: HTMLElement; - #rtsErasDropdown: Dropdown; + #commandModeDialog: HTMLElement; + #commandModeErasDropdown: Dropdown; constructor() { - document.addEventListener("showRTSSettingsDialog", () => this.showRTSSettingsDialog()); - document.addEventListener("applyRTSOptions", () => this.#applyRTSOptions()); + document.addEventListener("showCommandModeDialog", () => this.showCommandModeDialog()); + document.addEventListener("applycommandModeOptions", () => this.#applycommandModeOptions()); - /* RTS settings dialog */ - this.#RTSSettingsDialog = document.querySelector("#rts-settings-dialog"); + /* command-mode settings dialog */ + this.#commandModeDialog = document.querySelector("#command-mode-settings-dialog"); - this.#rtsErasDropdown = new Dropdown("rts-era-options", () => {}); + this.#commandModeErasDropdown = new Dropdown("command-mode-era-options", () => {}); } updateBullseyes(data: BullseyesData) { @@ -65,27 +65,28 @@ export class MissionHandler { updateMission(data: MissionData) { if (data.mission) { + /* Set the mission theatre */ if (data.mission.theatre != this.#theatre) { this.#theatre = data.mission.theatre; getMap().setTheatre(this.#theatre); getInfoPopup().setText("Map set to " + this.#theatre); } + /* Set the date and time data */ this.#dateAndTime = data.mission.dateAndTime; - this.#setRTSOptions(data.mission.RTSOptions); - getUnitsManager().setCommandMode(this.#RTSOptions.commandMode); - - this.#remainingSetupTime = this.#RTSOptions.setupTime - this.getDateAndTime().elapsedTime; - var RTSPhaseEl = document.querySelector("#rts-phase") as HTMLElement; - if (RTSPhaseEl) { + /* Set the command mode options */ + this.#setcommandModeOptions(data.mission.commandModeOptions); + this.#remainingSetupTime = this.getCommandModeOptions().setupTime - this.getDateAndTime().elapsedTime; + var commandModePhaseEl = document.querySelector("#command-mode-phase") as HTMLElement; + if (commandModePhaseEl) { if (this.#remainingSetupTime > 0) { 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); - RTSPhaseEl.classList.toggle("game-commenced", this.#remainingSetupTime <= 0); + commandModePhaseEl.classList.toggle("setup-phase", this.#remainingSetupTime > 0); + commandModePhaseEl.classList.toggle("game-commenced", this.#remainingSetupTime <= 0); } } } @@ -98,8 +99,8 @@ export class MissionHandler { return this.#airbases; } - getRTSOptions() { - return this.#RTSOptions; + getCommandModeOptions() { + return this.#commandModeOptions; } getDateAndTime() { @@ -111,16 +112,25 @@ export class MissionHandler { } getAvailableSpawnPoints() { - if (getUnitsManager().getCommandMode() === GAME_MASTER) + if (this.getCommandModeOptions().commandMode === GAME_MASTER) return Infinity; - else if (getUnitsManager().getCommandMode() === BLUE_COMMANDER) - return this.getRTSOptions().spawnPoints.blue - this.#spentSpawnPoint; - else if (getUnitsManager().getCommandMode() === RED_COMMANDER) - return this.getRTSOptions().spawnPoints.red - this.#spentSpawnPoint; + else if (this.getCommandModeOptions().commandMode === BLUE_COMMANDER) + return this.getCommandModeOptions().spawnPoints.blue - this.#spentSpawnPoint; + else if (this.getCommandModeOptions().commandMode === RED_COMMANDER) + return this.getCommandModeOptions().spawnPoints.red - this.#spentSpawnPoint; else return 0; } + getCommandedCoalition() { + if (this.getCommandModeOptions().commandMode === BLUE_COMMANDER) + return "blue"; + else if (this.getCommandModeOptions().commandMode === RED_COMMANDER) + return "red"; + else + return "all"; + } + refreshSpawnPoints() { var spawnPointsEl = document.querySelector("#spawn-points"); if (spawnPointsEl) { @@ -133,68 +143,68 @@ export class MissionHandler { this.refreshSpawnPoints(); } - showRTSSettingsDialog() { + showCommandModeDialog() { /* Create the checkboxes to select the unit eras */ 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(); - this.#rtsErasDropdown.setOptionsElements(eras.map((era: string) => { - return createCheckboxOption(era, `Enable ${era} units spawns`, this.#RTSOptions.eras.includes(era)); + this.#commandModeErasDropdown.setOptionsElements(eras.map((era: string) => { + 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 restrictToCoalitionCheckbox = this.#RTSSettingsDialog.querySelector("#restrict-to-coalition")?.querySelector("input") as HTMLInputElement; - const blueSpawnPointsInput = this.#RTSSettingsDialog.querySelector("#blue-spawn-points")?.querySelector("input") as HTMLInputElement; - const redSpawnPointsInput = this.#RTSSettingsDialog.querySelector("#red-spawn-points")?.querySelector("input") as HTMLInputElement; - const setupTimeInput = this.#RTSSettingsDialog.querySelector("#setup-time")?.querySelector("input") as HTMLInputElement; + const restrictSpawnsCheckbox = this.#commandModeDialog.querySelector("#restrict-spawns")?.querySelector("input") as HTMLInputElement; + const restrictToCoalitionCheckbox = this.#commandModeDialog.querySelector("#restrict-to-coalition")?.querySelector("input") as HTMLInputElement; + const blueSpawnPointsInput = this.#commandModeDialog.querySelector("#blue-spawn-points")?.querySelector("input") as HTMLInputElement; + const redSpawnPointsInput = this.#commandModeDialog.querySelector("#red-spawn-points")?.querySelector("input") as HTMLInputElement; + const setupTimeInput = this.#commandModeDialog.querySelector("#setup-time")?.querySelector("input") as HTMLInputElement; - restrictSpawnsCheckbox.checked = this.#RTSOptions.restrictSpawns; - restrictToCoalitionCheckbox.checked = this.#RTSOptions.restrictToCoalition; - blueSpawnPointsInput.value = String(this.#RTSOptions.spawnPoints.blue); - redSpawnPointsInput.value = String(this.#RTSOptions.spawnPoints.red); - setupTimeInput.value = String(Math.floor(this.#RTSOptions.setupTime / 60.0)); + restrictSpawnsCheckbox.checked = this.getCommandModeOptions().restrictSpawns; + restrictToCoalitionCheckbox.checked = this.getCommandModeOptions().restrictToCoalition; + blueSpawnPointsInput.value = String(this.getCommandModeOptions().spawnPoints.blue); + redSpawnPointsInput.value = String(this.getCommandModeOptions().spawnPoints.red); + setupTimeInput.value = String(Math.floor(this.getCommandModeOptions().setupTime / 60.0)); } - #applyRTSOptions() { - this.#RTSSettingsDialog.classList.add("hide"); + #applycommandModeOptions() { + this.#commandModeDialog.classList.add("hide"); - const restrictSpawnsCheckbox = this.#RTSSettingsDialog.querySelector("#restrict-spawns")?.querySelector("input") as HTMLInputElement; - const restrictToCoalitionCheckbox = this.#RTSSettingsDialog.querySelector("#restrict-to-coalition")?.querySelector("input") as HTMLInputElement; - const blueSpawnPointsInput = this.#RTSSettingsDialog.querySelector("#blue-spawn-points")?.querySelector("input") as HTMLInputElement; - const redSpawnPointsInput = this.#RTSSettingsDialog.querySelector("#red-spawn-points")?.querySelector("input") as HTMLInputElement; - const setupTimeInput = this.#RTSSettingsDialog.querySelector("#setup-time")?.querySelector("input") as HTMLInputElement; + const restrictSpawnsCheckbox = this.#commandModeDialog.querySelector("#restrict-spawns")?.querySelector("input") as HTMLInputElement; + const restrictToCoalitionCheckbox = this.#commandModeDialog.querySelector("#restrict-to-coalition")?.querySelector("input") as HTMLInputElement; + const blueSpawnPointsInput = this.#commandModeDialog.querySelector("#blue-spawn-points")?.querySelector("input") as HTMLInputElement; + const redSpawnPointsInput = this.#commandModeDialog.querySelector("#red-spawn-points")?.querySelector("input") as HTMLInputElement; + const setupTimeInput = this.#commandModeDialog.querySelector("#setup-time")?.querySelector("input") as HTMLInputElement; 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)}); - 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) { - var RTSOptionsChanged = (!RTSOptions.eras.every((value: string, idx: number) => {return value === this.#RTSOptions.eras[idx]}) || - RTSOptions.spawnPoints.red !== this.#RTSOptions.spawnPoints.red || - RTSOptions.spawnPoints.blue !== this.#RTSOptions.spawnPoints.blue || - RTSOptions.restrictSpawns !== this.#RTSOptions.restrictSpawns || - RTSOptions.restrictToCoalition !== this.#RTSOptions.restrictToCoalition); + #setcommandModeOptions(commandModeOptions: CommandModeOptions) { + var commandModeOptionsChanged = (!commandModeOptions.eras.every((value: string, idx: number) => {return value === this.getCommandModeOptions().eras[idx]}) || + commandModeOptions.spawnPoints.red !== this.getCommandModeOptions().spawnPoints.red || + commandModeOptions.spawnPoints.blue !== this.getCommandModeOptions().spawnPoints.blue || + commandModeOptions.restrictSpawns !== this.getCommandModeOptions().restrictSpawns || + commandModeOptions.restrictToCoalition !== this.getCommandModeOptions().restrictToCoalition); - this.#RTSOptions = RTSOptions; + this.#commandModeOptions = commandModeOptions; this.setSpentSpawnPoints(0); this.refreshSpawnPoints(); - if (RTSOptionsChanged) { - document.dispatchEvent(new CustomEvent("RTSOptionsChanged", { detail: this })); + if (commandModeOptionsChanged) { + 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"); if (el) { - el.dataset.mode = RTSOptions.commandMode; - el.textContent = RTSOptions.commandMode.toUpperCase(); + el.dataset.mode = commandModeOptions.commandMode; + el.textContent = commandModeOptions.commandMode.toUpperCase(); } } - document.querySelector("#spawn-points-container")?.classList.toggle("hide", getUnitsManager().getCommandMode() === GAME_MASTER); - document.querySelector("#rts-settings-button")?.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("#command-mode-settings-button")?.classList.toggle("hide", this.getCommandModeOptions().commandMode !== GAME_MASTER); } #onAirbaseClick(e: any) { diff --git a/client/src/panels/logpanel.ts b/client/src/panels/logpanel.ts index 80a5b86c..efa398c6 100644 --- a/client/src/panels/logpanel.ts +++ b/client/src/panels/logpanel.ts @@ -4,6 +4,7 @@ export class LogPanel extends Panel { #open: boolean = false; #queuedMessages: number = 0; #scrolledDown: boolean = true; + #logs: {[key: string]: string} = {}; constructor(ID: string) { super(ID); @@ -26,8 +27,13 @@ export class LogPanel extends Panel { } } - appendLogs(logs: string[]) { - logs.forEach((log: string) => this.appendLog(log)); + appendLogs(logs: {[key: string]: string}) { + Object.keys(logs).forEach((key: string) => { + if (!(key in this.#logs)) { + this.#logs[key] = logs[key]; + this.appendLog(logs[key]); + } + }); } appendLog(log: string) { diff --git a/client/src/server/server.ts b/client/src/server/server.ts index 1115cf7e..afd4193c 100644 --- a/client/src/server/server.ts +++ b/client/src/server/server.ts @@ -320,7 +320,7 @@ export function setAdvacedOptions(ID: number, isTanker: boolean, isAWACS: boolea 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 = { "restrictSpawns": restrictSpawns, "restrictToCoalition": restrictToCoalition, @@ -329,7 +329,7 @@ export function setRTSOptions(restrictSpawns: boolean, restrictToCoalition: bool "setupTime": setupTime }; - var data = { "setRTSOptions": command }; + var data = { "setCommandModeOptions": command }; POST(data, () => { }); } @@ -351,7 +351,7 @@ export function startUpdate() { return data.time; }); getLogs((data: any) => { - getLogPanel().appendLogs(Object.values(data.logs)) + getLogPanel().appendLogs(data.logs) return data.time; }); getUnits((buffer: ArrayBuffer) => {return getUnitsManager()?.update(buffer), true /* Does a full refresh */}); @@ -389,7 +389,7 @@ export function requestRefresh() { return data.time; }); getLogs((data: any) => { - getLogPanel().appendLogs(Object.values(data.logs)) + getLogPanel().appendLogs(data.logs) return data.time; }); diff --git a/client/src/units/aircraftdatabase.ts b/client/src/units/aircraftdatabase.ts index 9d1fa206..049e64c3 100644 --- a/client/src/units/aircraftdatabase.ts +++ b/client/src/units/aircraftdatabase.ts @@ -1,4 +1,4 @@ -import { getUnitsManager } from ".."; +import { getMissionHandler } from ".."; import { GAME_MASTER } from "../constants/constants"; import { UnitDatabase } from "./unitdatabase" @@ -3982,7 +3982,7 @@ export class AircraftDatabase extends UnitDatabase { } getSpawnPointsByName(name: string) { - if (getUnitsManager().getCommandMode() == GAME_MASTER) + if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns) return 0; const blueprint = this.getByName(name); diff --git a/client/src/units/groundunitdatabase.ts b/client/src/units/groundunitdatabase.ts index 014d80c6..ea0baf02 100644 --- a/client/src/units/groundunitdatabase.ts +++ b/client/src/units/groundunitdatabase.ts @@ -1,4 +1,4 @@ -import { getUnitsManager } from ".."; +import { getMissionHandler} from ".."; import { GAME_MASTER } from "../constants/constants"; import { UnitDatabase } from "./unitdatabase" @@ -1463,7 +1463,7 @@ export class GroundUnitDatabase extends UnitDatabase { } getSpawnPointsByName(name: string) { - if (getUnitsManager().getCommandMode() == GAME_MASTER) + if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns) return 0; const blueprint = this.getByName(name); diff --git a/client/src/units/helicopterdatabase.ts b/client/src/units/helicopterdatabase.ts index 7ef89a98..18d7a792 100644 --- a/client/src/units/helicopterdatabase.ts +++ b/client/src/units/helicopterdatabase.ts @@ -1,4 +1,4 @@ -import { getUnitsManager } from ".."; +import { getMissionHandler } from ".."; import { GAME_MASTER } from "../constants/constants"; import { UnitDatabase } from "./unitdatabase" @@ -595,7 +595,7 @@ export class HelicopterDatabase extends UnitDatabase { } getSpawnPointsByName(name: string) { - if (getUnitsManager().getCommandMode() == GAME_MASTER) + if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns) return 0; const blueprint = this.getByName(name); diff --git a/client/src/units/navyunitdatabase.ts b/client/src/units/navyunitdatabase.ts index 023787fe..e4c72d1f 100644 --- a/client/src/units/navyunitdatabase.ts +++ b/client/src/units/navyunitdatabase.ts @@ -1,4 +1,4 @@ -import { getUnitsManager } from ".."; +import { getMissionHandler } from ".."; import { GAME_MASTER } from "../constants/constants"; import { UnitDatabase } from "./unitdatabase" @@ -461,7 +461,7 @@ export class NavyUnitDatabase extends UnitDatabase { } getSpawnPointsByName(name: string) { - if (getUnitsManager().getCommandMode() == GAME_MASTER) + if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns) return 0; const blueprint = this.getByName(name); diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index ae07ae0a..6a77c196 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -1,5 +1,5 @@ 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 { 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'; @@ -336,7 +336,7 @@ export class Unit extends CustomMarker { } this.getElement()?.querySelector(`.unit`)?.toggleAttribute("data-is-selected", selected); - if (getMap().getZoom() < 13) { + if (this.getCategory() === "GroundUnit" && getMap().getZoom() < 13) { if (this.#isLeader) this.getGroupMembers().forEach((unit: Unit) => unit.setSelected(selected)); else @@ -384,7 +384,7 @@ export class Unit extends CustomMarker { } belongsToCommandedCoalition() { - if (getUnitsManager().getCommandMode() !== GAME_MASTER && getUnitsManager().getCommandedCoalition() !== this.#coalition) + if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER && getMissionHandler().getCommandedCoalition() !== this.#coalition) return false; return true; } @@ -1019,7 +1019,7 @@ export class Unit extends CustomMarker { } else if (this.#targetID != 0 && getMap().getVisibilityOptions()[SHOW_UNIT_TARGETS]) { 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()); } } diff --git a/client/src/units/unitdatabase.ts b/client/src/units/unitdatabase.ts index a273dffa..7f8e61fe 100644 --- a/client/src/units/unitdatabase.ts +++ b/client/src/units/unitdatabase.ts @@ -30,15 +30,15 @@ export class UnitDatabase { } getBlueprints() { - if (getUnitsManager().getCommandMode() == GAME_MASTER || !getMissionHandler().getRTSOptions().restrictSpawns) + if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || !getMissionHandler().getCommandModeOptions().restrictSpawns) return this.blueprints; else { var filteredBlueprints: { [key: string]: UnitBlueprint } = {}; for (let unit in this.blueprints) { const blueprint = this.blueprints[unit]; - if (this.getSpawnPointsByName(blueprint.name) < getMissionHandler().getAvailableSpawnPoints() && - getMissionHandler().getRTSOptions().eras.includes(blueprint.era) && - (!getMissionHandler().getRTSOptions().restrictToCoalition || blueprint.coalition === getUnitsManager().getCommandedCoalition())) { + if (this.getSpawnPointsByName(blueprint.name) <= getMissionHandler().getAvailableSpawnPoints() && + getMissionHandler().getCommandModeOptions().eras.includes(blueprint.era) && + (!getMissionHandler().getCommandModeOptions().restrictToCoalition || blueprint.coalition === getMissionHandler().getCommandedCoalition())) { filteredBlueprints[unit] = blueprint; } } diff --git a/client/src/units/unitsmanager.ts b/client/src/units/unitsmanager.ts index 603f1e47..43650697 100644 --- a/client/src/units/unitsmanager.ts +++ b/client/src/units/unitsmanager.ts @@ -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 { CoalitionArea } from "../map/coalitionarea"; 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 { Contact } from "../@types/unit"; import { citiesDatabase } from "./citiesdatabase"; @@ -19,7 +19,6 @@ export class UnitsManager { #selectionEventDisabled: boolean = false; #pasteDisabled: boolean = false; #hiddenTypes: string[] = []; - #commandMode: string = NONE; #requestDetectionUpdate: boolean = false; constructor() { @@ -36,6 +35,7 @@ export class UnitsManager { document.addEventListener('exportToFile', () => this.exportToFile()); document.addEventListener('importFromFile', () => this.importFromFile()); document.addEventListener('contactsUpdated', (e: CustomEvent) => {this.#requestDetectionUpdate = true}); + document.addEventListener("commandModeOptionsChanged", () => {Object.values(this.#units).forEach((unit: Unit) => unit.updateVisibility())}); } getSelectableAircraft() { @@ -96,7 +96,7 @@ export class UnitsManager { 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) { var unit = this.#units[ID]; if (!unit.belongsToCommandedCoalition()) @@ -127,28 +127,6 @@ export class UnitsManager { 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) { if (deselectAllUnits) this.getSelectedUnits().filter((unit: Unit) => unit.ID !== ID).forEach((unit: Unit) => unit.setSelected(false)); @@ -573,7 +551,7 @@ export class UnitsManager { } 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 */ var nUnits = this.#copiedUnits.length; var avgLat = 0; @@ -613,7 +591,7 @@ export class UnitsManager { getInfoPopup().setText(`${this.#copiedUnits.length - 1} units pasted`); } 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 = "") { var spawnPoints = 0; 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"); return false; } spawnPoints = units.reduce((points: number, unit: any) => {return points + aircraftDatabase.getSpawnPointsByName(unit.unitType)}, 0); spawnAircrafts(units, coalition, airbase, immediate, spawnPoints); } 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"); return false; } spawnPoints = units.reduce((points: number, unit: any) => {return points + helicopterDatabase.getSpawnPointsByName(unit.unitType)}, 0); spawnHelicopters(units, coalition, airbase, immediate, spawnPoints); } 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"); return false; } spawnPoints = units.reduce((points: number, unit: any) => {return points + groundUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0); spawnGroundUnits(units, coalition, immediate, spawnPoints); } 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"); return false; } spawnPoints = units.reduce((points: number, unit: any) => {return points + navyUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0); spawnNavyUnits(units, coalition, immediate, spawnPoints); } + if (spawnPoints <= getMissionHandler().getAvailableSpawnPoints()) { getMissionHandler().setSpentSpawnPoints(spawnPoints); return true; diff --git a/client/views/index.ejs b/client/views/index.ejs index b0473bbe..2d8bbe35 100644 --- a/client/views/index.ejs +++ b/client/views/index.ejs @@ -30,7 +30,7 @@
<%- include('toolbars/primary.ejs') %> - <%- include('toolbars/rts.ejs') %> + <%- include('toolbars/commandmode.ejs') %>
<%- include('other/dialogs.ejs') %> diff --git a/client/views/other/dialogs.ejs b/client/views/other/dialogs.ejs index 0619c62b..6c6ef894 100644 --- a/client/views/other/dialogs.ejs +++ b/client/views/other/dialogs.ejs @@ -233,11 +233,11 @@ -
+
-

RTS mode settings

+

command-mode mode settings

@@ -269,7 +269,7 @@
-
+
Select eras
@@ -299,7 +299,7 @@
\ No newline at end of file diff --git a/client/views/toolbars/commandmode.ejs b/client/views/toolbars/commandmode.ejs new file mode 100644 index 00000000..573c6467 --- /dev/null +++ b/client/views/toolbars/commandmode.ejs @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/client/views/toolbars/rts.ejs b/client/views/toolbars/rts.ejs deleted file mode 100644 index c32d2372..00000000 --- a/client/views/toolbars/rts.ejs +++ /dev/null @@ -1,6 +0,0 @@ - \ No newline at end of file diff --git a/src/core/include/scheduler.h b/src/core/include/scheduler.h index 2b1017b8..3cd2fe30 100644 --- a/src/core/include/scheduler.h +++ b/src/core/include/scheduler.h @@ -11,24 +11,27 @@ public: void appendCommand(Command* command); 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 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 setBlueSpawnPoints(unsigned int newBlueSpawnPoints) { blueSpawnPoints = newBlueSpawnPoints; } void setRedSpawnPoints(unsigned int newRedSpawnPoints) { redSpawnPoints = newRedSpawnPoints; } void setEras(vector newEras) { eras = newEras; } + void setCommandModeOptions(json::value newOptions); int getFrameRate() { return frameRate; }; int getLoad(); bool getRestrictSpawns() { return restrictSpawns; } - bool getRestrictToCoalition() { return restrictSpawns; } + bool getRestrictToCoalition() { return restrictToCoalition; } unsigned int getSetupTime() { return setupTime; } unsigned int getBlueSpawnPoints() { return blueSpawnPoints; } unsigned int getRedSpawnPoints() { return redSpawnPoints; } vector getEras() { return eras; } + json::value getCommandModeOptions(); private: list commands; diff --git a/src/core/include/server.h b/src/core/include/server.h index 2bcddddd..72cdf738 100644 --- a/src/core/include/server.h +++ b/src/core/include/server.h @@ -24,6 +24,7 @@ private: void handle_request(http_request request, function action); void handle_put(http_request request); + string extractUsername(http_request& request); string extractPassword(http_request& request); void task(); diff --git a/src/core/src/core.cpp b/src/core/src/core.cpp index 502ad4ea..15948906 100644 --- a/src/core/src/core.cpp +++ b/src/core/src/core.cpp @@ -67,6 +67,9 @@ extern "C" DllExport int coreFrame(lua_State* L) if (!initialized) return (0); + /* Lock for thread safety */ + lock_guard guard(mutexLock); + frameCounter++; const std::chrono::duration executionDuration = std::chrono::system_clock::now() - lastExecution; @@ -91,9 +94,9 @@ extern "C" DllExport int coreUnitsData(lua_State * L) return (0); /* Lock for thread safety */ - json::value unitsData = json::value::object(); - lock_guard guard(mutexLock); + + json::value unitsData = json::value::object(); lua_getglobal(L, "Olympus"); lua_getfield(L, -1, "unitsData"); luaTableToJSON(L, -1, unitsData); @@ -115,6 +118,7 @@ extern "C" DllExport int coreMissionData(lua_State * L) /* Lock for thread safety */ lock_guard guard(mutexLock); + lua_getglobal(L, "Olympus"); lua_getfield(L, -1, "missionData"); luaTableToJSON(L, -1, missionData); diff --git a/src/core/src/scheduler.cpp b/src/core/src/scheduler.cpp index e9b60aca..d9227ddc 100644 --- a/src/core/src/scheduler.cpp +++ b/src/core/src/scheduler.cpp @@ -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 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; log("Received request with ID: " + key); - log(value.serialize()); + log(L"Incoming command raw value: " + value.serialize()); + if (key.compare("setPath") == 0) { 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); double lat = path[i][L"lat"].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; newPath.push_back(dest); } unit->setActivePath(newPath); 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) @@ -104,7 +170,7 @@ void Scheduler::handleRequest(string key, json::value value) string color = to_string(value[L"color"]); double lat = value[L"location"][L"lat"].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; command = dynamic_cast(new Smoke(color, loc)); } @@ -114,6 +180,9 @@ void Scheduler::handleRequest(string key, json::value value) string coalition = to_string(value[L"coalition"]); string airbaseName = to_string(value[L"airbaseName"]); + int spawnPoints = value[L"spawnPoints"].as_number().to_int32(); + if (!checkSpawnPoints(spawnPoints, coalition)) return; + vector unitTypes; vector locations; vector loadouts; @@ -125,10 +194,10 @@ void Scheduler::handleRequest(string key, json::value value) Coords location; location.lat = lat; location.lng = lng; location.alt = alt; 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); locations.push_back(location); loadouts.push_back(loadout); + log(username + " spawned a " + coalition + " " + unitType, true); } command = dynamic_cast(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 airbaseName = to_string(value[L"airbaseName"]); + int spawnPoints = value[L"spawnPoints"].as_number().to_int32(); + if (!checkSpawnPoints(spawnPoints, coalition)) return; + vector unitTypes; vector locations; vector loadouts; @@ -150,10 +222,10 @@ void Scheduler::handleRequest(string key, json::value value) Coords location; location.lat = lat; location.lng = lng; location.alt = alt; 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); locations.push_back(location); loadouts.push_back(loadout); + log(username + " spawned a " + coalition + " " + unitType, true); } command = dynamic_cast(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(); string coalition = to_string(value[L"coalition"]); + int spawnPoints = value[L"spawnPoints"].as_number().to_int32(); + if (!checkSpawnPoints(spawnPoints, coalition)) return; + vector unitTypes; vector locations; 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 lng = unit[L"location"][L"lng"].as_double(); 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); locations.push_back(location); + log(username + " spawned a " + coalition + " " + unitType, true); } command = dynamic_cast(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(); string coalition = to_string(value[L"coalition"]); + int spawnPoints = value[L"spawnPoints"].as_number().to_int32(); + if (!checkSpawnPoints(spawnPoints, coalition)) return; + vector unitTypes; vector locations; 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 lng = unit[L"location"][L"lng"].as_double(); 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); locations.push_back(location); + log(username + " spawned a " + coalition + " " + unitType, true); } command = dynamic_cast(new SpawnNavyUnits(coalition, unitTypes, locations, immediate)); @@ -218,7 +298,7 @@ void Scheduler::handleRequest(string key, json::value value) else return; - log("Unit " + unitName + " attacking unit " + targetName); + log(username + " tasked unit " + unitName + " to attack unit " + targetName, true); unit->setTargetID(targetID); unit->setState(State::ATTACK); } @@ -247,7 +327,7 @@ void Scheduler::handleRequest(string key, json::value value) else return; - log("Unit " + unitName + " following unit " + leaderName); + log(username + " tasked unit " + unitName + " to follow unit " + leaderName, true); unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ)); unit->setLeaderID(leaderID); 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(); Coords loc; loc.lat = lat; loc.lng = lng; command = dynamic_cast(new Clone(ID, loc)); - log("Cloning unit " + to_string(ID)); } else if (key.compare("setROE") == 0) { @@ -316,6 +395,7 @@ void Scheduler::handleRequest(string key, json::value value) Unit* unit = unitsManager->getGroupLeader(ID); unsigned char ROE = value[L"ROE"].as_number().to_uint32(); unit->setROE(ROE); + log(username + " set unit " + unit->getName() + " ROE to " + to_string(ROE), true); } else if (key.compare("setReactionToThreat") == 0) { @@ -324,6 +404,7 @@ void Scheduler::handleRequest(string key, json::value value) Unit* unit = unitsManager->getGroupLeader(ID); unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().to_uint32(); unit->setReactionToThreat(reactionToThreat); + log(username + " set unit " + unit->getName() + " reaction to threat to " + to_string(reactionToThreat), true); } else if (key.compare("setEmissionsCountermeasures") == 0) { @@ -332,6 +413,7 @@ void Scheduler::handleRequest(string key, json::value value) Unit* unit = unitsManager->getGroupLeader(ID); unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().to_uint32(); unit->setEmissionsCountermeasures(emissionsCountermeasures); + log(username + " set unit " + unit->getName() + " emissions and countermeasures to " + to_string(emissionsCountermeasures), true); } 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(); Coords loc; loc.lat = lat; loc.lng = lng; unit->landAt(loc); + log(username + " tasked unit " + unit->getName() + " to land", true); } 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 immediate = value[L"immediate"].as_bool(); unitsManager->deleteUnit(ID, explosion, immediate); + Unit* unit = unitsManager->getUnit(ID); + log(username + " deleted unit " + unit->getName(), true); } else if (key.compare("refuel") == 0) { @@ -356,6 +441,7 @@ void Scheduler::handleRequest(string key, json::value value) unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::REFUEL); + log(username + " tasked unit " + unit->getName() + " to refuel", true); } else if (key.compare("setAdvancedOptions") == 0) { @@ -433,6 +519,7 @@ void Scheduler::handleRequest(string key, json::value value) Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::BOMB_POINT); unit->setTargetPosition(loc); + log(username + " tasked unit " + unit->getName() + " to bomb a point", true); } else if (key.compare("carpetBomb") == 0) { @@ -444,6 +531,7 @@ void Scheduler::handleRequest(string key, json::value value) Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::CARPET_BOMB); unit->setTargetPosition(loc); + log(username + " tasked unit " + unit->getName() + " to perform carpet bombing", true); } else if (key.compare("bombBuilding") == 0) { @@ -466,6 +554,11 @@ void Scheduler::handleRequest(string key, json::value value) Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::FIRE_AT_AREA); 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 { diff --git a/src/core/src/server.cpp b/src/core/src/server.cpp index 9c7b5913..36cce0e1 100644 --- a/src/core/src/server.cpp +++ b/src/core/src/server.cpp @@ -94,6 +94,7 @@ void Server::handle_get(http_request request) if (path.size() > 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) { 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())); } else { + /* Logs data*/ if (URI.compare(LOGS_URI) == 0) { auto logs = json::value::object(); getLogsJSON(logs, time); answer[L"logs"] = logs; } + /* Airbases data */ else if (URI.compare(AIRBASES_URI) == 0 && missionData.has_object_field(L"airbases")) answer[L"airbases"] = missionData[L"airbases"]; + /* Bullseyes data */ else if (URI.compare(BULLSEYE_URI) == 0 && missionData.has_object_field(L"bullseyes")) answer[L"bullseyes"] = missionData[L"bullseyes"]; + /* Mission data */ else if (URI.compare(MISSION_URI) == 0 && missionData.has_object_field(L"mission")) { answer[L"mission"] = missionData[L"mission"]; - answer[L"mission"][L"RTSOptions"] = json::value::object(); - if (password.compare(gameMasterPassword) == 0) - answer[L"mission"][L"RTSOptions"][L"commandMode"] = json::value(L"Game master"); - else if (password.compare(blueCommanderPassword) == 0) - answer[L"mission"][L"RTSOptions"][L"commandMode"] = json::value(L"Blue commander"); - else if (password.compare(redCommanderPassword) == 0) - answer[L"mission"][L"RTSOptions"][L"commandMode"] = json::value(L"Red commander"); + answer[L"mission"][L"commandModeOptions"] = scheduler->getCommandModeOptions(); - answer[L"mission"][L"RTSOptions"][L"restrictSpawns"] = json::value(scheduler->getRestrictSpawns()); - 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)); + /* The active mode is determined by the inserted password*/ + if (password.compare(gameMasterPassword) == 0) + answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Game master"); + else if (password.compare(blueCommanderPassword) == 0) + answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Blue commander"); + else if (password.compare(redCommanderPassword) == 0) + answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Red commander"); + else + answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Observer"); } + /* Common data */ answer[L"time"] = json::value::string(to_wstring(ms.count())); answer[L"sessionHash"] = json::value::string(to_wstring(sessionHash)); answer[L"load"] = scheduler->getLoad(); @@ -199,9 +197,10 @@ void Server::handle_request(http_request request, function guard(mutexLock); @@ -210,9 +209,10 @@ void Server::handle_put(http_request request) { auto key = e.first; auto value = e.second; + std::exception_ptr eptr; try { - scheduler->handleRequest(to_string(key), value); + scheduler->handleRequest(to_string(key), value, username); } catch (...) { 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) { if (request.headers().has(L"Authorization")) { string authorization = to_string(request.headers().find(L"Authorization")->second); diff --git a/src/logger/include/interface.h b/src/logger/include/interface.h index 955365b9..f712e58d 100644 --- a/src/logger/include/interface.h +++ b/src/logger/include/interface.h @@ -1,6 +1,6 @@ #pragma once #include "framework.h" -void DllExport log(const std::string& sMessage); -void DllExport log(const std::wstring& sMessage); +void DllExport log(const std::string& sMessage, bool addToJSON = false); +void DllExport log(const std::wstring& sMessage, bool addToJSON = false); void DllExport getLogsJSON(json::value& json, unsigned long long time); diff --git a/src/logger/include/logger.h b/src/logger/include/logger.h index 0d799fe8..aedd4655 100644 --- a/src/logger/include/logger.h +++ b/src/logger/include/logger.h @@ -5,8 +5,8 @@ class Logger { public: - void log(const string& sMessage); - void log(const wstring& sMessage); + void log(const string& sMessage, bool addToJSON); + void log(const wstring& sMessage, bool addToJSON); void toJSON(json::value& json, unsigned long long time); static Logger* GetLogger(); diff --git a/src/logger/src/interface.cpp b/src/logger/src/interface.cpp index 75ed631a..95c3c9a3 100644 --- a/src/logger/src/interface.cpp +++ b/src/logger/src/interface.cpp @@ -4,14 +4,14 @@ #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) diff --git a/src/logger/src/logger.cpp b/src/logger/src/logger.cpp index a3605964..e32cf76f 100644 --- a/src/logger/src/logger.cpp +++ b/src/logger/src/logger.cpp @@ -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 guard(mutexLock); Open(); milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); m_Logfile << CurrentDateTime() << ":\t"; m_Logfile << message << "\n"; - m_logs[static_cast(ms.count())] = CurrentDateTime() + ": " + message; + if (addToJSON) + m_logs[static_cast(ms.count())] = message; Close(); } -void Logger::log(const wstring& message) +void Logger::log(const wstring& message, bool addToJSON) { lock_guard guard(mutexLock); Open(); milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); m_Logfile << CurrentDateTime() << ":\t"; m_Logfile << to_string(message) << "\n"; - m_logs[static_cast(ms.count())] = CurrentDateTime() + ": " + to_string(message); + if (addToJSON) + m_logs[static_cast(ms.count())] = to_string(message); Close(); }