diff --git a/client/src/app.ts b/client/src/app.ts index 0f7c611f..749fde68 100644 --- a/client/src/app.ts +++ b/client/src/app.ts @@ -14,12 +14,12 @@ import { CommandModeToolbar } from "./toolbars/commandmodetoolbar"; import { PrimaryToolbar } from "./toolbars/primarytoolbar"; import { UnitsManager } from "./unit/unitsmanager"; import { WeaponsManager } from "./weapon/weaponsmanager"; - -import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "./constants/constants"; import { Manager } from "./other/manager"; import { ShortcutKeyboard } from "./shortcut/shortcut"; -import { getPaused, setCredentials, setPaused, startUpdate, toggleDemoEnabled } from "./server/server"; import { SVGInjector } from "@tanem/svg-injector"; +import { ServerManager } from "./server/servermanager"; + +import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "./constants/constants"; export class OlympusApp { /* Global data */ @@ -29,6 +29,7 @@ export class OlympusApp { #map: Map | null = null; /* Managers */ + #serverManager: ServerManager | null = null; #unitsManager: UnitsManager | null = null; #weaponsManager: WeaponsManager | null = null; #missionManager: MissionManager | null = null; @@ -46,10 +47,15 @@ export class OlympusApp { } + // TODO add checks on null getMap() { return this.#map as Map; } + getServerManager() { + return this.#serverManager as ServerManager; + } + getPanelsManager() { return this.#panelsManager as Manager; } @@ -122,6 +128,7 @@ export class OlympusApp { /* Initialize base functionalitites */ this.#map = new Map('map-container'); + this.#serverManager = new ServerManager(); this.#unitsManager = new UnitsManager(); this.#weaponsManager = new WeaponsManager(); this.#missionManager = new MissionManager(); @@ -151,6 +158,21 @@ export class OlympusApp { this.#pluginsManager = new PluginsManager(); + /* Load the config file from the app server*/ + this.getServerManager().getConfig((config: ConfigurationOptions) => { + if (config && config.address != undefined && config.port != undefined) { + const address = config.address; + const port = config.port; + if (typeof address === 'string' && typeof port == 'number') { + this.getServerManager().setAddress(address == "*" ? window.location.hostname : address, port); + } + } + else { + throw new Error('Could not read configuration file'); + } + }); + + /* Setup all global events */ this.#setupEvents(); } @@ -183,13 +205,13 @@ export class OlympusApp { const shortcutManager = this.getShortcutManager(); shortcutManager.add("toggleDemo", new ShortcutKeyboard({ "callback": () => { - toggleDemoEnabled(); + this.getServerManager().toggleDemoEnabled(); }, "code": "KeyT" })).add("togglePause", new ShortcutKeyboard({ "altKey": false, "callback": () => { - setPaused(!getPaused()); + this.getServerManager().setPaused(!this.getServerManager().getPaused()); }, "code": "Space", "ctrlKey": false @@ -242,10 +264,10 @@ export class OlympusApp { const password = (form?.querySelector("#password") as HTMLInputElement).value; /* Update the user credentials */ - setCredentials(username, password); + this.getServerManager().setCredentials(username, password); /* Start periodically requesting updates */ - startUpdate(); + this.getServerManager().startUpdate(); this.setLoginStatus("connecting"); }) diff --git a/client/src/contextmenus/mapcontextmenu.ts b/client/src/contextmenus/mapcontextmenu.ts index 2d86772c..2f3c3689 100644 --- a/client/src/contextmenus/mapcontextmenu.ts +++ b/client/src/contextmenus/mapcontextmenu.ts @@ -1,6 +1,5 @@ import { LatLng } from "leaflet"; import { getApp } from ".."; -import { spawnExplosion, spawnSmoke } from "../server/server"; import { ContextMenu } from "./contextmenu"; import { Switch } from "../controls/switch"; import { GAME_MASTER } from "../constants/constants"; @@ -48,14 +47,14 @@ export class MapContextMenu extends ContextMenu { document.addEventListener("contextMenuDeploySmoke", (e: any) => { this.hide(); - spawnSmoke(e.detail.color, this.getLatLng()); + getApp().getServerManager().spawnSmoke(e.detail.color, this.getLatLng()); var marker = new SmokeMarker(this.getLatLng(), e.detail.color); marker.addTo(getApp().getMap()); }); document.addEventListener("contextMenuExplosion", (e: any) => { this.hide(); - spawnExplosion(e.detail.strength, this.getLatLng()); + getApp().getServerManager().spawnExplosion(e.detail.strength, this.getLatLng()); }); document.addEventListener("editCoalitionArea", (e: any) => { diff --git a/client/src/index.ts b/client/src/index.ts index 8d7d5cba..2b637448 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -1,26 +1,10 @@ -import { getConfig, setAddress } from "./server/server"; import { OlympusApp } from "./app"; var app: OlympusApp; function setup() { - /* Load the config file from the app server*/ - getConfig((config: ConfigurationOptions) => { - if (config && config.address != undefined && config.port != undefined) { - const address = config.address; - const port = config.port; - if (typeof address === 'string' && typeof port == 'number') { - setAddress(address == "*" ? window.location.hostname : address, port); - - /* If the configuration file was successfully loaded, start the app */ - app = new OlympusApp(); - app.start(); - } - } - else { - throw new Error('Could not read configuration file'); - } - }); + app = new OlympusApp(); + app.start(); } export function getApp() { diff --git a/client/src/map/markers/temporaryunitmarker.ts b/client/src/map/markers/temporaryunitmarker.ts index 1d480a13..bd538d86 100644 --- a/client/src/map/markers/temporaryunitmarker.ts +++ b/client/src/map/markers/temporaryunitmarker.ts @@ -2,7 +2,6 @@ import { CustomMarker } from "./custommarker"; import { DivIcon, LatLng } from "leaflet"; import { SVGInjector } from "@tanem/svg-injector"; import { getMarkerCategoryByName, getUnitDatabaseByCategory } from "../../other/utils"; -import { isCommandExecuted } from "../../server/server"; import { getApp } from "../.."; export class TemporaryUnitMarker extends CustomMarker { @@ -25,7 +24,7 @@ export class TemporaryUnitMarker extends CustomMarker { this.#commandHash = commandHash; this.#timer = window.setInterval(() => { if (this.#commandHash !== undefined) { - isCommandExecuted((res: any) => { + getApp().getServerManager().isCommandExecuted((res: any) => { if (res.commandExecuted) { this.removeFrom(getApp().getMap()); window.clearInterval(this.#timer); diff --git a/client/src/mission/missionmanager.ts b/client/src/mission/missionmanager.ts index 1b6f2c85..5acf3c96 100644 --- a/client/src/mission/missionmanager.ts +++ b/client/src/mission/missionmanager.ts @@ -3,7 +3,6 @@ import { getApp } from ".."; import { Airbase } from "./airbase"; import { Bullseye } from "./bullseye"; import { BLUE_COMMANDER, GAME_MASTER, NONE, RED_COMMANDER } from "../constants/constants"; -import { refreshAll, setCommandModeOptions } from "../server/server"; import { Dropdown } from "../controls/dropdown"; import { groundUnitDatabase } from "../unit/databases/groundunitdatabase"; import { createCheckboxOption, getCheckboxOptions } from "../other/utils"; @@ -30,7 +29,7 @@ export class MissionManager { document.addEventListener("applycommandModeOptions", () => this.#applycommandModeOptions()); /* command-mode settings dialog */ - this.#commandModeDialog = document.querySelector("#command-mode-settings-dialog"); + this.#commandModeDialog = document.querySelector("#command-mode-settings-dialog") as HTMLElement; this.#commandModeErasDropdown = new Dropdown("command-mode-era-options", () => {}); } @@ -191,7 +190,7 @@ export class MissionManager { var eras: string[] = []; const enabledEras = getCheckboxOptions(this.#commandModeErasDropdown); Object.keys(enabledEras).forEach((key: string) => {if (enabledEras[key]) eras.push(key)}); - setCommandModeOptions(restrictSpawnsCheckbox.checked, restrictToCoalitionCheckbox.checked, {blue: parseInt(blueSpawnPointsInput.value), red: parseInt(redSpawnPointsInput.value)}, eras, parseInt(setupTimeInput.value) * 60); + getApp().getServerManager().setCommandModeOptions(restrictSpawnsCheckbox.checked, restrictToCoalitionCheckbox.checked, {blue: parseInt(blueSpawnPointsInput.value), red: parseInt(redSpawnPointsInput.value)}, eras, parseInt(setupTimeInput.value) * 60); } #setcommandModeOptions(commandModeOptions: CommandModeOptions) { @@ -229,7 +228,7 @@ export class MissionManager { document.querySelector("#command-mode-settings-button")?.classList.toggle("hide", this.getCommandModeOptions().commandMode !== GAME_MASTER); if (requestRefresh) - refreshAll(); + getApp().getServerManager().refreshAll(); } #onAirbaseClick(e: any) { diff --git a/client/src/server/server.ts b/client/src/server/server.ts deleted file mode 100644 index 9087abfa..00000000 --- a/client/src/server/server.ts +++ /dev/null @@ -1,492 +0,0 @@ -import { LatLng } from 'leaflet'; -import { getApp } from '..'; -import { AIRBASES_URI, BULLSEYE_URI, COMMANDS_URI, LOGS_URI, MISSION_URI, NONE, ROEs, UNITS_URI, WEAPONS_URI, emissionsCountermeasures, reactionsToThreat } from '../constants/constants'; -import { ServerStatusPanel } from '../panels/serverstatuspanel'; -import { LogPanel } from '../panels/logpanel'; -import { Popup } from '../popups/popup'; -import { ConnectionStatusPanel } from '../panels/connectionstatuspanel'; - -var connected: boolean = false; -var paused: boolean = false; - -var REST_ADDRESS = "http://localhost:30000/olympus"; -var DEMO_ADDRESS = window.location.href + "demo"; - -var username = ""; -var password = ""; - -var sessionHash: string | null = null; -var lastUpdateTimes: {[key: string]: number} = {} -lastUpdateTimes[UNITS_URI] = Date.now(); -lastUpdateTimes[WEAPONS_URI] = Date.now(); -lastUpdateTimes[LOGS_URI] = Date.now(); -lastUpdateTimes[AIRBASES_URI] = Date.now(); -lastUpdateTimes[BULLSEYE_URI] = Date.now(); -lastUpdateTimes[MISSION_URI] = Date.now(); - -var demoEnabled = false; - -export function toggleDemoEnabled() { - demoEnabled = !demoEnabled; -} - -export function setCredentials(newUsername: string, newPassword: string) { - username = newUsername; - password = newPassword; -} - -export function GET(callback: CallableFunction, uri: string, options?: ServerRequestOptions, responseType?: string) { - var xmlHttp = new XMLHttpRequest(); - - /* Assemble the request options string */ - var optionsString = ''; - if (options?.time != undefined) - optionsString = `time=${options.time}`; - if (options?.commandHash != undefined) - optionsString = `commandHash=${options.commandHash}`; - - /* On the connection */ - xmlHttp.open("GET", `${demoEnabled ? DEMO_ADDRESS : REST_ADDRESS}/${uri}${optionsString ? `?${optionsString}` : ''}`, true); - - /* If provided, set the credentials */ - if (username && password) - xmlHttp.setRequestHeader("Authorization", "Basic " + btoa(`${username}:${password}`)); - - /* If specified, set the response type */ - if (responseType) - xmlHttp.responseType = responseType as XMLHttpRequestResponseType; - - xmlHttp.onload = function (e) { - if (xmlHttp.status == 200) { - /* Success */ - setConnected(true); - if (xmlHttp.responseType == 'arraybuffer') - lastUpdateTimes[uri] = callback(xmlHttp.response); - else { - const result = JSON.parse(xmlHttp.responseText); - lastUpdateTimes[uri] = callback(result); - - if (result.frameRate !== undefined && result.load !== undefined) - (getApp().getPanelsManager().get("serverStatus") as ServerStatusPanel).update(result.frameRate, result.load); - } - } else if (xmlHttp.status == 401) { - /* Bad credentials */ - console.error("Incorrect username/password"); - getApp().setLoginStatus("failed"); - } else { - /* Failure, probably disconnected */ - setConnected(false); - } - }; - xmlHttp.onerror = function (res) { - console.error("An error occurred during the XMLHttpRequest"); - setConnected(false); - }; - xmlHttp.send(null); -} - -export function POST(request: object, callback: CallableFunction) { - var xmlHttp = new XMLHttpRequest(); - xmlHttp.open("PUT", demoEnabled ? DEMO_ADDRESS : REST_ADDRESS); - xmlHttp.setRequestHeader("Content-Type", "application/json"); - if (username && password) - xmlHttp.setRequestHeader("Authorization", "Basic " + btoa(`${username}:${password}`)); - xmlHttp.onload = (res: any) => { - var res = JSON.parse(xmlHttp.responseText); - callback(res); - }; - xmlHttp.send(JSON.stringify(request)); -} - -export function getConfig(callback: CallableFunction) { - var xmlHttp = new XMLHttpRequest(); - xmlHttp.open("GET", window.location.href + "config", true); - xmlHttp.onload = function (e) { - var data = JSON.parse(xmlHttp.responseText); - callback(data); - }; - xmlHttp.onerror = function () { - console.error("An error occurred during the XMLHttpRequest, could not retrieve configuration file"); - }; - xmlHttp.send(null); -} - -export function setAddress(address: string, port: number) { - REST_ADDRESS = `http://${address}:${port}/olympus` - console.log(`Setting REST address to ${REST_ADDRESS}`) -} - -export function getAirbases(callback: CallableFunction) { - GET(callback, AIRBASES_URI); -} - -export function getBullseye(callback: CallableFunction) { - GET(callback, BULLSEYE_URI); -} - -export function getLogs(callback: CallableFunction, refresh: boolean = false) { - GET(callback, LOGS_URI, { time: refresh ? 0 : lastUpdateTimes[LOGS_URI]}); -} - -export function getMission(callback: CallableFunction) { - GET(callback, MISSION_URI); -} - -export function getUnits(callback: CallableFunction, refresh: boolean = false) { - GET(callback, UNITS_URI, { time: refresh ? 0 : lastUpdateTimes[UNITS_URI] }, 'arraybuffer'); -} - -export function getWeapons(callback: CallableFunction, refresh: boolean = false) { - GET(callback, WEAPONS_URI, { time: refresh ? 0 : lastUpdateTimes[WEAPONS_URI] }, 'arraybuffer'); -} - -export function isCommandExecuted(callback: CallableFunction, commandHash: string) { - GET(callback, COMMANDS_URI, { commandHash: commandHash}); -} - -export function addDestination(ID: number, path: any, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "path": path } - var data = { "setPath": command } - POST(data, callback); -} - -export function spawnSmoke(color: string, latlng: LatLng, callback: CallableFunction = () => {}) { - var command = { "color": color, "location": latlng }; - var data = { "smoke": command } - POST(data, callback); -} - -export function spawnExplosion(intensity: number, latlng: LatLng, callback: CallableFunction = () => {}) { - var command = { "intensity": intensity, "location": latlng }; - var data = { "explosion": command } - POST(data, callback); -} - -export function spawnAircrafts(units: any, coalition: string, airbaseName: string, country: string, immediate: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { - var command = { "units": units, "coalition": coalition, "airbaseName": airbaseName, "country": country, "immediate": immediate, "spawnPoints": spawnPoints }; - var data = { "spawnAircrafts": command } - POST(data, callback); -} - -export function spawnHelicopters(units: any, coalition: string, airbaseName: string, country: string, immediate: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { - var command = { "units": units, "coalition": coalition, "airbaseName": airbaseName, "country": country, "immediate": immediate, "spawnPoints": spawnPoints }; - var data = { "spawnHelicopters": command } - POST(data, callback); -} - -export function spawnGroundUnits(units: any, coalition: string, country: string, immediate: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { - var command = { "units": units, "coalition": coalition, "country": country, "immediate": immediate, "spawnPoints": spawnPoints };; - var data = { "spawnGroundUnits": command } - POST(data, callback); -} - -export function spawnNavyUnits(units: any, coalition: string, country: string, immediate: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { - var command = { "units": units, "coalition": coalition, "country": country, "immediate": immediate, "spawnPoints": spawnPoints }; - var data = { "spawnNavyUnits": command } - POST(data, callback); -} - -export function attackUnit(ID: number, targetID: number, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "targetID": targetID }; - var data = { "attackUnit": command } - POST(data, callback); -} - -export function followUnit(ID: number, targetID: number, offset: { "x": number, "y": number, "z": number }, callback: CallableFunction = () => {}) { - // X: front-rear, positive front - // Y: top-bottom, positive bottom - // Z: left-right, positive right - - var command = { "ID": ID, "targetID": targetID, "offsetX": offset["x"], "offsetY": offset["y"], "offsetZ": offset["z"] }; - var data = { "followUnit": command } - POST(data, callback); -} - -export function cloneUnits(units: {ID: number, location: LatLng}[], deleteOriginal: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { - var command = { "units": units, "deleteOriginal": deleteOriginal, "spawnPoints": spawnPoints }; - var data = { "cloneUnits": command } - POST(data, callback); -} - -export function deleteUnit(ID: number, explosion: boolean, immediate: boolean, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "explosion": explosion, "immediate": immediate }; - var data = { "deleteUnit": command } - POST(data, callback); -} - -export function landAt(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "location": latlng }; - var data = { "landAt": command } - POST(data, callback); -} - -export function changeSpeed(ID: number, speedChange: string, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "change": speedChange } - var data = { "changeSpeed": command } - POST(data, callback); -} - -export function setSpeed(ID: number, speed: number, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "speed": speed } - var data = { "setSpeed": command } - POST(data, callback); -} - -export function setSpeedType(ID: number, speedType: string, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "speedType": speedType } - var data = { "setSpeedType": command } - POST(data, callback); -} - -export function changeAltitude(ID: number, altitudeChange: string, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "change": altitudeChange } - var data = { "changeAltitude": command } - POST(data, callback); -} - -export function setAltitudeType(ID: number, altitudeType: string, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "altitudeType": altitudeType } - var data = { "setAltitudeType": command } - POST(data, callback); -} - -export function setAltitude(ID: number, altitude: number, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "altitude": altitude } - var data = { "setAltitude": command } - POST(data, callback); -} - -export function createFormation(ID: number, isLeader: boolean, wingmenIDs: number[], callback: CallableFunction = () => {}) { - var command = { "ID": ID, "wingmenIDs": wingmenIDs, "isLeader": isLeader } - var data = { "setLeader": command } - POST(data, callback); -} - -export function setROE(ID: number, ROE: string, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "ROE": ROEs.indexOf(ROE) } - var data = { "setROE": command } - POST(data, callback); -} - -export function setReactionToThreat(ID: number, reactionToThreat: string, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "reactionToThreat": reactionsToThreat.indexOf(reactionToThreat) } - var data = { "setReactionToThreat": command } - POST(data, callback); -} - -export function setEmissionsCountermeasures(ID: number, emissionCountermeasure: string, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "emissionsCountermeasures": emissionsCountermeasures.indexOf(emissionCountermeasure) } - var data = { "setEmissionsCountermeasures": command } - POST(data, callback); -} - -export function setOnOff(ID: number, onOff: boolean, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "onOff": onOff } - var data = { "setOnOff": command } - POST(data, callback); -} - -export function setFollowRoads(ID: number, followRoads: boolean, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "followRoads": followRoads } - var data = { "setFollowRoads": command } - POST(data, callback); -} - -export function refuel(ID: number, callback: CallableFunction = () => {}) { - var command = { "ID": ID }; - var data = { "refuel": command } - POST(data, callback); -} - -export function bombPoint(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "location": latlng } - var data = { "bombPoint": command } - POST(data, callback); -} - -export function carpetBomb(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "location": latlng } - var data = { "carpetBomb": command } - POST(data, callback); -} - -export function bombBuilding(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "location": latlng } - var data = { "bombBuilding": command } - POST(data, callback); -} - -export function fireAtArea(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "location": latlng } - var data = { "fireAtArea": command } - POST(data, callback); -} - -export function setAdvacedOptions(ID: number, isTanker: boolean, isAWACS: boolean, TACAN: TACAN, radio: Radio, generalSettings: GeneralSettings, callback: CallableFunction = () => {}) { - var command = { - "ID": ID, - "isTanker": isTanker, - "isAWACS": isAWACS, - "TACAN": TACAN, - "radio": radio, - "generalSettings": generalSettings - }; - - var data = { "setAdvancedOptions": command }; - POST(data, callback); -} - -export function setCommandModeOptions(restrictSpawns: boolean, restrictToCoalition: boolean, spawnPoints: {blue: number, red: number}, eras: string[], setupTime: number, callback: CallableFunction = () => {}) { - var command = { - "restrictSpawns": restrictSpawns, - "restrictToCoalition": restrictToCoalition, - "spawnPoints": spawnPoints, - "eras": eras, - "setupTime": setupTime - }; - - var data = { "setCommandModeOptions": command }; - POST(data, callback); -} - -export function startUpdate() { - window.setInterval(() => { - if (!getPaused()) { - getMission((data: MissionData) => { - checkSessionHash(data.sessionHash); - getApp().getMissionManager()?.updateMission(data); - return data.time; - }); - } - }, 1000); - - window.setInterval(() => { - if (!getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { - getAirbases((data: AirbasesData) => { - checkSessionHash(data.sessionHash); - getApp().getMissionManager()?.updateAirbases(data); - return data.time; - }); - } - }, 10000); - - window.setInterval(() => { - if (!getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE){ - getBullseye((data: BullseyesData) => { - checkSessionHash(data.sessionHash); - getApp().getMissionManager()?.updateBullseyes(data); - return data.time; - }); - } - }, 10000); - - window.setInterval(() => { - if (!getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { - getLogs((data: any) => { - checkSessionHash(data.sessionHash); - (getApp().getPanelsManager().get("log") as LogPanel).appendLogs(data.logs) - return data.time; - }); - } - }, 1000); - - window.setInterval(() => { - if (!getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { - getUnits((buffer: ArrayBuffer) => { - var time = getApp().getUnitsManager()?.update(buffer); - return time; - }, false); - } - }, 250); - - window.setInterval(() => { - if (!getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { - getWeapons((buffer: ArrayBuffer) => { - var time = getApp().getWeaponsManager()?.update(buffer); - return time; - }, false); - } - }, 250); - - window.setInterval(() => { - if (!getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { - getUnits((buffer: ArrayBuffer) => { - var time = getApp().getUnitsManager()?.update(buffer); - return time; - }, true); - (getApp().getPanelsManager().get("connectionStatus") as ConnectionStatusPanel).update(getConnected()); - } - }, 5000); - - window.setInterval(() => { - if (!getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { - getWeapons((buffer: ArrayBuffer) => { - var time = getApp().getWeaponsManager()?.update(buffer); - return time; - }, true); - } - }, 5000); -} - -export function refreshAll() { - getAirbases((data: AirbasesData) => { - checkSessionHash(data.sessionHash); - getApp().getMissionManager()?.updateAirbases(data); - return data.time; - }); - - getBullseye((data: BullseyesData) => { - checkSessionHash(data.sessionHash); - getApp().getMissionManager()?.updateBullseyes(data); - return data.time; - }); - - getLogs((data: any) => { - checkSessionHash(data.sessionHash); - (getApp().getPanelsManager().get("log") as LogPanel).appendLogs(data.logs) - return data.time; - }); - - getWeapons((buffer: ArrayBuffer) => { - var time = getApp().getWeaponsManager()?.update(buffer); - return time; - }, true); - - getUnits((buffer: ArrayBuffer) => { - var time = getApp().getUnitsManager()?.update(buffer); - return time; - }, true); -} - -export function checkSessionHash(newSessionHash: string) { - if (sessionHash != null) { - if (newSessionHash !== sessionHash) - location.reload(); - } - else - sessionHash = newSessionHash; -} - -export function setConnected(newConnected: boolean) { - if (connected != newConnected) - newConnected ? (getApp().getPopupsManager().get("infoPopup") as Popup).setText("Connected to DCS Olympus server") : (getApp().getPopupsManager().get("infoPopup") as Popup).setText("Disconnected from DCS Olympus server"); - connected = newConnected; - - if (connected) { - document.querySelector("#splash-screen")?.classList.add("hide"); - document.querySelector("#gray-out")?.classList.add("hide"); - } -} - -export function getConnected() { - return connected; -} - -export function setPaused(newPaused: boolean) { - paused = newPaused; - paused ? (getApp().getPopupsManager().get("infoPopup") as Popup).setText("View paused") : (getApp().getPopupsManager().get("infoPopup") as Popup).setText("View unpaused"); -} - -export function getPaused() { - return paused; -} \ No newline at end of file diff --git a/client/src/server/servermanager.ts b/client/src/server/servermanager.ts new file mode 100644 index 00000000..d2747e69 --- /dev/null +++ b/client/src/server/servermanager.ts @@ -0,0 +1,493 @@ +import { LatLng } from 'leaflet'; +import { getApp } from '..'; +import { AIRBASES_URI, BULLSEYE_URI, COMMANDS_URI, LOGS_URI, MISSION_URI, NONE, ROEs, UNITS_URI, WEAPONS_URI, emissionsCountermeasures, reactionsToThreat } from '../constants/constants'; +import { ServerStatusPanel } from '../panels/serverstatuspanel'; +import { LogPanel } from '../panels/logpanel'; +import { Popup } from '../popups/popup'; +import { ConnectionStatusPanel } from '../panels/connectionstatuspanel'; + +export class ServerManager { + #connected: boolean = false; + #paused: boolean = false; + #REST_ADDRESS = "http://localhost:30000/olympus"; + #DEMO_ADDRESS = window.location.href + "demo"; + #username = ""; + #password = ""; + #sessionHash: string | null = null; + #lastUpdateTimes: {[key: string]: number} = {} + #demoEnabled = false; + + constructor() { + this.#lastUpdateTimes[UNITS_URI] = Date.now(); + this.#lastUpdateTimes[WEAPONS_URI] = Date.now(); + this.#lastUpdateTimes[LOGS_URI] = Date.now(); + this.#lastUpdateTimes[AIRBASES_URI] = Date.now(); + this.#lastUpdateTimes[BULLSEYE_URI] = Date.now(); + this.#lastUpdateTimes[MISSION_URI] = Date.now(); + } + + toggleDemoEnabled() { + this.#demoEnabled = !this.#demoEnabled; + } + + setCredentials(newUsername: string, newPassword: string) { + this.#username = newUsername; + this.#password = newPassword; + } + + GET(callback: CallableFunction, uri: string, options?: ServerRequestOptions, responseType?: string) { + var xmlHttp = new XMLHttpRequest(); + + /* Assemble the request options string */ + var optionsString = ''; + if (options?.time != undefined) + optionsString = `time=${options.time}`; + if (options?.commandHash != undefined) + optionsString = `commandHash=${options.commandHash}`; + + /* On the connection */ + xmlHttp.open("GET", `${this.#demoEnabled ? this.#DEMO_ADDRESS : this.#REST_ADDRESS}/${uri}${optionsString ? `?${optionsString}` : ''}`, true); + + /* If provided, set the credentials */ + if (this.#username && this.#password) + xmlHttp.setRequestHeader("Authorization", "Basic " + btoa(`${this.#username}:${this.#password}`)); + + /* If specified, set the response type */ + if (responseType) + xmlHttp.responseType = responseType as XMLHttpRequestResponseType; + + xmlHttp.onload = (e) => { + if (xmlHttp.status == 200) { + /* Success */ + this.setConnected(true); + if (xmlHttp.responseType == 'arraybuffer') + this.#lastUpdateTimes[uri] = callback(xmlHttp.response); + else { + const result = JSON.parse(xmlHttp.responseText); + this.#lastUpdateTimes[uri] = callback(result); + + if (result.frameRate !== undefined && result.load !== undefined) + (getApp().getPanelsManager().get("serverStatus") as ServerStatusPanel).update(result.frameRate, result.load); + } + } else if (xmlHttp.status == 401) { + /* Bad credentials */ + console.error("Incorrect username/password"); + getApp().setLoginStatus("failed"); + } else { + /* Failure, probably disconnected */ + this.setConnected(false); + } + }; + xmlHttp.onerror = (res) => { + console.error("An error occurred during the XMLHttpRequest"); + this.setConnected(false); + }; + xmlHttp.send(null); + } + + POST(request: object, callback: CallableFunction) { + var xmlHttp = new XMLHttpRequest(); + xmlHttp.open("PUT", this.#demoEnabled ? this.#DEMO_ADDRESS : this.#REST_ADDRESS); + xmlHttp.setRequestHeader("Content-Type", "application/json"); + if (this.#username && this.#password) + xmlHttp.setRequestHeader("Authorization", "Basic " + btoa(`${this.#username}:${this.#password}`)); + xmlHttp.onload = (res: any) => { + var res = JSON.parse(xmlHttp.responseText); + callback(res); + }; + xmlHttp.send(JSON.stringify(request)); + } + + getConfig(callback: CallableFunction) { + var xmlHttp = new XMLHttpRequest(); + xmlHttp.open("GET", window.location.href + "config", true); + xmlHttp.onload = function (e) { + var data = JSON.parse(xmlHttp.responseText); + callback(data); + }; + xmlHttp.onerror = function () { + console.error("An error occurred during the XMLHttpRequest, could not retrieve configuration file"); + }; + xmlHttp.send(null); + } + + setAddress(address: string, port: number) { + this.#REST_ADDRESS = `http://${address}:${port}/olympus` + console.log(`Setting REST address to ${this.#REST_ADDRESS}`) + } + + getAirbases(callback: CallableFunction) { + this.GET(callback, AIRBASES_URI); + } + + getBullseye(callback: CallableFunction) { + this.GET(callback, BULLSEYE_URI); + } + + getLogs(callback: CallableFunction, refresh: boolean = false) { + this.GET(callback, LOGS_URI, { time: refresh ? 0 : this.#lastUpdateTimes[LOGS_URI]}); + } + + getMission(callback: CallableFunction) { + this.GET(callback, MISSION_URI); + } + + getUnits(callback: CallableFunction, refresh: boolean = false) { + this.GET(callback, UNITS_URI, { time: refresh ? 0 : this.#lastUpdateTimes[UNITS_URI] }, 'arraybuffer'); + } + + getWeapons(callback: CallableFunction, refresh: boolean = false) { + this.GET(callback, WEAPONS_URI, { time: refresh ? 0 : this.#lastUpdateTimes[WEAPONS_URI] }, 'arraybuffer'); + } + + isCommandExecuted(callback: CallableFunction, commandHash: string) { + this.GET(callback, COMMANDS_URI, { commandHash: commandHash}); + } + + addDestination(ID: number, path: any, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "path": path } + var data = { "setPath": command } + this.POST(data, callback); + } + + spawnSmoke(color: string, latlng: LatLng, callback: CallableFunction = () => {}) { + var command = { "color": color, "location": latlng }; + var data = { "smoke": command } + this.POST(data, callback); + } + + spawnExplosion(intensity: number, latlng: LatLng, callback: CallableFunction = () => {}) { + var command = { "intensity": intensity, "location": latlng }; + var data = { "explosion": command } + this.POST(data, callback); + } + + spawnAircrafts(units: any, coalition: string, airbaseName: string, country: string, immediate: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { + var command = { "units": units, "coalition": coalition, "airbaseName": airbaseName, "country": country, "immediate": immediate, "spawnPoints": spawnPoints }; + var data = { "spawnAircrafts": command } + this.POST(data, callback); + } + + spawnHelicopters(units: any, coalition: string, airbaseName: string, country: string, immediate: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { + var command = { "units": units, "coalition": coalition, "airbaseName": airbaseName, "country": country, "immediate": immediate, "spawnPoints": spawnPoints }; + var data = { "spawnHelicopters": command } + this.POST(data, callback); + } + + spawnGroundUnits(units: any, coalition: string, country: string, immediate: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { + var command = { "units": units, "coalition": coalition, "country": country, "immediate": immediate, "spawnPoints": spawnPoints };; + var data = { "spawnGroundUnits": command } + this.POST(data, callback); + } + + spawnNavyUnits(units: any, coalition: string, country: string, immediate: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { + var command = { "units": units, "coalition": coalition, "country": country, "immediate": immediate, "spawnPoints": spawnPoints }; + var data = { "spawnNavyUnits": command } + this.POST(data, callback); + } + + attackUnit(ID: number, targetID: number, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "targetID": targetID }; + var data = { "attackUnit": command } + this.POST(data, callback); + } + + followUnit(ID: number, targetID: number, offset: { "x": number, "y": number, "z": number }, callback: CallableFunction = () => {}) { + // X: front-rear, positive front + // Y: top-bottom, positive bottom + // Z: left-right, positive right + + var command = { "ID": ID, "targetID": targetID, "offsetX": offset["x"], "offsetY": offset["y"], "offsetZ": offset["z"] }; + var data = { "followUnit": command } + this.POST(data, callback); + } + + cloneUnits(units: {ID: number, location: LatLng}[], deleteOriginal: boolean, spawnPoints: number, callback: CallableFunction = () => {}) { + var command = { "units": units, "deleteOriginal": deleteOriginal, "spawnPoints": spawnPoints }; + var data = { "cloneUnits": command } + this.POST(data, callback); + } + + deleteUnit(ID: number, explosion: boolean, immediate: boolean, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "explosion": explosion, "immediate": immediate }; + var data = { "deleteUnit": command } + this.POST(data, callback); + } + + landAt(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "location": latlng }; + var data = { "landAt": command } + this.POST(data, callback); + } + + changeSpeed(ID: number, speedChange: string, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "change": speedChange } + var data = { "changeSpeed": command } + this.POST(data, callback); + } + + setSpeed(ID: number, speed: number, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "speed": speed } + var data = { "setSpeed": command } + this.POST(data, callback); + } + + setSpeedType(ID: number, speedType: string, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "speedType": speedType } + var data = { "setSpeedType": command } + this.POST(data, callback); + } + + changeAltitude(ID: number, altitudeChange: string, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "change": altitudeChange } + var data = { "changeAltitude": command } + this.POST(data, callback); + } + + setAltitudeType(ID: number, altitudeType: string, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "altitudeType": altitudeType } + var data = { "setAltitudeType": command } + this.POST(data, callback); + } + + setAltitude(ID: number, altitude: number, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "altitude": altitude } + var data = { "setAltitude": command } + this.POST(data, callback); + } + + createFormation(ID: number, isLeader: boolean, wingmenIDs: number[], callback: CallableFunction = () => {}) { + var command = { "ID": ID, "wingmenIDs": wingmenIDs, "isLeader": isLeader } + var data = { "setLeader": command } + this.POST(data, callback); + } + + setROE(ID: number, ROE: string, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "ROE": ROEs.indexOf(ROE) } + var data = { "setROE": command } + this.POST(data, callback); + } + + setReactionToThreat(ID: number, reactionToThreat: string, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "reactionToThreat": reactionsToThreat.indexOf(reactionToThreat) } + var data = { "setReactionToThreat": command } + this.POST(data, callback); + } + + setEmissionsCountermeasures(ID: number, emissionCountermeasure: string, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "emissionsCountermeasures": emissionsCountermeasures.indexOf(emissionCountermeasure) } + var data = { "setEmissionsCountermeasures": command } + this.POST(data, callback); + } + + setOnOff(ID: number, onOff: boolean, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "onOff": onOff } + var data = { "setOnOff": command } + this.POST(data, callback); + } + + setFollowRoads(ID: number, followRoads: boolean, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "followRoads": followRoads } + var data = { "setFollowRoads": command } + this.POST(data, callback); + } + + refuel(ID: number, callback: CallableFunction = () => {}) { + var command = { "ID": ID }; + var data = { "refuel": command } + this.POST(data, callback); + } + + bombPoint(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "location": latlng } + var data = { "bombPoint": command } + this.POST(data, callback); + } + + carpetBomb(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "location": latlng } + var data = { "carpetBomb": command } + this.POST(data, callback); + } + + bombBuilding(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "location": latlng } + var data = { "bombBuilding": command } + this.POST(data, callback); + } + + fireAtArea(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "location": latlng } + var data = { "fireAtArea": command } + this.POST(data, callback); + } + + setAdvacedOptions(ID: number, isTanker: boolean, isAWACS: boolean, TACAN: TACAN, radio: Radio, generalSettings: GeneralSettings, callback: CallableFunction = () => {}) { + var command = { + "ID": ID, + "isTanker": isTanker, + "isAWACS": isAWACS, + "TACAN": TACAN, + "radio": radio, + "generalSettings": generalSettings + }; + + var data = { "setAdvancedOptions": command }; + this.POST(data, callback); + } + + setCommandModeOptions(restrictSpawns: boolean, restrictToCoalition: boolean, spawnPoints: {blue: number, red: number}, eras: string[], setupTime: number, callback: CallableFunction = () => {}) { + var command = { + "restrictSpawns": restrictSpawns, + "restrictToCoalition": restrictToCoalition, + "spawnPoints": spawnPoints, + "eras": eras, + "setupTime": setupTime + }; + + var data = { "setCommandModeOptions": command }; + this.POST(data, callback); + } + + startUpdate() { + window.setInterval(() => { + if (!this.getPaused()) { + this.getMission((data: MissionData) => { + this.checkSessionHash(data.sessionHash); + getApp().getMissionManager()?.updateMission(data); + return data.time; + }); + } + }, 1000); + + window.setInterval(() => { + if (!this.getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { + this.getAirbases((data: AirbasesData) => { + this.checkSessionHash(data.sessionHash); + getApp().getMissionManager()?.updateAirbases(data); + return data.time; + }); + } + }, 10000); + + window.setInterval(() => { + if (!this.getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE){ + this.getBullseye((data: BullseyesData) => { + this.checkSessionHash(data.sessionHash); + getApp().getMissionManager()?.updateBullseyes(data); + return data.time; + }); + } + }, 10000); + + window.setInterval(() => { + if (!this.getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { + this.getLogs((data: any) => { + this.checkSessionHash(data.sessionHash); + (getApp().getPanelsManager().get("log") as LogPanel).appendLogs(data.logs) + return data.time; + }); + } + }, 1000); + + window.setInterval(() => { + if (!this.getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { + this.getUnits((buffer: ArrayBuffer) => { + var time = getApp().getUnitsManager()?.update(buffer); + return time; + }, false); + } + }, 250); + + window.setInterval(() => { + if (!this.getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { + this.getWeapons((buffer: ArrayBuffer) => { + var time = getApp().getWeaponsManager()?.update(buffer); + return time; + }, false); + } + }, 250); + + window.setInterval(() => { + if (!this.getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { + this.getUnits((buffer: ArrayBuffer) => { + var time = getApp().getUnitsManager()?.update(buffer); + return time; + }, true); + (getApp().getPanelsManager().get("connectionStatus") as ConnectionStatusPanel).update(this.getConnected()); + } + }, 5000); + + window.setInterval(() => { + if (!this.getPaused() && getApp().getMissionManager().getCommandModeOptions().commandMode != NONE) { + this.getWeapons((buffer: ArrayBuffer) => { + var time = getApp().getWeaponsManager()?.update(buffer); + return time; + }, true); + } + }, 5000); + } + + refreshAll() { + this.getAirbases((data: AirbasesData) => { + this.checkSessionHash(data.sessionHash); + getApp().getMissionManager()?.updateAirbases(data); + return data.time; + }); + + this.getBullseye((data: BullseyesData) => { + this.checkSessionHash(data.sessionHash); + getApp().getMissionManager()?.updateBullseyes(data); + return data.time; + }); + + this.getLogs((data: any) => { + this.checkSessionHash(data.sessionHash); + (getApp().getPanelsManager().get("log") as LogPanel).appendLogs(data.logs) + return data.time; + }); + + this.getWeapons((buffer: ArrayBuffer) => { + var time = getApp().getWeaponsManager()?.update(buffer); + return time; + }, true); + + this.getUnits((buffer: ArrayBuffer) => { + var time = getApp().getUnitsManager()?.update(buffer); + return time; + }, true); + } + + checkSessionHash(newSessionHash: string) { + if (this.#sessionHash != null) { + if (newSessionHash !== this.#sessionHash) + location.reload(); + } + else + this.#sessionHash = newSessionHash; + } + + setConnected(newConnected: boolean) { + if (this.#connected != newConnected) + newConnected ? (getApp().getPopupsManager().get("infoPopup") as Popup).setText("Connected to DCS Olympus server") : (getApp().getPopupsManager().get("infoPopup") as Popup).setText("Disconnected from DCS Olympus server"); + this.#connected = newConnected; + + if (this.#connected) { + document.querySelector("#splash-screen")?.classList.add("hide"); + document.querySelector("#gray-out")?.classList.add("hide"); + } + } + + getConnected() { + return this.#connected; + } + + setPaused(newPaused: boolean) { + this.#paused = newPaused; + this.#paused ? (getApp().getPopupsManager().get("infoPopup") as Popup).setText("View paused") : (getApp().getPopupsManager().get("infoPopup") as Popup).setText("View unpaused"); + } + + getPaused() { + return this.#paused; + } +} diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts index 7ca1d5d8..60b801f8 100644 --- a/client/src/unit/unit.ts +++ b/client/src/unit/unit.ts @@ -1,7 +1,6 @@ import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map, Point } from 'leaflet'; import { getApp } from '..'; import { enumToCoalition, enumToEmissioNCountermeasure, getMarkerCategoryByName, enumToROE, enumToReactionToThreat, enumToState, getUnitDatabaseByCategory, mToFt, msToKnots, rad2deg, bearing, deg2rad, ftToM } 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/markers/custommarker'; import { SVGInjector } from '@tanem/svg-injector'; import { UnitDatabase } from './databases/unitdatabase'; @@ -610,7 +609,7 @@ export class Unit extends CustomMarker { else { path = [latlng]; } - addDestination(this.ID, path); + getApp().getServerManager().addDestination(this.ID, path); } } @@ -623,109 +622,104 @@ export class Unit extends CustomMarker { /* Units can't attack themselves */ if (!this.#human) if (this.ID != targetID) - attackUnit(this.ID, targetID); + getApp().getServerManager().attackUnit(this.ID, targetID); } followUnit(targetID: number, offset: { "x": number, "y": number, "z": number }) { /* Units can't follow themselves */ if (!this.#human) if (this.ID != targetID) - followUnit(this.ID, targetID, offset); + getApp().getServerManager().followUnit(this.ID, targetID, offset); } landAt(latlng: LatLng) { if (!this.#human) - landAt(this.ID, latlng); + getApp().getServerManager().landAt(this.ID, latlng); } changeSpeed(speedChange: string) { if (!this.#human) - changeSpeed(this.ID, speedChange); + getApp().getServerManager().changeSpeed(this.ID, speedChange); } changeAltitude(altitudeChange: string) { if (!this.#human) - changeAltitude(this.ID, altitudeChange); + getApp().getServerManager().changeAltitude(this.ID, altitudeChange); } setSpeed(speed: number) { if (!this.#human) - setSpeed(this.ID, speed); + getApp().getServerManager().setSpeed(this.ID, speed); } setSpeedType(speedType: string) { if (!this.#human) - setSpeedType(this.ID, speedType); + getApp().getServerManager().setSpeedType(this.ID, speedType); } setAltitude(altitude: number) { if (!this.#human) - setAltitude(this.ID, altitude); + getApp().getServerManager().setAltitude(this.ID, altitude); } setAltitudeType(altitudeType: string) { if (!this.#human) - setAltitudeType(this.ID, altitudeType); + getApp().getServerManager().setAltitudeType(this.ID, altitudeType); } setROE(ROE: string) { if (!this.#human) - setROE(this.ID, ROE); + getApp().getServerManager().setROE(this.ID, ROE); } setReactionToThreat(reactionToThreat: string) { if (!this.#human) - setReactionToThreat(this.ID, reactionToThreat); + getApp().getServerManager().setReactionToThreat(this.ID, reactionToThreat); } setEmissionsCountermeasures(emissionCountermeasure: string) { if (!this.#human) - setEmissionsCountermeasures(this.ID, emissionCountermeasure); - } - - setLeader(isLeader: boolean, wingmenIDs: number[] = []) { - if (!this.#human) - setLeader(this.ID, isLeader, wingmenIDs); + getApp().getServerManager().setEmissionsCountermeasures(this.ID, emissionCountermeasure); } setOnOff(onOff: boolean) { if (!this.#human) - setOnOff(this.ID, onOff); + getApp().getServerManager().setOnOff(this.ID, onOff); } setFollowRoads(followRoads: boolean) { if (!this.#human) - setFollowRoads(this.ID, followRoads); + getApp().getServerManager().setFollowRoads(this.ID, followRoads); } delete(explosion: boolean, immediate: boolean) { - deleteUnit(this.ID, explosion, immediate); + getApp().getServerManager().deleteUnit(this.ID, explosion, immediate); } refuel() { if (!this.#human) - refuel(this.ID); + getApp().getServerManager().refuel(this.ID); } setAdvancedOptions(isTanker: boolean, isAWACS: boolean, TACAN: TACAN, radio: Radio, generalSettings: GeneralSettings) { if (!this.#human) - setAdvacedOptions(this.ID, isTanker, isAWACS, TACAN, radio, generalSettings); + getApp().getServerManager().setAdvacedOptions(this.ID, isTanker, isAWACS, TACAN, radio, generalSettings); } bombPoint(latlng: LatLng) { - bombPoint(this.ID, latlng); + getApp().getServerManager().bombPoint(this.ID, latlng); } carpetBomb(latlng: LatLng) { - carpetBomb(this.ID, latlng); + getApp().getServerManager().carpetBomb(this.ID, latlng); } bombBuilding(latlng: LatLng) { - bombBuilding(this.ID, latlng); + getApp().getServerManager().bombBuilding(this.ID, latlng); } fireAtArea(latlng: LatLng) { - fireAtArea(this.ID, latlng); + getApp().getServerManager().fireAtArea(this.ID, latlng); } /***********************************************/ diff --git a/client/src/unit/unitsmanager.ts b/client/src/unit/unitsmanager.ts index c0a0f6d5..4feda9e4 100644 --- a/client/src/unit/unitsmanager.ts +++ b/client/src/unit/unitsmanager.ts @@ -1,7 +1,6 @@ import { LatLng, LatLngBounds } from "leaflet"; import { getApp } from ".."; import { Unit } from "./unit"; -import { cloneUnits, spawnAircrafts, spawnGroundUnits, spawnHelicopters, spawnNavyUnits } from "../server/server"; import { bearingAndDistanceToLatLng, deg2rad, getUnitDatabaseByCategory, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils"; import { CoalitionArea } from "../map/coalitionarea/coalitionarea"; import { groundUnitDatabase } from "./databases/groundunitdatabase"; @@ -635,7 +634,7 @@ export class UnitsManager { var unit = selectedUnits[idx]; units.push({ ID: unit.ID, location: unit.getPosition() }); } - cloneUnits(units, true, 0 /* No spawn points, we delete the original units */); + getApp().getServerManager().cloneUnits(units, true, 0 /* No spawn points, we delete the original units */); } else { (getApp().getPopupsManager().get("infoPopup") as Popup).setText(`Groups can only be created from units of the same category`); } @@ -790,7 +789,7 @@ export class UnitsManager { units.push({ ID: unit.ID, location: position }); }); - cloneUnits(units, false, spawnPoints, (res: any) => { + getApp().getServerManager().cloneUnits(units, false, spawnPoints, (res: any) => { if (res.commandHash !== undefined) { markers.forEach((marker: TemporaryUnitMarker) => { marker.setCommandHash(res.commandHash); @@ -920,14 +919,14 @@ export class UnitsManager { return false; } spawnPoints = units.reduce((points: number, unit: UnitSpawnTable) => {return points + aircraftDatabase.getSpawnPointsByName(unit.unitType)}, 0); - spawnFunction = () => spawnAircrafts(units, coalition, airbase, country, immediate, spawnPoints, callback); + spawnFunction = () => getApp().getServerManager().spawnAircrafts(units, coalition, airbase, country, immediate, spawnPoints, callback); } else if (category === "Helicopter") { if (airbase == "" && spawnsRestricted) { (getApp().getPopupsManager().get("infoPopup") as Popup).setText("Helicopters can be air spawned during the SETUP phase only"); return false; } spawnPoints = units.reduce((points: number, unit: UnitSpawnTable) => {return points + helicopterDatabase.getSpawnPointsByName(unit.unitType)}, 0); - spawnFunction = () => spawnHelicopters(units, coalition, airbase, country, immediate, spawnPoints, callback); + spawnFunction = () => getApp().getServerManager().spawnHelicopters(units, coalition, airbase, country, immediate, spawnPoints, callback); } else if (category === "GroundUnit") { if (spawnsRestricted) { @@ -935,7 +934,7 @@ export class UnitsManager { return false; } spawnPoints = units.reduce((points: number, unit: UnitSpawnTable) => {return points + groundUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0); - spawnFunction = () => spawnGroundUnits(units, coalition, country, immediate, spawnPoints, callback); + spawnFunction = () => getApp().getServerManager().spawnGroundUnits(units, coalition, country, immediate, spawnPoints, callback); } else if (category === "NavyUnit") { if (spawnsRestricted) { @@ -943,7 +942,7 @@ export class UnitsManager { return false; } spawnPoints = units.reduce((points: number, unit: UnitSpawnTable) => {return points + navyUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0); - spawnFunction = () => spawnNavyUnits(units, coalition, country, immediate, spawnPoints, callback); + spawnFunction = () => getApp().getServerManager().spawnNavyUnits(units, coalition, country, immediate, spawnPoints, callback); } if (spawnPoints <= getApp().getMissionManager().getAvailableSpawnPoints()) {