mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Merge pull request #143 from Pax1601/76-add-configuration-file-for-server-properties
Added configuration file to set address and port
This commit is contained in:
commit
ebb410a192
@ -2,6 +2,7 @@ var express = require('express');
|
||||
var path = require('path');
|
||||
var cookieParser = require('cookie-parser');
|
||||
var logger = require('morgan');
|
||||
var fs = require('fs');
|
||||
|
||||
var indexRouter = require('./routes/index');
|
||||
var uikitRouter = require('./routes/uikit');
|
||||
@ -21,12 +22,14 @@ app.use('/uikit', uikitRouter);
|
||||
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
let rawdata = fs.readFileSync('../olympus.json');
|
||||
let config = JSON.parse(rawdata);
|
||||
app.get('/config', (req, res) => res.send(config));
|
||||
|
||||
module.exports = app;
|
||||
|
||||
const DemoDataGenerator = require('./demo.js');
|
||||
|
||||
var demoDataGenerator = new DemoDataGenerator(10);
|
||||
|
||||
app.get('/demo/units', (req, res) => demoDataGenerator.units(req, res));
|
||||
app.get('/demo/logs', (req, res) => demoDataGenerator.logs(req, res));
|
||||
app.get('/demo/bullseyes', (req, res) => demoDataGenerator.bullseyes(req, res));
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "DCSOlympus",
|
||||
"node-main": "./bin/www",
|
||||
"main": "http://localhost:3000",
|
||||
"version": "0.1.0-alpha",
|
||||
"version": "0.1.1-alpha",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"copy": "copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet.css",
|
||||
|
||||
@ -9,7 +9,7 @@ import { AIC } from "./aic/aic";
|
||||
import { ATC } from "./atc/atc";
|
||||
import { FeatureSwitches } from "./featureswitches";
|
||||
import { LogPanel } from "./panels/logpanel";
|
||||
import { getAirbases, getBullseye as getBullseyes, getMission, getUnits, toggleDemoEnabled } from "./server/server";
|
||||
import { getAirbases, getBullseye as getBullseyes, getConfig, getMission, getUnits, setAddress, toggleDemoEnabled } from "./server/server";
|
||||
import { UnitDataTable } from "./units/unitdatatable";
|
||||
|
||||
var map: Map;
|
||||
@ -69,16 +69,33 @@ function setup() {
|
||||
/* Setup event handlers */
|
||||
setupEvents();
|
||||
|
||||
/* On the first connection, force request of full data */
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {getMissionData()?.update(data)});
|
||||
getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */);
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
startPeriodicUpdate();
|
||||
getConfig(readConfig)
|
||||
}
|
||||
|
||||
function readConfig(config: any)
|
||||
{
|
||||
if (config && config["server"] != undefined && config["server"]["address"] != undefined && config["server"]["port"] != undefined)
|
||||
{
|
||||
const address = config["server"]["address"];
|
||||
const port = config["server"]["port"];
|
||||
if ((typeof address === 'string' || address instanceof String) && typeof port == 'number')
|
||||
{
|
||||
setAddress(<string>address, <number>port);
|
||||
}
|
||||
|
||||
/* On the first connection, force request of full data */
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {getMissionData()?.update(data)});
|
||||
getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */);
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
startPeriodicUpdate();
|
||||
}
|
||||
else {
|
||||
throw new Error('Could not read configuration file!');
|
||||
}
|
||||
}
|
||||
|
||||
function startPeriodicUpdate() {
|
||||
requestUpdate();
|
||||
|
||||
@ -87,7 +87,7 @@ export class UnitControlPanel extends Panel {
|
||||
}
|
||||
|
||||
var button = document.createElement("button");
|
||||
var callsign = aircraftDatabase.getByName(unit.getBaseData().unitName)?.label || "";
|
||||
var callsign = unit.getBaseData().unitName || "";
|
||||
|
||||
button.innerText = unit.getBaseData().unitName;
|
||||
button.setAttribute("data-short-label", database?.getByName(unit.getBaseData().name)?.shortLabel || "");
|
||||
|
||||
@ -2,9 +2,8 @@ import * as L from 'leaflet'
|
||||
import { setConnected } from '..';
|
||||
import { SpawnOptions } from '../controls/mapcontextmenu';
|
||||
|
||||
/* Edit here to change server address */
|
||||
const REST_ADDRESS = "http://localhost:30000/olympus";
|
||||
const DEMO_ADDRESS = "http://localhost:3000/demo";
|
||||
var REST_ADDRESS = "http://localhost:30000/olympus";
|
||||
var DEMO_ADDRESS = window.location.href + "demo";
|
||||
const UNITS_URI = "units";
|
||||
const LOGS_URI = "logs";
|
||||
const AIRBASES_URI = "airbases";
|
||||
@ -45,6 +44,25 @@ export function POST(request: object, callback: CallableFunction){
|
||||
xhr.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);
|
||||
lastUpdateTime = parseInt(data.time);
|
||||
};
|
||||
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);
|
||||
}
|
||||
|
||||
@ -573,6 +573,15 @@ export class GroundUnit extends Unit {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
getMarkerHTML() {
|
||||
var role = groundUnitsDatabase.getByName(this.getBaseData().name)?.loadouts[0].roles[0];
|
||||
return `<div class="unit" data-object="unit-${this.getMarkerCategory()}" data-coalition="${this.getMissionData().coalition}">
|
||||
<div class="unit-selected-spotlight"></div>
|
||||
<div class="unit-marker"></div>
|
||||
<div class="unit-short-label">${role?.substring(0, 1)?.toUpperCase() || ""}</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
getMarkerCategory()
|
||||
{
|
||||
// TODO this is very messy
|
||||
|
||||
@ -10,13 +10,13 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;600;700;800&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z4L2TC3YX0"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-Z4L2TC3YX0');
|
||||
</script>
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z4L2TC3YX0"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-Z4L2TC3YX0');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<div class="ol-select-options">
|
||||
<div id="olympus-toolbar-summary">
|
||||
<h3>Olympus</h3>
|
||||
<div class="accent-green app-version-number">v0.1.0</div>
|
||||
<div class="accent-green app-version-number">v0.1.1</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://www.discord.com" target="_blank">Discord</a>
|
||||
|
||||
@ -18,6 +18,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
|
||||
;Source: "..\scripts\OlympusExport.lua"; DestDir: "{app}\Scripts"; Flags: ignoreversion
|
||||
;Source: "..\scripts\OlympusPatcher.exe"; DestDir: "{app}\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts\Hooks"; Flags: ignoreversion
|
||||
Source: "..\olympus.json"; DestDir: "{app}\Mods\Services\Olympus"; Flags: onlyifdoesntexist
|
||||
Source: "..\scripts\OlympusCommand.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\unitPayloads.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
;Source: "..\scripts\OlympusMission.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
|
||||
@ -15,7 +15,7 @@ declare_plugin(self_ID,
|
||||
shortName = "Olympus",
|
||||
fileMenuName = "Olympus",
|
||||
|
||||
version = "0.1.0-alpha",
|
||||
version = "0.1.1-alpha",
|
||||
state = "installed",
|
||||
developerName= "DCS Refugees 767 squadron",
|
||||
info = _("DCS Olympus is a mod for DCS World. It allows users to spawn, control, task, group, and remove units from a DCS World server using a real-time map interface, similarly to Real Time Strategy games. The user interface also provides useful informations units, like loadouts, fuel, tasking, and so on. In the future, more features for DCS World GCI and JTAC will be available."),
|
||||
|
||||
6
olympus.json
Normal file
6
olympus.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"server": {
|
||||
"address": "localhost",
|
||||
"port": 30000
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
local version = 'v0.1.0-alpha'
|
||||
|
||||
Olympus = {}
|
||||
Olympus.OlympusDLL = nil
|
||||
Olympus.cppRESTDLL = nil
|
||||
Olympus.DLLsloaded = false
|
||||
Olympus.OlympusModPath = os.getenv('DCSOLYMPUS_PATH')..'\\bin\\'
|
||||
|
||||
log.write('Olympus.EXPORT.LUA', log.INFO, 'Executing OlympusExport.lua')
|
||||
|
||||
function Olympus.loadDLLs()
|
||||
-- Add the .dll paths
|
||||
package.cpath = package.cpath..';'..Olympus.OlympusModPath..'?.dll;'
|
||||
|
||||
local status
|
||||
log.write('Olympus.HOOKS.LUA', log.INFO, 'Loading olympus.dll from ['..Olympus.OlympusModPath..']')
|
||||
status, Olympus.OlympusDLL = pcall(require, 'olympus')
|
||||
if status then
|
||||
log.write('Olympus.HOOKS.LUA', log.INFO, 'olympus.dll loaded successfully')
|
||||
return true
|
||||
else
|
||||
log.write('Olympus.HOOKS.LUA', log.ERROR, 'Error loading olympus.dll: '..Olympus.OlympusDLL)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
if isOlympusModuleInitialized~=true then
|
||||
local OlympusName = 'Olympus ' .. version .. ' C++ module';
|
||||
isOlympusModuleInitialized=true;
|
||||
Olympus.DLLsloaded = Olympus.loadDLLs()
|
||||
if Olympus.DLLsloaded then
|
||||
log.write('Olympus.EXPORT.LUA', log.INFO, OlympusName..' successfully loaded.')
|
||||
else
|
||||
log.write('Olympus.EXPORT.LUA', log.ERROR, 'Failed to load '..OlympusName)
|
||||
end
|
||||
else
|
||||
log.write('Olympus.EXPORT.LUA', log.INFO, 'olympus.dll already initialized')
|
||||
end
|
||||
end
|
||||
@ -1,135 +0,0 @@
|
||||
local version = 'v0.1.0-alpha'
|
||||
|
||||
Olympus = {}
|
||||
Olympus.groupIndex = 0
|
||||
Olympus.groupStep = 40
|
||||
|
||||
function Olympus.notify(message, displayFor)
|
||||
trigger.action.outText(message, displayFor)
|
||||
end
|
||||
|
||||
function Olympus.setMissionData(arg, time)
|
||||
local missionData = {}
|
||||
|
||||
-- Bullseye data
|
||||
local bullseyes = {}
|
||||
for i = 0, 2 do
|
||||
local bullseyeVec3 = coalition.getMainRefPoint(i)
|
||||
local bullseyeLatitude, bullseyeLongitude, bullseyeAltitude = coord.LOtoLL(bullseyeVec3)
|
||||
bullseyes[i] = {}
|
||||
bullseyes[i]["latitude"] = bullseyeLatitude
|
||||
bullseyes[i]["longitude"] = bullseyeLongitude
|
||||
end
|
||||
|
||||
-- Units tactical data
|
||||
local unitsData = {}
|
||||
|
||||
local startIndex = Olympus.groupIndex
|
||||
local endIndex = startIndex + Olympus.groupStep
|
||||
local index = 0
|
||||
for groupName, gp in pairs(mist.DBs.groupsByName) do
|
||||
index = index + 1
|
||||
if index > startIndex then
|
||||
if groupName ~= nil then
|
||||
local group = Group.getByName(groupName)
|
||||
if group ~= nil then
|
||||
local controller = group:getController()
|
||||
for index, unit in pairs(group:getUnits()) do
|
||||
local table = {}
|
||||
table["targets"] = {}
|
||||
table["targets"]["visual"] = controller:getDetectedTargets(1)
|
||||
table["targets"]["radar"] = controller:getDetectedTargets(4)
|
||||
table["targets"]["rwr"] = controller:getDetectedTargets(16)
|
||||
table["targets"]["other"] = controller:getDetectedTargets(2, 8, 32)
|
||||
|
||||
table["hasTask"] = controller:hasTask()
|
||||
|
||||
table["ammo"] = unit:getAmmo()
|
||||
table["fuel"] = unit:getFuel()
|
||||
table["life"] = unit:getLife() / unit:getLife0()
|
||||
unitsData[unit:getObjectID()] = table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if index >= endIndex then
|
||||
break
|
||||
end
|
||||
end
|
||||
if index ~= endIndex then
|
||||
Olympus.groupIndex = 0
|
||||
else
|
||||
Olympus.groupIndex = endIndex
|
||||
end
|
||||
|
||||
-- Airbases data
|
||||
local base = world.getAirbases()
|
||||
local airbases = {}
|
||||
for i = 1, #base do
|
||||
local info = {}
|
||||
local latitude, longitude, altitude = coord.LOtoLL(Airbase.getPoint(base[i]))
|
||||
info["callsign"] = Airbase.getCallsign(base[i])
|
||||
local coalitionID = Airbase.getCoalition(base[i])
|
||||
if coalitionID == 0 then
|
||||
info["coalition"] = "neutral"
|
||||
elseif coalitionID == 1 then
|
||||
info["coalition"] = "red"
|
||||
else
|
||||
info["coalition"] = "blue"
|
||||
end
|
||||
info["latitude"] = latitude
|
||||
info["longitude"] = longitude
|
||||
if Airbase.getUnit(base[i]) then
|
||||
info["unitId"] = Airbase.getUnit(base[i]):getID()
|
||||
end
|
||||
airbases[i] = info
|
||||
end
|
||||
|
||||
local mission = {}
|
||||
mission.theatre = env.mission.theatre
|
||||
|
||||
-- Assemble missionData table
|
||||
missionData["bullseyes"] = bullseyes
|
||||
missionData["unitsData"] = unitsData
|
||||
missionData["airbases"] = airbases
|
||||
missionData["mission"] = mission
|
||||
|
||||
local command = "Olympus.missionData = " .. Olympus.serializeTable(missionData) .. "\n" .. "Olympus.OlympusDLL.setMissionData()"
|
||||
net.dostring_in("export", command)
|
||||
return time + 1
|
||||
end
|
||||
|
||||
function Olympus.serializeTable(val, name, skipnewlines, depth)
|
||||
skipnewlines = skipnewlines or false
|
||||
depth = depth or 0
|
||||
|
||||
local tmp = string.rep(" ", depth)
|
||||
if name then
|
||||
if type(name) == "number" then
|
||||
tmp = tmp .. "[" .. name .. "]" .. " = "
|
||||
else
|
||||
tmp = tmp .. name .. " = "
|
||||
end
|
||||
end
|
||||
|
||||
if type(val) == "table" then
|
||||
tmp = tmp .. "{" .. (not skipnewlines and "\n" or "")
|
||||
for k, v in pairs(val) do
|
||||
tmp = tmp .. Olympus.serializeTable(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and "\n" or "")
|
||||
end
|
||||
tmp = tmp .. string.rep(" ", depth) .. "}"
|
||||
elseif type(val) == "number" then
|
||||
tmp = tmp .. tostring(val)
|
||||
elseif type(val) == "string" then
|
||||
tmp = tmp .. string.format("%q", val)
|
||||
elseif type(val) == "boolean" then
|
||||
tmp = tmp .. (val and "true" or "false")
|
||||
else
|
||||
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
|
||||
end
|
||||
|
||||
return tmp
|
||||
end
|
||||
|
||||
timer.scheduleFunction(Olympus.setMissionData, {}, timer.getTime() + 1)
|
||||
Olympus.notify("OlympusMission " .. version .. " script loaded correctly", 10)
|
||||
Binary file not shown.
@ -1,42 +0,0 @@
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
START_STRING = "-- Olympus START\n"
|
||||
END_STRING = "-- Olympus END\n"
|
||||
EXPORT_STRING = "local Olympuslfs=require('lfs');dofile(Olympuslfs.writedir()..'Scripts/OlympusExport.lua')\n"
|
||||
|
||||
def main(flag):
|
||||
if flag == "-i":
|
||||
try:
|
||||
with open("Export.lua", "r") as f:
|
||||
shutil.copyfile("Export.lua", "Export.lua.bak")
|
||||
lines = f.readlines()
|
||||
if START_STRING in lines:
|
||||
return
|
||||
except FileNotFoundError:
|
||||
print('File does not exist')
|
||||
|
||||
with open("Export.lua", "a") as f:
|
||||
f.writelines(["\n", START_STRING, EXPORT_STRING, END_STRING, "\n"])
|
||||
elif flag == "-u":
|
||||
try:
|
||||
with open("Export.lua", "r") as f:
|
||||
shutil.copyfile("Export.lua", "Export.lua.bak")
|
||||
lines = f.readlines()
|
||||
except FileNotFoundError:
|
||||
print('File does not exist')
|
||||
|
||||
with open("Export.lua", "w") as f:
|
||||
block = False
|
||||
for line in lines:
|
||||
if line == START_STRING:
|
||||
block = True
|
||||
|
||||
if not block:
|
||||
f.write(line)
|
||||
|
||||
if line == END_STRING:
|
||||
block = False
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1])
|
||||
@ -1,44 +0,0 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['OlympusPatcher.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='OlympusPatcher',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
@ -179,7 +179,35 @@ void Server::handle_put(http_request request)
|
||||
|
||||
void Server::task()
|
||||
{
|
||||
http_listener listener(wstring(REST_ADDRESS) + L"/" + wstring(REST_URI));
|
||||
wstring address = wstring(REST_ADDRESS);
|
||||
wstring modLocation;
|
||||
char* buf = nullptr;
|
||||
size_t sz = 0;
|
||||
if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr)
|
||||
{
|
||||
std::ifstream ifstream(string(buf) + "\\olympus.json");
|
||||
std::stringstream ss;
|
||||
ss << ifstream.rdbuf();
|
||||
std::error_code errorCode;
|
||||
json::value config = json::value::parse(to_wstring(ss.str()), errorCode);
|
||||
if (config.is_object() && config.has_object_field(L"server") &&
|
||||
config[L"server"].has_string_field(L"address") && config[L"server"].has_number_field(L"port"))
|
||||
{
|
||||
address = L"http://" + config[L"server"][L"address"].as_string() + L":" + to_wstring(config[L"server"][L"port"].as_number().to_int32());
|
||||
log(L"Starting server on " + address);
|
||||
}
|
||||
else
|
||||
{
|
||||
log(L"Error reading configuration file. Starting server on " + address);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
log(L"DCSOLYMPUS_PATH environment variable is missing, starting server on " + address);
|
||||
}
|
||||
|
||||
http_listener listener(address + L"/" + wstring(REST_URI));
|
||||
|
||||
std::function<void(http_request)> handle_options = std::bind(&Server::handle_options, this, std::placeholders::_1);
|
||||
std::function<void(http_request)> handle_get = std::bind(&Server::handle_get, this, std::placeholders::_1);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user