mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
First commit
This commit is contained in:
parent
a338e5fa26
commit
4d863bb894
@ -4,7 +4,7 @@ import { Unit } from "../unit/unit";
|
||||
|
||||
export class UnitDataTable extends Panel {
|
||||
constructor(id: string) {
|
||||
super(id);
|
||||
super( id );
|
||||
this.hide();
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import { SVGInjector } from "@tanem/svg-injector";
|
||||
import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "./constants/constants";
|
||||
import { ServerStatusPanel } from "./panels/serverstatuspanel";
|
||||
import { WeaponsManager } from "./weapon/weaponsmanager";
|
||||
import { IndexApp } from "./indexapp";
|
||||
|
||||
var map: Map;
|
||||
|
||||
@ -90,6 +91,32 @@ function setup() {
|
||||
|
||||
/* Load the config file */
|
||||
getConfig(readConfig);
|
||||
|
||||
/*
|
||||
This is done like this for now as a way to make it work in the new and old world.
|
||||
Over time/at some point, we'll need to start migrating the pre-existing code to an "app" format
|
||||
*/
|
||||
|
||||
const indexApp = new IndexApp({
|
||||
"featureSwitches": featureSwitches,
|
||||
"map": map,
|
||||
"missionHandler": missionHandler,
|
||||
"panels": {
|
||||
"connectionStatus": connectionStatusPanel,
|
||||
"hotgroup": hotgroupPanel,
|
||||
"infoPopup": infoPopup,
|
||||
"log": logPanel,
|
||||
"mouseInfo": mouseInfoPanel,
|
||||
"serverStatus": serverStatusPanel,
|
||||
"unitControl": unitControlPanel,
|
||||
"unitInfo": unitInfoPanel
|
||||
},
|
||||
"unitDataTable": unitDataTable,
|
||||
"unitsManager": unitsManager
|
||||
});
|
||||
|
||||
indexApp.start();
|
||||
|
||||
}
|
||||
|
||||
function readConfig(config: any) {
|
||||
|
||||
78
client/src/indexapp.ts
Normal file
78
client/src/indexapp.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import { FeatureSwitches } from "./features/featureswitches";
|
||||
import { Map } from "./map/map";
|
||||
import { MissionHandler } from "./mission/missionhandler";
|
||||
import { IOlympusApp, OlympusApp } from "./olympusapp";
|
||||
import { ConnectionStatusPanel } from "./panels/connectionstatuspanel";
|
||||
import { HotgroupPanel } from "./panels/hotgrouppanel";
|
||||
import { LogPanel } from "./panels/logpanel";
|
||||
import { MouseInfoPanel } from "./panels/mouseinfopanel";
|
||||
import { Panel } from "./panels/panel";
|
||||
import { ServerStatusPanel } from "./panels/serverstatuspanel";
|
||||
import { UnitControlPanel } from "./panels/unitcontrolpanel";
|
||||
import { UnitInfoPanel } from "./panels/unitinfopanel";
|
||||
import { PluginManager } from "./plugin/pluginmanager";
|
||||
import { PluginHelloWorld } from "./plugins/helloworld/pluginhelloworld";
|
||||
import { Popup } from "./popups/popup";
|
||||
import { UnitsManager } from "./unit/unitsmanager";
|
||||
|
||||
export interface IIndexApp extends IOlympusApp {
|
||||
"featureSwitches": FeatureSwitches,
|
||||
"map": Map,
|
||||
"missionHandler": MissionHandler,
|
||||
"panels": IIndexAppPanels,
|
||||
"unitsManager": UnitsManager
|
||||
}
|
||||
|
||||
export interface IIndexAppPanels {
|
||||
"connectionStatus": ConnectionStatusPanel,
|
||||
"hotgroup": HotgroupPanel,
|
||||
"infoPopup": Popup,
|
||||
"log": LogPanel,
|
||||
"mouseInfo": MouseInfoPanel,
|
||||
"serverStatus": ServerStatusPanel,
|
||||
"unitControl": UnitControlPanel,
|
||||
"unitInfo": UnitInfoPanel
|
||||
}
|
||||
|
||||
export class IndexApp extends OlympusApp {
|
||||
|
||||
#pluginManager!: PluginManager;
|
||||
|
||||
constructor( config:IIndexApp ) {
|
||||
|
||||
super( config );
|
||||
|
||||
// this.setMap( config.map );
|
||||
|
||||
// Panels
|
||||
this.getPanelsManager().add( "connectionStatus", config.panels.connectionStatus );
|
||||
this.getPanelsManager().add( "hotgroup", config.panels.hotgroup );
|
||||
this.getPanelsManager().add( "log", config.panels.log );
|
||||
this.getPanelsManager().add( "mouseInfo", config.panels.mouseInfo );
|
||||
this.getPanelsManager().add( "serverStatus", config.panels.serverStatus );
|
||||
this.getPanelsManager().add( "unitControl", config.panels.unitControl );
|
||||
this.getPanelsManager().add( "unitInfo", config.panels.unitInfo );
|
||||
|
||||
// Popup
|
||||
this.getPanelsManager().add( "unitPopup", config.panels.infoPopup );
|
||||
|
||||
// Retrofitting
|
||||
Object.values( this.getPanelsManager().getAll() ).forEach( ( panel:Panel ) => {
|
||||
panel.setOlympusApp( this );
|
||||
});
|
||||
|
||||
// Plugins
|
||||
this.#pluginManager = new PluginManager( this );
|
||||
|
||||
// Manual loading for now
|
||||
this.#pluginManager.add( "helloWorld", new PluginHelloWorld( this ) );
|
||||
}
|
||||
|
||||
|
||||
start() {
|
||||
|
||||
super.start();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -12,7 +12,7 @@ import { DestinationPreviewMarker } from "./destinationpreviewmarker";
|
||||
import { TemporaryUnitMarker } from "./temporaryunitmarker";
|
||||
import { ClickableMiniMap } from "./clickableminimap";
|
||||
import { SVGInjector } from '@tanem/svg-injector'
|
||||
import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTootlips, MOVE_UNIT, SHOW_CONTACT_LINES, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, visibilityControlsTypes, SHOW_UNIT_LABELS } from "../constants/constants";
|
||||
import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTooltips, MOVE_UNIT, SHOW_CONTACT_LINES, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, visibilityControlsTypes, SHOW_UNIT_LABELS } from "../constants/constants";
|
||||
import { TargetMarker } from "./targetmarker";
|
||||
import { CoalitionArea } from "./coalitionarea";
|
||||
import { CoalitionAreaContextMenu } from "../controls/coalitionareacontextmenu";
|
||||
@ -20,7 +20,7 @@ import { DrawingCursor } from "./drawingcursor";
|
||||
|
||||
L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect);
|
||||
|
||||
// TODO would be nice to convert to ts
|
||||
// TODO would be nice to convert to ts - yes
|
||||
require("../../public/javascripts/leaflet.nauticscale.js")
|
||||
require("../../public/javascripts/L.Path.Drag.js")
|
||||
|
||||
|
||||
67
client/src/olympusapp.ts
Normal file
67
client/src/olympusapp.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { UnitDataTable } from "./atc/unitdatatable";
|
||||
import { FeatureSwitches } from "./features/featureswitches";
|
||||
import { Map } from "./map/map";
|
||||
import { MissionHandler } from "./mission/missionhandler";
|
||||
import { PanelsManager } from "./panels/panelsmanager";
|
||||
import { UnitsManager } from "./unit/unitsmanager";
|
||||
|
||||
export interface IOlympusApp {
|
||||
featureSwitches: FeatureSwitches;
|
||||
missionHandler: MissionHandler;
|
||||
unitDataTable: UnitDataTable;
|
||||
unitsManager: UnitsManager;
|
||||
}
|
||||
|
||||
export abstract class OlympusApp {
|
||||
|
||||
#featureSwitches: FeatureSwitches;
|
||||
#map!: Map;
|
||||
#missionHandler: MissionHandler;
|
||||
#panelsManager: PanelsManager = new PanelsManager( this );
|
||||
#unitDataTable: UnitDataTable;
|
||||
#unitsManager: UnitsManager;
|
||||
|
||||
constructor( config:IOlympusApp ) {
|
||||
|
||||
this.#featureSwitches = config.featureSwitches;
|
||||
this.#missionHandler = config.missionHandler;
|
||||
this.#unitDataTable = config.unitDataTable;
|
||||
this.#unitsManager = config.unitsManager;
|
||||
|
||||
}
|
||||
|
||||
getFeatureSwitches() {
|
||||
return this.#featureSwitches;
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.#map;
|
||||
}
|
||||
|
||||
getPanelsManager() {
|
||||
return this.#panelsManager;
|
||||
}
|
||||
|
||||
getUnitDataTable() {
|
||||
return this.#unitDataTable;
|
||||
}
|
||||
|
||||
getUnitsManager() {
|
||||
return this.#unitsManager;
|
||||
}
|
||||
|
||||
getWeaponsManager() {
|
||||
return this.getWeaponsManager;
|
||||
}
|
||||
|
||||
setMap( map:Map ) {
|
||||
this.#map = map;
|
||||
}
|
||||
|
||||
start() {
|
||||
|
||||
// Start the app
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
10
client/src/other/eventsmanager.ts
Normal file
10
client/src/other/eventsmanager.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { OlympusApp } from "../olympusapp";
|
||||
import { Manager } from "./manager";
|
||||
|
||||
export abstract class EventsManager extends Manager {
|
||||
|
||||
constructor( olympusApp:OlympusApp ) {
|
||||
super( olympusApp );
|
||||
}
|
||||
|
||||
}
|
||||
52
client/src/other/manager.ts
Normal file
52
client/src/other/manager.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { OlympusApp } from "../olympusapp";
|
||||
|
||||
export interface IManager {
|
||||
add:CallableFunction;
|
||||
}
|
||||
|
||||
export abstract class Manager {
|
||||
|
||||
#items: {[key:string]: any } = {};
|
||||
#olympusApp: OlympusApp;
|
||||
|
||||
constructor( olympusApp:OlympusApp ) {
|
||||
|
||||
this.#olympusApp = olympusApp;
|
||||
|
||||
}
|
||||
|
||||
add( name:string, item:any ) {
|
||||
|
||||
const regex = new RegExp( "^[a-z][a-z0-9]{2,}$", "i" );
|
||||
|
||||
if ( regex.test( name ) === false ) {
|
||||
throw new Error( `Item name "${name}" does not match regex: ${regex.toString()}.` );
|
||||
}
|
||||
|
||||
if ( this.#items.hasOwnProperty( name ) ) {
|
||||
throw new Error( `Item with name "${name}" already exists.` );
|
||||
}
|
||||
|
||||
this.#items[ name ] = item;
|
||||
|
||||
}
|
||||
|
||||
get( name:string ) {
|
||||
|
||||
if ( this.#items.hasOwnProperty( name ) ) {
|
||||
return this.#items[ name ];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getAll() {
|
||||
return this.#items;
|
||||
}
|
||||
|
||||
getOlympusApp() {
|
||||
return this.#olympusApp;
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@ import { Panel } from "./panel";
|
||||
|
||||
export class ConnectionStatusPanel extends Panel {
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
super( ID );
|
||||
}
|
||||
|
||||
update(connected: boolean) {
|
||||
|
||||
@ -4,7 +4,7 @@ import { Panel } from "./panel";
|
||||
|
||||
export class HotgroupPanel extends Panel {
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
super( ID );
|
||||
document.addEventListener("unitDeath", () => this.refreshHotgroups());
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ export class LogPanel extends Panel {
|
||||
#logs: {[key: string]: string} = {};
|
||||
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
super( ID );
|
||||
|
||||
document.addEventListener("toggleLogPanel", () => {
|
||||
this.getElement().classList.toggle("open");
|
||||
|
||||
@ -13,7 +13,7 @@ export class MouseInfoPanel extends Panel {
|
||||
#measureBox: HTMLElement;
|
||||
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
super( ID );
|
||||
|
||||
this.#measureIcon = new Icon({ iconUrl: 'resources/theme/images/icons/pin.svg', iconAnchor: [16, 32] });
|
||||
this.#measureMarker = new Marker([0, 0], { icon: this.#measureIcon, interactive: false });
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
export class Panel {
|
||||
import { OlympusApp } from "../olympusapp";
|
||||
import { PanelEventsManager } from "./paneleventsmanager";
|
||||
|
||||
export abstract class Panel {
|
||||
|
||||
#element: HTMLElement
|
||||
#visible: boolean = true;
|
||||
#eventsManager!: PanelEventsManager;
|
||||
#olympusApp!: OlympusApp;
|
||||
|
||||
constructor(ID: string) {
|
||||
this.#element = <HTMLElement>document.getElementById(ID);
|
||||
@ -8,17 +13,17 @@ export class Panel {
|
||||
|
||||
show() {
|
||||
this.#element.classList.toggle("hide", false);
|
||||
this.#visible = true;
|
||||
this.getEventsManager()?.trigger( "show", {} );
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.#element.classList.toggle("hide", true);
|
||||
this.#visible = false;
|
||||
this.getEventsManager()?.trigger( "hide", {} );
|
||||
}
|
||||
|
||||
toggle() {
|
||||
// Simple way to track if currently visible
|
||||
if (this.#visible)
|
||||
if (this.getVisible())
|
||||
this.hide();
|
||||
else
|
||||
this.show();
|
||||
@ -29,6 +34,20 @@ export class Panel {
|
||||
}
|
||||
|
||||
getVisible(){
|
||||
return this.#visible;
|
||||
return (!this.getElement().classList.contains( "hide" ) );
|
||||
}
|
||||
|
||||
getEventsManager() {
|
||||
return this.#eventsManager;
|
||||
}
|
||||
|
||||
getOlympusApp() {
|
||||
return this.#olympusApp;
|
||||
}
|
||||
|
||||
setOlympusApp( olympusApp:OlympusApp ) {
|
||||
this.#olympusApp = olympusApp;
|
||||
this.#eventsManager = new PanelEventsManager( this.getOlympusApp() );
|
||||
}
|
||||
|
||||
}
|
||||
50
client/src/panels/paneleventsmanager.ts
Normal file
50
client/src/panels/paneleventsmanager.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { OlympusApp } from "../olympusapp";
|
||||
import { EventsManager } from "../other/eventsmanager";
|
||||
|
||||
interface IListener {
|
||||
callback: CallableFunction;
|
||||
name?: string
|
||||
}
|
||||
|
||||
export class PanelEventsManager extends EventsManager {
|
||||
|
||||
constructor( olympusApp:OlympusApp ) {
|
||||
|
||||
super( olympusApp );
|
||||
|
||||
this.add( "hide", [] );
|
||||
this.add( "show", [] );
|
||||
|
||||
}
|
||||
|
||||
on( eventName:string, listener:IListener ) {
|
||||
|
||||
const event = this.get( eventName );
|
||||
|
||||
if ( !event ) {
|
||||
throw new Error( `Event name "${eventName}" is not valid.` );
|
||||
}
|
||||
|
||||
this.get( eventName ).push({
|
||||
"callback": listener.callback
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
trigger( eventName:string, contextData:object ) {
|
||||
|
||||
const listeners = this.get( eventName );
|
||||
|
||||
if ( listeners ) {
|
||||
|
||||
listeners.forEach( ( listener:IListener ) => {
|
||||
|
||||
listener.callback( contextData );
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
17
client/src/panels/panelsmanager.ts
Normal file
17
client/src/panels/panelsmanager.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { OlympusApp } from "../olympusapp";
|
||||
import { Manager } from "../other/manager";
|
||||
import { Panel } from "./panel";
|
||||
|
||||
export class PanelsManager extends Manager {
|
||||
|
||||
#panels: { [key:string]: Panel } = {}
|
||||
|
||||
constructor( olympusApp:OlympusApp ) {
|
||||
super( olympusApp );
|
||||
}
|
||||
|
||||
get( name:string ): Panel {
|
||||
return super.get( name );
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@ import { Panel } from "./panel";
|
||||
|
||||
export class ServerStatusPanel extends Panel {
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
super( ID );
|
||||
}
|
||||
|
||||
update(frameRate: number, load: number) {
|
||||
|
||||
@ -26,7 +26,7 @@ export class UnitControlPanel extends Panel {
|
||||
#selectedUnitsTypes: string[] = [];
|
||||
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
super( ID );
|
||||
|
||||
/* Unit control sliders */
|
||||
this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => { getUnitsManager().selectedUnitsSetAltitude(ftToM(value)); });
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { getUnitsManager } from "..";
|
||||
import { Ammo } from "../@types/unit";
|
||||
import { ConvertDDToDMS, rad2deg } from "../other/utils";
|
||||
import { aircraftDatabase } from "../unit/aircraftdatabase";
|
||||
import { Unit } from "../unit/unit";
|
||||
import { Panel } from "./panel";
|
||||
@ -23,7 +21,7 @@ export class UnitInfoPanel extends Panel {
|
||||
#unitName: HTMLElement;
|
||||
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
super( ID );
|
||||
|
||||
this.#altitude = (this.getElement().querySelector("#altitude")) as HTMLElement;
|
||||
this.#currentTask = (this.getElement().querySelector("#current-task")) as HTMLElement;
|
||||
|
||||
32
client/src/plugin/plugin.ts
Normal file
32
client/src/plugin/plugin.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { OlympusApp } from "../olympusapp";
|
||||
|
||||
export interface PluginInterface {
|
||||
}
|
||||
|
||||
export abstract class Plugin {
|
||||
|
||||
#olympusApp!:OlympusApp;
|
||||
protected name = "";
|
||||
|
||||
constructor( olympusApp:OlympusApp, pluginName:string ) {
|
||||
|
||||
const regex = "^[a-zA-Z][a-zA-Z\d]{4,}"
|
||||
|
||||
if ( new RegExp( regex ).test( pluginName ) === false ) {
|
||||
throw new Error( `Plugin names must match regex: ${regex}` );
|
||||
}
|
||||
|
||||
this.name = pluginName;
|
||||
this.#olympusApp = olympusApp;
|
||||
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
getOlympusApp() {
|
||||
return this.#olympusApp;
|
||||
}
|
||||
|
||||
}
|
||||
13
client/src/plugin/pluginmanager.ts
Normal file
13
client/src/plugin/pluginmanager.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { OlympusApp } from "../olympusapp";
|
||||
import { Manager } from "../other/manager";
|
||||
|
||||
|
||||
export class PluginManager extends Manager {
|
||||
|
||||
constructor( olympusApp:OlympusApp ) {
|
||||
|
||||
super( olympusApp );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
6
client/src/plugins/helloworld/plugin.json
Normal file
6
client/src/plugins/helloworld/plugin.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"author": "J. R. Hartley",
|
||||
"exportedClassName": "PluginHelloWorld",
|
||||
"name": "Hello World",
|
||||
"version": "1.2.3"
|
||||
}
|
||||
29
client/src/plugins/helloworld/pluginhelloworld.ts
Normal file
29
client/src/plugins/helloworld/pluginhelloworld.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { OlympusApp } from "../../olympusapp";
|
||||
import { Plugin, PluginInterface } from "../../plugin/plugin";
|
||||
|
||||
|
||||
export class PluginHelloWorld extends Plugin implements PluginInterface {
|
||||
|
||||
constructor( olympusApp:OlympusApp ) {
|
||||
|
||||
super( olympusApp, "HelloWorld" );
|
||||
|
||||
const panel = this.getOlympusApp().getPanelsManager().get( "unitControl" );
|
||||
const em = panel.getEventsManager();
|
||||
|
||||
em.on( "show", {
|
||||
"callback": () => {
|
||||
console.log( "Showing unit control panel" );
|
||||
}
|
||||
});
|
||||
|
||||
em.on( "hide", {
|
||||
"callback": () => {
|
||||
console.log( "Hiding unit control panel" );
|
||||
}
|
||||
});
|
||||
|
||||
//const tpl = new ejs
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,11 @@
|
||||
import { Panel } from "../panels/panel";
|
||||
|
||||
export class Popup extends Panel {
|
||||
|
||||
constructor( elementId:string ) {
|
||||
super( elementId );
|
||||
}
|
||||
|
||||
#fadeTime: number = 2000; // Milliseconds
|
||||
#hideTimer: number | undefined = undefined;
|
||||
#visibilityTimer: number | undefined = undefined;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user