Completed manager and moved client to common folder

This commit is contained in:
Pax1601 2023-12-20 12:33:46 +01:00
parent 603018d1ef
commit 787bf13f3c
47 changed files with 159936 additions and 199 deletions

View File

@ -1,50 +1,50 @@
/* Requires */
var express = require('express');
var path = require('path');
var logger = require('morgan');
var fs = require('fs');
var bodyParser = require('body-parser');
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (configLocation) {
/* Requires */
var express = require('express');
var path = require('path');
var logger = require('morgan');
var fs = require('fs');
var bodyParser = require('body-parser');
const { createProxyMiddleware } = require('http-proxy-middleware');
/* Default routers */
var atcRouter = require('./routes/api/atc');
var airbasesRouter = require('./routes/api/airbases');
var elevationRouter = require('./routes/api/elevation');
var databasesRouter = require('./routes/api/databases');
var indexRouter = require('./routes/index');
var uikitRouter = require('./routes/uikit');
var usersRouter = require('./routes/users');
var resourcesRouter = require('./routes/resources');
var pluginsRouter = require('./routes/plugins');
/* Default routers */
var atcRouter = require('./routes/api/atc');
var airbasesRouter = require('./routes/api/airbases');
var elevationRouter = require('./routes/api/elevation');
var databasesRouter = require('./routes/api/databases')(path.join(path.dirname(configLocation), "..", "Mods", "Services", "Olympus", "databases"));
var indexRouter = require('./routes/index');
var uikitRouter = require('./routes/uikit');
var usersRouter = require('./routes/users');
var resourcesRouter = require('./routes/resources');
var pluginsRouter = require('./routes/plugins');
/* Load the config and create the express app */
let rawdata = fs.readFileSync('../olympus.json');
let config = JSON.parse(rawdata);
var app = express();
/* Load the config and create the express app */
let rawdata = fs.readFileSync(configLocation);
let config = JSON.parse(rawdata);
var app = express();
/* Define middleware */
app.use(logger('dev'));
app.use('/olympus', createProxyMiddleware({target: `http://${config["server"]["address"]}:${config["server"]["port"]}`, changeOrigin: true }));
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
app.use(express.static(path.join(__dirname, 'public')));
/* Define middleware */
app.use(logger('dev'));
app.use('/olympus', createProxyMiddleware({ target: `http://${config["server"]["address"]}:${config["server"]["port"]}`, changeOrigin: true }));
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
app.use(express.static(path.join(__dirname, 'public')));
/* Apply routers */
app.use('/', indexRouter);
app.use('/api/atc', atcRouter);
app.use('/api/airbases', airbasesRouter);
app.use('/api/elevation', elevationRouter);
app.use('/api/databases', databasesRouter);
app.use('/plugins', pluginsRouter)
app.use('/users', usersRouter);
app.use('/uikit', uikitRouter);
app.use('/resources', resourcesRouter);
app.set('view engine', 'ejs');
module.exports = app;
/* Apply routers */
app.use('/', indexRouter);
app.use('/api/atc', atcRouter);
app.use('/api/airbases', airbasesRouter);
app.use('/api/elevation', elevationRouter);
app.use('/api/databases', databasesRouter);
app.use('/plugins', pluginsRouter)
app.use('/users', usersRouter);
app.use('/uikit', uikitRouter);
app.use('/resources', resourcesRouter);
app.set('view engine', 'ejs');
return app;
}

View File

@ -1,5 +1,10 @@
#!/usr/bin/env node
const yargs = require('yargs');
yargs.alias('c', 'config').describe('c', 'olympus.json config location').string('rp');
args = yargs.argv;
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
console.log('\x1b[36m%s\x1b[0m', "* _____ _____ _____ ____ _ *");
console.log('\x1b[36m%s\x1b[0m', "* | __ \\ / ____|/ ____| / __ \\| | *");
@ -12,16 +17,23 @@ console.log('\x1b[36m%s\x1b[0m', "* |___/
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
console.log('\x1b[36m%s\x1b[0m', "");
console.log("Please wait while DCS Olympus Server starts up...");
console.log(`Config location: ${args["config"]}`)
var fs = require('fs');
let rawdata = fs.readFileSync('../olympus.json');
let config = JSON.parse(rawdata);
var clientPort = 3000;
if (fs.existsSync(args["config"])) {
var json = JSON.parse(fs.readFileSync(args["config"], 'utf-8'));
clientPort = json["client"]["port"];
} else {
console.log("Failed to read config, trying default port");
}
/**
* Module dependencies.
*/
var app = require('../app');
var app = require('../app')(args["config"]);
var debug = require('debug')('client:server');
var http = require('http');
@ -29,12 +41,8 @@ var http = require('http');
* Get port from environment and store in Express.
*/
var configPort = null;
if (config["client"] != undefined && config["client"]["port"] != undefined) {
configPort = config["client"]["port"];
}
var port = normalizePort(configPort || '3000');
var port = normalizePort(clientPort || '3000');
app.set('port', port);
console.log("Express server listening on port: " + port)

View File

@ -27,10 +27,10 @@ function createWindow() {
}
app.whenReady().then(() => {
const server = spawn('node', [path.join('.', 'bin', 'www')]);
const server = spawn('node', [path.join('.', 'bin', 'www'), "--config", args["config"]]);
server.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
console.log(`${data}`);
});
server.stderr.on('data', (data) => {
@ -38,7 +38,7 @@ app.whenReady().then(() => {
});
server.on('close', (code) => {
console.log(`child process exited with code ${code}`);
console.log(`Child process exited with code ${code}`);
});
createWindow()

View File

@ -1 +1 @@
CreateObject("Wscript.Shell").Run "npm run client -- --config """&WScript.Arguments(0)&"""", 1
CreateObject("Wscript.Shell").Run "npm run client -- --config """&WScript.Arguments(0)&"""", 0

View File

@ -1,4 +1,4 @@
copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet\\leaflet.css
copy .\\node_modules\\leaflet-gesture-handling\\dist\\leaflet-gesture-handling.css .\\public\\stylesheets\\leaflet\\leaflet-gesture-handling.css
copy .\\node_modules\\leaflet.nauticscale\\dist\\leaflet.nauticscale.js .\\public\\javascripts\\leaflet.nauticscale.js
copy .\\node_modules\\leaflet-path-drag\\dist\\L.Path.Drag.js .\\public\\javascripts\\L.Path.Drag.js
xcopy /S /Q /Y /F .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet\\leaflet.css
xcopy /S /Q /Y /F .\\node_modules\\leaflet-gesture-handling\\dist\\leaflet-gesture-handling.css .\\public\\stylesheets\\leaflet\\leaflet-gesture-handling.css
xcopy /S /Q /Y /F .\\node_modules\\leaflet.nauticscale\\dist\\leaflet.nauticscale.js .\\public\\javascripts\\leaflet.nauticscale.js
xcopy /S /Q /Y /F .\\node_modules\\leaflet-path-drag\\dist\\L.Path.Drag.js .\\public\\javascripts\\L.Path.Drag.js

View File

@ -1,14 +1,15 @@
{
"name": "DCSOlympus",
"version": "v1.0.4",
"version": "v{{OLYMPUS_VERSION_NUMBER}}",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "DCSOlympus",
"version": "v1.0.4",
"version": "v{{OLYMPUS_VERSION_NUMBER}}",
"dependencies": {
"appjs": "^0.0.20",
"appjs-win32": "^0.0.19",
"body-parser": "^1.20.2",
"debug": "~2.6.9",
"ejs": "^3.1.8",
@ -3782,6 +3783,17 @@
"node": ">=0.8"
}
},
"node_modules/appjs-win32": {
"version": "0.0.19",
"resolved": "https://registry.npmjs.org/appjs-win32/-/appjs-win32-0.0.19.tgz",
"integrity": "sha512-ide+/pVBbT043Zxx5CQd2R8j2UIhOs4xV17rEf335ooujHtdvWphiyC3R81UWib9vKHEOY7dNlv91J9R/a7pVw==",
"os": [
"win32"
],
"engines": {
"node": ">=0.8"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",

View File

@ -2,7 +2,7 @@
"name": "DCSOlympus",
"node-main": "./bin/www",
"main": "client.js",
"version": "v1.0.4",
"version": "v{{OLYMPUS_VERSION_NUMBER}}",
"private": true,
"scripts": {
"build": "browserify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ] && copy.bat",
@ -10,7 +10,7 @@
"emit-declarations": "tsc --project tsconfig.json --declaration --emitDeclarationOnly --outfile ./@types/olympus/index.d.ts",
"copy": "copy.bat",
"start": "node ./bin/www",
"debug": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon --ignore ./public/databases/ ./bin/www\"",
"debug": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon --ignore ./public/databases/ ./bin/www -- --config ../moc_dcs/Config/olympus.json\"",
"watch": "watchify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]",
"client": "electron ."
},

View File

@ -0,0 +1,661 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Prevents IE11 from highlighting tiles in blue */
.leaflet-tile::selection {
background: transparent;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg {
max-width: none !important;
max-height: none !important;
}
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer,
.leaflet-container .leaflet-tile {
max-width: none !important;
max-height: none !important;
width: auto;
padding: 0;
}
.leaflet-container img.leaflet-tile {
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
mix-blend-mode: plus-lighter;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
/* Fallback for FF which doesn't support pinch-zoom */
touch-action: none;
touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-container {
-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
svg.leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive,
svg.leaflet-image-layer.leaflet-interactive path {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline-offset: 1px;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
font-size: 12px;
font-size: 0.75rem;
line-height: 1.5;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover,
.leaflet-bar a:focus {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
.leaflet-touch .leaflet-bar a:first-child {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.leaflet-touch .leaflet-bar a:last-child {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
font-size: 22px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
overflow-x: hidden;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
font-size: 13px;
font-size: 1.08333em;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.8);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
line-height: 1.4;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover,
.leaflet-control-attribution a:focus {
text-decoration: underline;
}
.leaflet-attribution-flag {
display: inline !important;
vertical-align: baseline !important;
width: 1em;
height: 0.6669em;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
white-space: nowrap;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.8);
text-shadow: 1px 1px #fff;
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 24px 13px 20px;
line-height: 1.3;
font-size: 13px;
font-size: 1.08333em;
min-height: 1px;
}
.leaflet-popup-content p {
margin: 17px 0;
margin: 1.3em 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-top: -1px;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
pointer-events: auto;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
border: none;
text-align: center;
width: 24px;
height: 24px;
font: 16px/24px Tahoma, Verdana, sans-serif;
color: #757575;
text-decoration: none;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover,
.leaflet-container a.leaflet-popup-close-button:focus {
color: #585858;
}
.leaflet-popup-scrolled {
overflow: auto;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
-ms-zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-interactive {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}
/* Printing */
@media print {
/* Prevent printers from removing background-images of controls. */
.leaflet-control {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}

View File

@ -1,58 +1,60 @@
const express = require('express');
const router = express.Router();
const fs = require("fs");
const path = require("path");
module.exports = function (databasesLocation) {
const express = require('express');
const router = express.Router();
const fs = require("fs");
const path = require("path");
router.get('/:type/:name', function (req, res) {
console.log(req.params.database)
});
router.get('/:type/:name', function (req, res) {
console.log(req.params.database)
});
router.put('/save/:type/:name', function (req, res) {
var dir = path.join("./public/databases", req.params.type, "old");
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
router.put('/save/:type/:name', function (req, res) {
var dir = path.join(databasesLocation, req.params.type, "old");
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
var filepath = path.join("./public/databases", req.params.type, req.params.name + ".json");
if (fs.existsSync(filepath)) {
var newFilepath = path.join("./public/databases/", req.params.type, "old", req.params.name + ".json");
fs.copyFileSync(filepath, newFilepath);
if (fs.existsSync(newFilepath)) {
try {
var json = JSON.stringify(req.body.blueprints, null, "\t" );
fs.writeFileSync(filepath, json, 'utf8');
res.send("OK");
} catch {
var filepath = path.join(databasesLocation, req.params.type, req.params.name + ".json");
if (fs.existsSync(filepath)) {
var newFilepath = path.join(databasesLocation, req.params.type, "old", req.params.name + ".json");
fs.copyFileSync(filepath, newFilepath);
if (fs.existsSync(newFilepath)) {
try {
var json = JSON.stringify(req.body.blueprints, null, "\t");
fs.writeFileSync(filepath, json, 'utf8');
res.send("OK");
} catch {
res.status(422).send("Error");
}
} else {
res.status(422).send("Error");
}
} else {
res.status(422).send("Error");
res.status(404).send('Not found');
}
} else {
res.status(404).send('Not found');
}
});
});
router.put('/reset/:type/:name', function (req, res) {
var filepath = path.join("./public/databases", req.params.type, "default", req.params.name + ".json");
if (fs.existsSync(filepath)) {
var newFilepath = path.join("./public/databases", req.params.type, req.params.name + ".json");
fs.copyFileSync(filepath, newFilepath);
res.send("OK");
} else {
res.status(404).send('Not found');
}
});
router.put('/reset/:type/:name', function (req, res) {
var filepath = path.join(databasesLocation, req.params.type, "default", req.params.name + ".json");
if (fs.existsSync(filepath)) {
var newFilepath = path.join(databasesLocation, req.params.type, req.params.name + ".json");
fs.copyFileSync(filepath, newFilepath);
res.send("OK");
} else {
res.status(404).send('Not found');
}
});
router.put('/restore/:type/:name', function (req, res) {
var filepath = path.join("./public/databases", req.params.type, "old", req.params.name + ".json");
if (fs.existsSync(filepath)) {
var newFilepath = path.join("./public/databases", req.params.type, req.params.name + ".json");
fs.copyFileSync(filepath, newFilepath);
res.send("OK");
} else {
res.status(404).send('Not found');
}
});
router.put('/restore/:type/:name', function (req, res) {
var filepath = path.join(databasesLocation, req.params.type, "old", req.params.name + ".json");
if (fs.existsSync(filepath)) {
var newFilepath = path.join(databasesLocation, req.params.type, req.params.name + ".json");
fs.copyFileSync(filepath, newFilepath);
res.send("OK");
} else {
res.status(404).send('Not found');
}
});
module.exports = router;
return router;
}

View File

@ -1 +0,0 @@
node .\\bin\\www

1
client/server.vbs Normal file
View File

@ -0,0 +1 @@
CreateObject("Wscript.Shell").Run "npm run start -- --config """&WScript.Arguments(0)&"""", 1

View File

@ -29,7 +29,6 @@ import { ContextManager } from "./context/contextmanager";
import { Context } from "./context/context";
var VERSION = "{{OLYMPUS_VERSION_NUMBER}}";
var DEBUG = false;
export class OlympusApp {
/* Global data */

View File

@ -34,8 +34,8 @@ Source: "..\scripts\mist.lua"; DestDir: "{app}\Scripts"; Flags: ignoreversion
Source: "..\scripts\mods.lua"; DestDir: "{app}\Scripts"; Flags: ignoreversion
Source: "..\mod\*"; DestDir: "{app}\mod"; Flags: ignoreversion recursesubdirs;
Source: "..\bin\*.dll"; DestDir: "{app}\bin"; Flags: ignoreversion;
Source: "..\bin\*.dll"; DestDir: "{app}\mod\bin"; Flags: ignoreversion;
Source: "..\client\public\databases\*"; DestDir: "{app}\mod\databases"; Flags: ignoreversion recursesubdirs;
Source: "..\client\bin\*"; DestDir: "{app}\client\bin"; Flags: ignoreversion;
Source: "..\client\public\*"; DestDir: "{app}\client\public"; Flags: ignoreversion recursesubdirs;
@ -43,11 +43,16 @@ Source: "..\client\routes\*"; DestDir: "{app}\client\routes"; Flags: ignoreversi
Source: "..\client\views\*"; DestDir: "{app}\client\views"; Flags: ignoreversion recursesubdirs;
Source: "..\client\app.js"; DestDir: "{app}\client"; Flags: ignoreversion;
Source: "..\client\demo.js"; DestDir: "{app}\client"; Flags: ignoreversion;
Source: "..\client\client.js"; DestDir: "{app}\client"; Flags: ignoreversion;
Source: "..\client\package.json"; DestDir: "{app}\client"; Flags: ignoreversion;
Source: "..\client\configurator.js"; DestDir: "{app}\client"; Flags: ignoreversion;
Source: "..\client\install.bat"; DestDir: "{app}\client"; Flags: ignoreversion;
Source: "..\client\*.vbs"; DestDir: "{app}\client"; Flags: ignoreversion;
Source: "..\manager\icons\*"; DestDir: "{app}\manager\icons"; Flags: ignoreversion;
Source: "..\manager\ejs\*"; DestDir: "{app}\manager\ejs"; Flags: ignoreversion;
Source: "..\manager\javascripts\*"; DestDir: "{app}\manager\javascripts"; Flags: ignoreversion;
Source: "..\manager\stylesheets\*"; DestDir: "{app}\manager\stylesheets"; Flags: ignoreversion;
Source: "..\manager\*"; DestDir: "{app}\manager"; Flags: ignoreversion;
Source: "..\img\olympus.ico"; DestDir: "{app}\img"; Flags: ignoreversion;
@ -61,13 +66,11 @@ Source: "..\LEGAL.txt"; DestDir: "{app}"; Flags: ignoreversion;
[Run]
Filename: "{app}\client\install.bat"; Description: "Installing node.js modules, this may take some time..."; Tasks: installmodules;
Filename: "{app}\manager\install.bat"; Description: "Installing node.js modules, this may take some time..."; Tasks: installmodules;
Filename: "{app}\manager\run.vbs"; WorkingDir: "{app}\manager"; Description: "Launch the Olympus manager"; Flags: postinstall shellexec;
Filename: "{app}\manager\manager.vbs"; WorkingDir: "{app}\manager"; Description: "Launch the Olympus manager"; Flags: postinstall shellexec;
[Icons]
Name: "{userdesktop}\DCS Olympus Manager"; Filename: "{app}\manager\run.vbs"; Tasks: desktopicon; IconFilename: "{app}\img\olympus.ico";
Name: "{app}\DCS Olympus Manager"; Filename: "{app}\manager\run.vbs"; IconFilename: "{app}\img\olympus_configurator.ico";
Name: "{app}\DCS Olympus Server"; Filename: "{app}\manager\server.bat"; IconFilename: "{app}\img\olympus_server.ico";
Name: "{app}\DCS Olympus"; Filename: "{app}\manager\local.bat"; IconFilename: "{app}\img\olympus.ico";
Name: "{userdesktop}\DCS Olympus Manager"; Filename: "{app}\manager\manager.vbs"; Tasks: desktopicon; IconFilename: "{app}\img\olympus_configurator.ico";
Name: "{app}\DCS Olympus Manager"; Filename: "{app}\manager\manager.vbs"; IconFilename: "{app}\img\olympus_configurator.ico";
[UninstallDelete]
Type: filesandordirs; Name: "{app}"

View File

@ -7,38 +7,50 @@
<table class="input-table">
<tr>
<td>
<div class="label">Client port <div class="icon info" title="This is the port that will allow users to connect to Olympus and must be forwarded in your firewall."></div></div>
<input id="client-port" type='number' value="<%= typeof client !== 'undefined' ? client["port"]: "" %>" min="1023" max="65535" <%= !installed? "disabled": "" %> tabindex="<%= index %>">
<span id="client-port-error" class="error"></span>
<div>
<div class="label">Client port <div class="icon info" title="This is the port that will allow users to connect to Olympus and must be forwarded in your firewall."></div></div>
<input id="client-port" type='number' value="<%= typeof client !== 'undefined' ? client["port"]: "" %>" min="1023" max="65535" <%= !installed? "disabled": "" %> tabindex="<%= index %>">
<span id="client-port-error" class="error"></span>
</div>
</td>
<td>
<div class="label">Game Master password <div class="icon info" title="This is the password you need to input to connect with the Game Master role."></div></div>
<input id="game-master-password" type="password" <%= !installed? "disabled": "" %> tabindex="<%= index + 3 %>">
<span id="game-master-password-error" class="error"></span>
<div>
<div class="label">Game Master password <div class="icon info" title="This is the password you need to input to connect with the Game Master role."></div></div>
<input id="game-master-password" type="password" <%= !installed? "disabled": "" %> tabindex="<%= index + 3 %>">
<span id="game-master-password-error" class="error"></span>
</div>
</td>
</tr>
<tr>
<td>
<div class="label">Backend port <div class="icon info" title="This is the backend port used by Olympus to connect to DCS. You don't need to forward it in your firewall anymore."></div></div>
<input id="backend-port" type='number' value="<%= typeof server !== 'undefined' ? server["port"]: "" %>" min="1023" max="65535" <%= !installed? "disabled": "" %> tabindex="<%= index + 1 %>">
<span id="backend-port-error" class="error"></span>
<div>
<div class="label">Backend port <div class="icon info" title="This is the backend port used by Olympus to connect to DCS. You don't need to forward it in your firewall anymore."></div></div>
<input id="backend-port" type='number' value="<%= typeof server !== 'undefined' ? server["port"]: "" %>" min="1023" max="65535" <%= !installed? "disabled": "" %> tabindex="<%= index + 1 %>">
<span id="backend-port-error" class="error"></span>
</div>
</td>
<td>
<div class="label">Blue Commander password <div class="icon info" title="This is the password you need to input to connect with the Blue Commander role."></div></div>
<input id="blue-commander-password" type="password" <%= !installed? "disabled": "" %> tabindex="<%= index + 4 %>">
<span id="blue-commander-password-error" class="error"></span>
<div>
<div class="label">Blue Commander password <div class="icon info" title="This is the password you need to input to connect with the Blue Commander role."></div></div>
<input id="blue-commander-password" type="password" <%= !installed? "disabled": "" %> tabindex="<%= index + 4 %>">
<span id="blue-commander-password-error" class="error"></span>
</div>
</td>
</tr>
<tr>
<td>
<div class="label">Backend address <div class="icon info" title="This is the address that DCS will listen on. Unless you want to send direct API commands, leave this to localhost even for dedicated server installations."></div></div>
<input id="backend-address" type='text' value="<%= typeof server !== 'undefined' ? server["address"]: "" %>" min="1023" max="65535" <%= !installed? "disabled": "" %> tabindex="<%= index + 2 %>">
<span id="backend-address-error" class="error"></span>
<div>
<div class="label">Backend address <div class="icon info" title="This is the address that DCS will listen on. Unless you want to send direct API commands, leave this to localhost even for dedicated server installations."></div></div>
<input id="backend-address" type='text' value="<%= typeof server !== 'undefined' ? server["address"]: "" %>" min="1023" max="65535" <%= !installed? "disabled": "" %> tabindex="<%= index + 2 %>">
<span id="backend-address-error" class="error"></span>
</div>
</td>
<td>
<div class="label">Red Commander password <div class="icon info" title="This is the password you need to input to connect with the Red Commander role."></div></div>
<input id="red-commander-password" type="password" <%= !installed? "disabled": "" %> tabindex="<%= index + 5 %>">
<span id="red-commander-password-error" class="error"></span>
<div>
<div class="label">Red Commander password <div class="icon info" title="This is the password you need to input to connect with the Red Commander role."></div></div>
<input id="red-commander-password" type="password" <%= !installed? "disabled": "" %> tabindex="<%= index + 5 %>">
<span id="red-commander-password-error" class="error"></span>
</div>
</td>
</tr>
</table>

10
manager/ejs/popup.ejs Normal file
View File

@ -0,0 +1,10 @@
<div class="popup-header">
Information
</div>
<div class="popup-content">
<%= message %>
</div>
<div class="popup-footer">
<button class="button other <%= otherButton? "": " hide"%>" ><%= otherButton %></button>
<button class="button apply">Close</button>
</div>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#F2F2F2" d="M.3 89.5C.1 91.6 0 93.8 0 96V224 416c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64V224 96c0-35.3-28.7-64-64-64H64c-2.2 0-4.4 .1-6.5 .3c-9.2 .9-17.8 3.8-25.5 8.2C21.8 46.5 13.4 55.1 7.7 65.5c-3.9 7.3-6.5 15.4-7.4 24zM48 224H464l0 192c0 8.8-7.2 16-16 16L64 432c-8.8 0-16-7.2-16-16l0-192z"/></svg>

After

Width:  |  Height:  |  Size: 568 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#F2F2F2" d="M24 432c-13.3 0-24 10.7-24 24s10.7 24 24 24H488c13.3 0 24-10.7 24-24s-10.7-24-24-24H24z"/></svg>

After

Width:  |  Height:  |  Size: 368 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#F2F2F2" d="M432 48H208c-17.7 0-32 14.3-32 32V96H128V80c0-44.2 35.8-80 80-80H432c44.2 0 80 35.8 80 80V304c0 44.2-35.8 80-80 80H416V336h16c17.7 0 32-14.3 32-32V80c0-17.7-14.3-32-32-32zM48 448c0 8.8 7.2 16 16 16H320c8.8 0 16-7.2 16-16V256H48V448zM64 128H320c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V192c0-35.3 28.7-64 64-64z"/></svg>

After

Width:  |  Height:  |  Size: 621 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="12" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#F2F2F2" d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/></svg>

After

Width:  |  Height:  |  Size: 560 B

View File

@ -1,27 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./stylesheets/style.css">
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;600;700;800&display=swap" />
<meta charset="UTF-8">
<title>DCS Olympus Manager v{{OLYMPUS_VERSION_NUMBER}}</title>
</head>
<body>
<div id="header">
<img class="main-icon" src="../img/OlympusLogoFinal_4k.png"\>
<div>
<div> DCS Olympus Manager</div>
<div class="accent-green">v{{OLYMPUS_VERSION_NUMBER}}</div>
</div>
<head>
<link rel="stylesheet" href="./stylesheets/style.css">
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;600;700;800&display=swap" />
<meta charset="UTF-8">
<title>DCS Olympus Manager v{{OLYMPUS_VERSION_NUMBER}}</title>
</head>
<body>
<div id="title-bar">
<div>DCS Olympus manager</div>
<button class="title-bar-button minimize"></button>
<button class="title-bar-button restore hide"></button>
<button class="title-bar-button maximize"></button>
<button class="title-bar-button close"></button>
</div>
<div id="header">
<img class="main-icon" src="../img/OlympusLogoFinal_4k.png" \>
<div>
<div> DCS Olympus Manager</div>
<div class="accent-green">v{{OLYMPUS_VERSION_NUMBER}}</div>
</div>
<div id="main-div">
<div>
These are the DCS instances that the Olympus Manager has automatically detected in your system. <br>
You can install Olympus and manage your instances from here. <br>
Click on "Install Olympus to instance" to install Olympus.
</div>
<div id="footer">
</div>
</body>
</div>
<div id="main-div">
</div>
<div id="footer">
</div>
</body>
<script>
document.querySelector('.minimize').addEventListener('click', () => {
window.ipcRender.send('window:minimize');
});
document.querySelector('.restore').addEventListener('click', () => {
window.ipcRender.send('window:restore');
});
document.querySelector('.maximize').addEventListener('click', () => {
window.ipcRender.send('window:maximize');
});
document.querySelector('.close').addEventListener('click', () => {
window.ipcRender.send('window:close');
});
window.ipcRender.receive('event:maximized', () => {
document.querySelector('.restore').classList.remove("hide");
document.querySelector('.maximize').classList.add("hide");
})
window.ipcRender.receive('event:unmaximized', () => {
document.querySelector('.restore').classList.add("hide");
document.querySelector('.maximize').classList.remove("hide");
})
</script>
</html>

View File

@ -4,12 +4,92 @@ var path = require('path')
const ejs = require('ejs')
const portfinder = require('portfinder')
const sha256 = require('sha256')
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
const createDesktopShortcut = require('create-desktop-shortcuts');
const shellFoldersKey = 'HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders'
const saveGamesKey = '{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}'
var instanceDivs = [];
// White-listed channels.
const ipc = {
'render': {
// From render to main.
'send': [
'window:minimize', // Channel names
'window:maximize',
'window:restore',
'window:close'
],
// From main to render.
'receive': [
'event:maximized',
'event:unmaximized'
],
// From render to main and back again.
'sendReceive': []
}
};
// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods.
'ipcRender', {
// From render to main.
send: (channel, args) => {
let validChannels = ipc.render.send;
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
},
// From main to render.
receive: (channel, listener) => {
let validChannels = ipc.render.receive;
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`.
ipcRenderer.on(channel, (event, ...args) => listener(...args));
}
},
// From render to main and back again.
invoke: (channel, args) => {
let validChannels = ipc.render.sendReceive;
if (validChannels.includes(channel)) {
return ipcRenderer.invoke(channel, args);
}
}
}
);
function showPopup(message, otherButton, otherButtonCallback) {
var data = {
message: message,
otherButton: otherButton
};
var popups = document.querySelectorAll(".popup");
for (let i = 0; i < popups.length; i++) {
document.body.removeChild(popups[i])
}
ejs.renderFile("./ejs/popup.ejs", data, {}, (err, str) => {
var div = document.createElement("div");
div.classList.add("popup");
div.innerHTML = str;
document.body.appendChild(div);
div.querySelector(".apply").addEventListener("click", () => {
document.body.removeChild(div);
})
div.querySelector(".other").addEventListener("click", () => {
otherButtonCallback();
})
});
}
function checkPort(port, callback) {
portfinder.getPort({port: port, stopPort: port}, (err, res) => {
if (err !== null) {
@ -21,22 +101,50 @@ function checkPort(port, callback) {
});
}
function installOlympus(folder) {
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function installOlympus(folder) {
console.log(`Installing Olympus in ${folder}`);
fs.cpSync(path.join("..", "Mod"), path.join(folder, "Mods", "Services", "Olympus"), {recursive: true});
fs.cpSync(path.join("..", "Scripts", "OlympusHook.lua"), path.join(folder, "Scripts", "OlympusHook.lua"), {recursive: true});
fs.cpSync(path.join("..", "olympus.json"), path.join(folder, "Config", "olympus.json"), {recursive: true});
fs.cpSync(path.join("..", "Scripts", "OlympusHook.lua"), path.join(folder, "Scripts", "OlympusHook.lua"));
fs.cpSync(path.join("..", "olympus.json"), path.join(folder, "Config", "olympus.json"));
if (createDesktopShortcut({
windows: {
filePath: path.resolve(__dirname, '..', '..', 'client', 'client.vbs'),
outputPath: folder,
name: "DCS Olympus client",
arguments: `"${path.join(folder, "Config", "olympus.json")}"`,
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus.ico'),
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
}
}) &&
createDesktopShortcut({
windows: {
filePath: path.resolve(__dirname, '..', '..', 'client', 'server.vbs'),
outputPath: folder,
name: "DCS Olympus server",
arguments: `"${path.join(folder, "Config", "olympus.json")}"`,
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus_server.ico'),
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
}
})) {
console.log("Shorcuts created succesfully")
} else {
throw new Error("Error creating shortcuts");
}
loadDivs();
}
function uninstallOlympus(folder) {
async function uninstallOlympus(folder) {
console.log(`Uninstalling Olympus from ${folder}`);
fs.rmSync(path.join(folder, "Mods", "Services", "Olympus"), {recursive: true});
fs.rmSync(path.join(folder, "Config", "olympus.json"), {recursive: true});
fs.rmSync(path.join(folder, "Config", "olympus.json"));
loadDivs();
}
function applyConfiguration(folder, data) {
async function applyConfiguration(folder, data) {
console.log(`Applying configuration to Olympus from ${folder}`);
if (fs.existsSync(path.join(folder, "Config", "olympus.json"))) {
@ -50,7 +158,9 @@ function applyConfiguration(folder, data) {
config["authentication"]["redCommanderPassword"] = sha256(data["redCommanderPassword"]);
fs.writeFileSync(path.join(folder, "Config", "olympus.json"), JSON.stringify(config, null, 4));
return true;
}
return false;
}
class InstanceDiv {
@ -86,18 +196,71 @@ class InstanceDiv {
ejs.renderFile("./ejs/instanceDiv.ejs", data, {}, (err, str) => {
this.element.innerHTML = str;
this.element.querySelector(".add").addEventListener("click", (e) => {
if (!e.srcElement.classList.contains("disabled"))
installOlympus(this.folder);
if (!e.srcElement.classList.contains("disabled")) {
showPopup("Please wait while Olympus is being installed");
delay(100)
.then(() => {
installOlympus(this.folder)
})
.then(() => {
showPopup("Olympus installed successfully. Use the provided form to set Olympus properties. All fields are mandatory. Click on \"Create desktop shortcuts\" to generate Olympus shortcuts on your desktop.", "Create desktop shortcuts", () => {
if (createDesktopShortcut({
windows: {
filePath: path.resolve(__dirname, '..', '..', 'client', 'client.vbs'),
name: "DCS Olympus client",
arguments: `"${path.join(this.folder, "Config", "olympus.json")}"`,
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus.ico'),
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
}
}) && createDesktopShortcut({
windows: {
filePath: path.resolve(__dirname, '..', '..', 'client', 'server.vbs'),
name: "DCS Olympus server",
arguments: `"${path.join(this.folder, "Config", "olympus.json")}"`,
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus_server.ico'),
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
}
})) {
showPopup("Shortcuts created successfully!")
} else {
showPopup("And error occurred while creating the shortcuts.")
}
});
}).catch(() => {
showPopup("An error has occurred during installation");
})
}
});
this.element.querySelector(".remove").addEventListener("click", (e) => {
if (!e.srcElement.classList.contains("disabled"))
uninstallOlympus(this.folder);
if (!e.srcElement.classList.contains("disabled")){
showPopup("Please wait while Olympus is being uninstalled from DCS instance");
delay(100)
.then(() => {
uninstallOlympus(this.folder)
})
.then(() => {
showPopup("Olympus uninstalled successfully from DCS instance!");
}).catch(() => {
showPopup("An error has occurred during uninstallation");
})
}
});
this.element.querySelector(".apply").addEventListener("click", (e) => {
if (!e.srcElement.classList.contains("disabled"))
applyConfiguration(this.folder, this.getFields());
e.srcElement.classList.remove("blink");
if (!e.srcElement.classList.contains("disabled")) {
showPopup("Please wait while the configuration is being applied");
delay(100)
.then(() => {
applyConfiguration(this.folder, this.getFields())
})
.then(() => {
showPopup("Olympus configuration applied successfully!");
}).catch(() => {
showPopup("An error has occurred while applying the configuration");
})
}
});
var inputs = this.element.querySelectorAll("input");

View File

@ -1,33 +1,66 @@
const { app, BrowserWindow } = require('electron/main')
const path = require('path')
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;
const path = require('path');
let window;
function createWindow() {
const win = new BrowserWindow({
const window = new electronBrowserWindow({
width: 1310,
height: 800,
frame: false,
webPreferences: {
contextIsolation: true,
preload: path.join(__dirname, "javascripts", 'preload.js'),
nodeIntegration: true, // like here
},
icon: "./../img/olympus.ico"
});
window.loadFile('index.html').then(() => { window.show(); });
window.on("maximize", () => {
window.webContents.send('event:maximized')
})
win.loadFile('index.html');
win.setMenuBarVisibility(false);
window.on("unmaximize", () => {
window.webContents.send('event:unmaximized')
})
return window;
}
app.whenReady().then(() => {
createWindow()
electronApp.on('ready', () => {
window = createWindow();
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// ---
electronIpcMain.on('window:minimize', () => {
window.minimize();
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
electronIpcMain.on('window:maximize', () => {
window.maximize();
})
electronIpcMain.on('window:restore', () => {
window.restore();
})
electronIpcMain.on('window:close', () => {
window.close();
})

View File

@ -9,6 +9,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"create-desktop-shortcuts": "^1.10.1",
"create-windowless-app": "^11.0.0",
"ejs": "^3.1.9",
"electron": "^28.0.0",

View File

@ -5,26 +5,85 @@
body {
background-color: #181e25;
padding: 0px;
margin: 0px;
}
#title-bar {
content: " ";
display: block;
-webkit-user-select: none;
-webkit-app-region: drag;
height: 20px;
width: 100%;
display: flex;
justify-content: end;
column-gap: 15px;
padding: 5px;
}
#title-bar>*:first-child {
margin-right: auto;
color: #F2F2F2AA;
font-size: 12px;
}
.title-bar-button {
background-color: transparent;
border: 0px solid transparent;
height: 20px;
width: 20px;
background-repeat: no-repeat;
background-position: 50% 50%;
cursor: pointer;
}
.minimize {
background-image: url("../icons/window-minimize-regular.svg");
}
.restore {
background-image: url("../icons/window-restore-regular.svg");
}
.maximize {
background-image: url("../icons/window-maximize-regular.svg");
}
.close {
background-image: url("../icons/xmark-solid.svg");
}
.title-bar-button {
-webkit-app-region: no-drag;
}
#header {
display: flex;
justify-content: start;
align-items: center;
align-items: start;
color: #F2F2F2;
font-weight: bold;
font-size: 16px;
padding: 10px;
padding: 20px;
column-gap: 10px;
}
#header>div:first-child>div:last-child {
color: green;
}
#header>div:last-child {
font-size: 13px;
margin-left: 30px;
font-weight: 400;
text-align: right;
width: 100%;
}
.main-icon {
width: 60px;
height: 60px;
margin: 10px;
}
#main-div {
@ -34,17 +93,18 @@ body {
row-gap: 30px;
column-gap: 30px;
flex-wrap: wrap;
padding: 15px;
padding: 25px;
}
body {
overflow-y: auto;
overflow: auto;
scrollbar-color: white transparent;
scrollbar-width: thin;
}
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
@ -71,6 +131,7 @@ body {
border-radius: 5px;
border-left: 5px solid #017DC1;
width: 600px;
box-shadow: 0px 0px 5px #000A;
}
.instance-content {
@ -118,8 +179,10 @@ body {
vertical-align: top;
}
.input-table td>* {
margin: 2px 0px;
.input-table td>div {
display: flex;
flex-direction: column;
width: fit-content;
}
.action-buttons {
@ -175,6 +238,10 @@ body {
padding: 5px 15px 5px 15px;
}
.other {
padding: 5px 15px 5px 15px;
}
.remove {
background-image: url("../icons/trash-can-regular.svg");
}
@ -223,4 +290,55 @@ input.error {
height: 12px;
background-image: url("../icons/circle-info-solid.svg");
background-position: 50% 50%;
}
.blink {
animation: blinker 1s linear 3;
}
@keyframes blinker {
50% {
background-color: transparent;
}
}
.popup {
display: flex;
flex-direction: column;
row-gap: 15px;
height: 300px;
width: 500px;
position: absolute;
top: 50%;
left: 50%;
background-color: #181e25;
border-radius: 5px;
transform: translate(-250px, -150px);
padding: 30px;
box-shadow: 0px 0px 5px #000A;
}
.popup-header {
height: 20px;
color: #F2F2F2;
font-size: 14px;
font-weight: 600;
}
.popup-content {
height: calc(100% - 50px);
color: #F2F2F2;
font-size: 13px;
}
.popup-footer {
height: 30px;
display: flex;
justify-content: end;
column-gap: 15px;
}
.popup-footer .apply {
background-image: none;
padding: 5px 15px 5px 15px;
}

View File

@ -0,0 +1,19 @@
{
"server": {
"address": "localhost",
"port": 3001
},
"authentication": {
"gameMasterPassword": "4b8823ed9e5c2392ab4a791913bb8ce41956ea32e308b760eefb97536746dd33",
"blueCommanderPassword": "b0ea4230c1558c5313165eda1bdb7fced008ca7f2ca6b823fb4d26292f309098",
"redCommanderPassword": "302bcbaf2a3fdcf175b689bf102d6cdf9328f68a13d4096101bba806482bfed9"
},
"client": {
"port": 3000,
"elevationProvider": {
"provider": "https://srtm.fasma.org/{lat}{lng}.SRTMGL3S.hgt.zip",
"username": null,
"password": null
}
}
}

View File

@ -0,0 +1,466 @@
{
"airfields": {
"Anapa-Vityazevo": {
"ICAO": "URKA",
"elevation": "141",
"TACAN": "",
"runways": [
{
"headings": [
{
"22": {
"magHeading": "214",
"ILS": ""
},
"04": {
"magHeading": "034",
"ILS": ""
}
}
],
"length": "9000"
}
]
},
"Batumi": {
"ICAO": "UGSB",
"elevation": "33",
"TACAN": "16X",
"runways": [
{
"headings": [
{
"13": {
"magHeading": "119",
"ILS": ""
},
"31": {
"magHeading": "299",
"ILS": ""
}
}
],
"length": "7500"
}
]
},
"Beslan": {
"ICAO": "URMO",
"elevation": "1722",
"TACAN": "",
"runways": [
{
"headings": [
{
"10": {
"magHeading": "086",
"ILS": "110.50"
},
"28": {
"magHeading": "266",
"ILS": ""
}
}
],
"length": "9600"
}
]
},
"Gelendzhik": {
"ICAO": "URKG",
"elevation": "72",
"TACAN": "",
"runways": [
{
"headings": [
{
"19": {
"magHeading": "212",
"ILS": ""
},
"01": {
"magHeading": "032",
"ILS": ""
}
}
],
"length": "5400"
}
]
},
"Gudauta": {
"ICAO": "UG23",
"elevation": "69",
"TACAN": "",
"runways": [
{
"headings": [
{
"15": {
"magHeading": "144",
"ILS": ""
},
"33": {
"magHeading": "324",
"ILS": ""
}
}
],
"length": "7700"
}
]
},
"Kobuleti": {
"ICAO": "UG5X",
"elevation": "69",
"TACAN": "67X",
"runways": [
{
"headings": [
{
"25": {
"magHeading": "243",
"ILS": ""
},
"07": {
"magHeading": "063",
"ILS": "111.50"
}
}
],
"length": "7400"
}
]
},
"Krasnodar-Center": {
"ICAO": "URKL",
"elevation": "98",
"TACAN": "",
"runways": [
{
"headings": [
{
"27": {
"magHeading": "259",
"ILS": ""
},
"09": {
"magHeading": "079",
"ILS": ""
}
}
],
"length": "7700"
}
]
},
"Krasnodar-Pashkovsky": {
"ICAO": "URKK",
"elevation": "112",
"TACAN": "",
"runways": [
{
"headings": [
{
"23": {
"magHeading": "219",
"ILS": ""
},
"05": {
"magHeading": "039",
"ILS": ""
}
}
],
"length": "9600"
}
]
},
"Krymsk": {
"ICAO": "URKW",
"elevation": "66",
"TACAN": "",
"runways": [
{
"headings": [
{
"22": {
"magHeading": "212",
"ILS": ""
},
"04": {
"magHeading": "032",
"ILS": ""
}
}
],
"length": "8000"
}
]
},
"Kutaisi": {
"ICAO": "UGKO",
"elevation": "148",
"TACAN": "44X",
"runways": [
{
"headings": [
{
"25": {
"magHeading": "247",
"ILS": ""
},
"07": {
"magHeading": "067'",
"ILS": "109.75"
}
}
],
"length": "7700"
}
]
},
"Maykop-Khanskaya": {
"ICAO": "URKH",
"elevation": "591",
"TACAN": "",
"runways": [
{
"headings": [
{
"22": {
"magHeading": "211",
"ILS": ""
},
"04": {
"magHeading": "031",
"ILS": ""
}
}
],
"length": "10100"
}
]
},
"Mineralnye Vody": {
"ICAO": "URMM",
"elevation": "1050",
"TACAN": "",
"runways": [
{
"headings": [
{
"12": {
"magHeading": "108",
"ILS": "111.70"
},
"30": {
"magHeading": "288",
"ILS": "109.30"
}
}
],
"length": "12700"
}
]
},
"Mozdok": {
"ICAO": "XRMF",
"elevation": "507",
"TACAN": "",
"runways": [
{
"headings": [
{
"26": {
"magHeading": "255",
"ILS": ""
},
"08": {
"magHeading": "075",
"ILS": ""
}
}
],
"length": "9400"
}
]
},
"Nalchik": {
"ICAO": "URMN",
"elevation": "1411",
"TACAN": "",
"runways": [
{
"headings": [
{
"24": {
"magHeading": "228",
"ILS": "110.50"
},
"06": {
"magHeading": "048'",
"ILS": ""
}
}
],
"length": "7000"
}
]
},
"Novorossiysk": {
"ICAO": "URKN",
"elevation": "131",
"TACAN": "",
"runways": [
{
"headings": [
{
"22": {
"magHeading": "214",
"ILS": ""
},
"04": {
"magHeading": "034",
"ILS": ""
}
}
],
"length": "5400"
}
]
},
"Senaki-Kolkhi": {
"ICAO": "UGKS",
"elevation": "43",
"TACAN": "31X",
"runways": [
{
"headings": [
{
"27": {
"magHeading": "268",
"ILS": ""
},
"09": {
"magHeading": "088'",
"ILS": "108.90"
}
}
],
"length": "7400"
}
]
},
"Sochi-Adler": {
"ICAO": "URSS",
"elevation": "98",
"TACAN": "",
"runways": [
{
"headings": [
{
"27": {
"magHeading": "235",
"ILS": ""
},
"06": {
"magHeading": "055",
"ILS": "111.10"
}
}
],
"length": "9700"
}
]
},
"Tbilisi-Lochini": {
"ICAO": "UGTB",
"elevation": "1574",
"TACAN": "25X",
"runways": [
{
"headings": [
{
"13": {
"magHeading": "121",
"ILS": "110.30"
},
"31": {
"magHeading": "301",
"ILS": "108.90"
}
}
],
"length": "9300"
}
]
},
"Soganlug": {
"ICAO": "UG24",
"elevation": "1500",
"TACAN": "25X",
"runways": [
{
"headings": [
{
"14": {
"magHeading": "125",
"ILS": ""
},
"32": {
"magHeading": "305",
"ILS": ""
}
}
],
"length": "6500"
}
]
},
"Sukhumi-Babushara": {
"ICAO": "UGSS",
"elevation": "43",
"TACAN": "",
"runways": [
{
"headings": [
{
"12": {
"magHeading": "109",
"ILS": ""
},
"30": {
"magHeading": "289",
"ILS": ""
}
}
],
"length": "11400"
}
]
},
"Vaziani": {
"ICAO": "UG27",
"elevation": "1524",
"TACAN": "22X",
"runways": [
{
"headings": [
{
"13": {
"magHeading": "129",
"ILS": "108.75"
},
"31": {
"magHeading": "309",
"ILS": "108.75"
}
}
],
"length": "7700"
}
]
}
}
}

View File

@ -0,0 +1,838 @@
{
"airfields": {
"Aerodromo De Tolhuin": {
"runways": [
{
"headings": [
{
"07": {
"magHeading": "66",
"Heading": "77",
"ILS": ""
}
},
{
"25": {
"magHeading": "246",
"Heading": "257",
"ILS": ""
}
}
],
"length": "3297"
}
],
"TACAN": "",
"ICAO": "SAWL",
"elevation": "355"
},
"Almirante Schroeders": {
"runways": [
{
"headings": [
{
"12": {
"magHeading": "114",
"Heading": "127",
"ILS": ""
}
},
{
"30": {
"magHeading": "294",
"Heading": "307",
"ILS": ""
}
}
],
"length": "4628"
},
{
"headings": [
{
"22": {
"magHeading": "208",
"Heading": "221",
"ILS": ""
}
},
{
"04": {
"magHeading": "28",
"Heading": "41",
"ILS": ""
}
}
],
"length": "3931"
}
],
"TACAN": "",
"ICAO": "SCDW",
"elevation": "160"
},
"Rio Chico": {
"runways": [
{
"headings": [
{
"08": {
"magHeading": "73",
"Heading": "84",
"ILS": ""
}
},
{
"26": {
"magHeading": "253",
"Heading": "264",
"ILS": ""
}
}
],
"length": "3239"
}
],
"TACAN": "",
"ICAO": "RGR",
"elevation": "74"
},
"Puerto Natales": {
"runways": [
{
"headings": [
{
"28": {
"magHeading": "274",
"Heading": "287",
"ILS": ""
}
},
{
"10": {
"magHeading": "94",
"Heading": "107",
"ILS": ""
}
}
],
"length": "5281"
}
],
"TACAN": "",
"ICAO": "SCNT",
"elevation": "216"
},
"Mount Pleasant": {
"runways": [
{
"headings": [
{
"10": {
"magHeading": "101",
"Heading": "104",
"ILS": ""
}
},
{
"28": {
"magHeading": "281",
"Heading": "284",
"ILS": "111.90"
}
}
],
"length": "6763"
},
{
"headings": [
{
"23": {
"magHeading": "231",
"Heading": "234",
"ILS": ""
}
},
{
"05": {
"magHeading": "51",
"Heading": "54",
"ILS": ""
}
}
],
"length": "6763"
}
],
"TACAN": "59X",
"ICAO": "EGYP",
"elevation": "243"
},
"Aerodromo O'Higgins": {
"runways": [
{
"headings": [
{
"34": {
"magHeading": "326",
"Heading": "338",
"ILS": ""
}
},
{
"16": {
"magHeading": "146",
"Heading": "158",
"ILS": ""
}
}
],
"length": "3968"
}
],
"TACAN": "",
"ICAO": "SCOH",
"elevation": "900"
},
"Ushuaia Helo Port": {
"runways": [
{
"headings": [
{
"16": {
"magHeading": "157",
"Heading": "170",
"ILS": ""
}
},
{
"34": {
"magHeading": "337",
"Heading": "350",
"ILS": ""
}
}
],
"length": "5076"
}
],
"TACAN": "",
"ICAO": "SAWO",
"elevation": "42"
},
"Franco Bianco": {
"runways": [
{
"headings": [
{
"07": {
"magHeading": "65",
"Heading": "77",
"ILS": ""
}
},
{
"25": {
"magHeading": "245",
"Heading": "257",
"ILS": ""
}
}
],
"length": "5008"
},
{
"headings": [
{
"20": {
"magHeading": "185",
"Heading": "196",
"ILS": ""
}
},
{
"02": {
"magHeading": "5",
"Heading": "16",
"ILS": ""
}
}
],
"length": "5008"
}
],
"TACAN": "",
"ICAO": "SCSB",
"elevation": "104"
},
"Pampa Guanaco": {
"runways": [
{
"headings": [
{
"26": {
"magHeading": "248",
"Heading": "260",
"ILS": ""
}
},
{
"08": {
"magHeading": "68",
"Heading": "80",
"ILS": ""
}
}
],
"length": "2349"
}
],
"TACAN": "",
"ICAO": "SCBI",
"elevation": "519"
},
"Puerto Santa Cruz": {
"runways": [
{
"headings": [
{
"07": {
"magHeading": "81",
"Heading": "69",
"ILS": ""
}
},
{
"25": {
"magHeading": "261",
"Heading": "249",
"ILS": ""
}
}
],
"length": "5638"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "365"
},
"San Carlos FOB": {
"runways": [
{
"headings": [
{
"11": {
"magHeading": "285",
"Heading": "288",
"ILS": ""
}
},
{
"29": {
"magHeading": "105",
"Heading": "108",
"ILS": ""
}
}
],
"length": "1079"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "65"
},
"Goose Green": {
"runways": [
{
"headings": [
{
"14": {
"magHeading": "135",
"Heading": "139",
"ILS": ""
}
},
{
"32": {
"magHeading": "315",
"Heading": "319",
"ILS": ""
}
}
],
"length": "1976"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "57"
},
"Rio Turbio": {
"runways": [
{
"headings": [
{
"24": {
"magHeading": "225",
"Heading": "239",
"ILS": ""
}
},
{
"06": {
"magHeading": "45",
"Heading": "59",
"ILS": ""
}
}
],
"length": "5057"
}
],
"TACAN": "",
"ICAO": "SAWT",
"elevation": "895"
},
"Porvenir Airfield": {
"runways": [
{
"headings": [
{
"09": {
"magHeading": "87",
"Heading": "99",
"ILS": ""
}
},
{
"27": {
"magHeading": "266",
"Heading": "279",
"ILS": ""
}
}
],
"length": "7821"
},
{
"headings": [
{
"21": {
"magHeading": "203",
"Heading": "216",
"ILS": ""
}
},
{
"03": {
"magHeading": "23",
"Heading": "36",
"ILS": ""
}
}
],
"length": "3220"
}
],
"TACAN": "",
"ICAO": "SCFM",
"elevation": "56"
},
"Punta Arenas": {
"runways": [
{
"headings": [
{
"30": {
"magHeading": "295",
"Heading": "308",
"ILS": ""
}
},
{
"12": {
"magHeading": "140",
"Heading": "128",
"ILS": ""
}
}
],
"length": "6834"
},
{
"headings": [
{
"25": {
"magHeading": "270",
"Heading": "258",
"ILS": ""
}
},
{
"07": {
"magHeading": "90",
"Heading": "78",
"ILS": ""
}
}
],
"length": "9360"
},
{
"headings": [
{
"19": {
"magHeading": "210",
"Heading": "198",
"ILS": ""
}
}
],
"length": "5160"
}
],
"TACAN": "",
"ICAO": "SCCI",
"elevation": "122"
},
"Gull Point": {
"runways": [
{
"headings": [
{
"15": {
"magHeading": "149",
"Heading": "152",
"ILS": ""
}
},
{
"33": {
"magHeading": "329",
"Heading": "332",
"ILS": ""
}
}
],
"length": "1521"
},
{
"headings": [
{
"23": {
"magHeading": "212",
"Heading": "216",
"ILS": ""
}
},
{
"05": {
"magHeading": "33",
"Heading": "36",
"ILS": ""
}
}
],
"length": "1352"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "4"
},
"Caleta Tortel Airport": {
"runways": [
{
"headings": [
{
"04": {
"magHeading": "235",
"Heading": "223",
"ILS": ""
}
},
{
"22": {
"magHeading": "55",
"Heading": "43",
"ILS": ""
}
}
],
"length": "1770"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "3"
},
"Comandante Luis Piedrabuena": {
"runways": [
{
"headings": [
{
"26": {
"magHeading": "272",
"Heading": "260",
"ILS": ""
}
},
{
"08": {
"magHeading": "92",
"Heading": "80",
"ILS": ""
}
}
],
"length": "3505"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "69"
},
"Hipico Flying Club": {
"runways": [
{
"headings": [
{
"02": {
"magHeading": "1",
"Heading": "11",
"ILS": ""
}
},
{
"19": {
"magHeading": "180",
"Heading": "191",
"ILS": ""
}
}
],
"length": "2304"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "934"
},
"Cullen Airport": {
"runways": [],
"TACAN": "",
"ICAO": "",
"elevation": "0"
},
"Aeropuerto de Gobernador Gregores": {
"runways": [
{
"headings": [
{
"28": {
"magHeading": "263",
"Heading": "274",
"ILS": ""
}
},
{
"10": {
"magHeading": "84",
"Heading": "94",
"ILS": ""
}
}
],
"length": "8672"
}
],
"TACAN": "",
"ICAO": "SAWR",
"elevation": "1168"
},
"San Julian": {
"runways": [
{
"headings": [
{
"25": {
"magHeading": "242",
"Heading": "251",
"ILS": ""
}
},
{
"07": {
"magHeading": "62",
"Heading": "71",
"ILS": ""
}
}
],
"length": "6218"
}
],
"TACAN": "",
"ICAO": "SAWJ",
"elevation": "144"
},
"Puerto Williams": {
"runways": [
{
"headings": [
{
"08": {
"magHeading": "70",
"Heading": "82",
"ILS": ""
}
},
{
"26": {
"magHeading": "250",
"Heading": "262",
"ILS": ""
}
}
],
"length": "4312"
}
],
"TACAN": "",
"ICAO": "SCGZ",
"elevation": "83"
},
"Ushuaia": {
"runways": [
{
"headings": [
{
"07": {
"magHeading": "65",
"Heading": "77",
"ILS": ""
}
},
{
"25": {
"magHeading": "245",
"Heading": "257",
"ILS": "111.30"
}
}
],
"length": "7631"
}
],
"TACAN": "",
"ICAO": "SAWH",
"elevation": "60"
},
"Rio Gallegos": {
"runways": [
{
"headings": [
{
"25": {
"magHeading": "245",
"Heading": "256",
"ILS": "110.30"
}
},
{
"07": {
"magHeading": "65",
"Heading": "76",
"ILS": ""
}
}
],
"length": "10585"
}
],
"TACAN": "",
"ICAO": "SAWG",
"elevation": "50"
},
"Rio Grande": {
"runways": [
{
"headings": [
{
"08": {
"magHeading": "68",
"Heading": "79",
"ILS": ""
}
},
{
"26": {
"magHeading": "247",
"Heading": "259",
"ILS": "109.50"
}
}
],
"length": "5922"
}
],
"TACAN": "31X",
"ICAO": "SAWE",
"elevation": "60"
},
"Port Stanley": {
"runways": [
{
"headings": [
{
"27": {
"magHeading": "266",
"Heading": "269",
"ILS": ""
}
},
{
"09": {
"magHeading": "101",
"Heading": "86",
"ILS": ""
}
}
],
"length": "4388"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "67"
},
"El Calafate": {
"runways": [
{
"headings": [
{
"25": {
"magHeading": "241",
"Heading": "253",
"ILS": "108.90"
}
},
{
"07": {
"magHeading": "61",
"Heading": "73",
"ILS": ""
}
}
],
"length": "7579"
}
],
"TACAN": "",
"ICAO": "SAWC",
"elevation": "654"
}
}
}

View File

@ -0,0 +1,466 @@
{
"airfields": {
"Anapa-Vityazevo": {
"ICAO": "URKA",
"elevation": "141",
"TACAN": "",
"runways": [
{
"headings": [
{
"22": {
"magHeading": "214",
"ILS": ""
},
"04": {
"magHeading": "034",
"ILS": ""
}
}
],
"length": "9000"
}
]
},
"Batumi": {
"ICAO": "UGSB",
"elevation": "33",
"TACAN": "16X",
"runways": [
{
"headings": [
{
"13": {
"magHeading": "119",
"ILS": ""
},
"31": {
"magHeading": "299",
"ILS": ""
}
}
],
"length": "7500"
}
]
},
"Beslan": {
"ICAO": "URMO",
"elevation": "1722",
"TACAN": "",
"runways": [
{
"headings": [
{
"10": {
"magHeading": "086",
"ILS": "110.50"
},
"28": {
"magHeading": "266",
"ILS": ""
}
}
],
"length": "9600"
}
]
},
"Gelendzhik": {
"ICAO": "URKG",
"elevation": "72",
"TACAN": "",
"runways": [
{
"headings": [
{
"19": {
"magHeading": "212",
"ILS": ""
},
"01": {
"magHeading": "032",
"ILS": ""
}
}
],
"length": "5400"
}
]
},
"Gudauta": {
"ICAO": "UG23",
"elevation": "69",
"TACAN": "",
"runways": [
{
"headings": [
{
"15": {
"magHeading": "144",
"ILS": ""
},
"33": {
"magHeading": "324",
"ILS": ""
}
}
],
"length": "7700"
}
]
},
"Kobuleti": {
"ICAO": "UG5X",
"elevation": "69",
"TACAN": "67X",
"runways": [
{
"headings": [
{
"25": {
"magHeading": "243",
"ILS": ""
},
"07": {
"magHeading": "063",
"ILS": "111.50"
}
}
],
"length": "7400"
}
]
},
"Krasnodar-Center": {
"ICAO": "URKL",
"elevation": "98",
"TACAN": "",
"runways": [
{
"headings": [
{
"27": {
"magHeading": "259",
"ILS": ""
},
"09": {
"magHeading": "079",
"ILS": ""
}
}
],
"length": "7700"
}
]
},
"Krasnodar-Pashkovsky": {
"ICAO": "URKK",
"elevation": "112",
"TACAN": "",
"runways": [
{
"headings": [
{
"23": {
"magHeading": "219",
"ILS": ""
},
"05": {
"magHeading": "039",
"ILS": ""
}
}
],
"length": "9600"
}
]
},
"Krymsk": {
"ICAO": "URKW",
"elevation": "66",
"TACAN": "",
"runways": [
{
"headings": [
{
"22": {
"magHeading": "212",
"ILS": ""
},
"04": {
"magHeading": "032",
"ILS": ""
}
}
],
"length": "8000"
}
]
},
"Kutaisi": {
"ICAO": "UGKO",
"elevation": "148",
"TACAN": "44X",
"runways": [
{
"headings": [
{
"25": {
"magHeading": "247",
"ILS": ""
},
"07": {
"magHeading": "067'",
"ILS": "109.75"
}
}
],
"length": "7700"
}
]
},
"Maykop-Khanskaya": {
"ICAO": "URKH",
"elevation": "591",
"TACAN": "",
"runways": [
{
"headings": [
{
"22": {
"magHeading": "211",
"ILS": ""
},
"04": {
"magHeading": "031",
"ILS": ""
}
}
],
"length": "10100"
}
]
},
"Mineralnye Vody": {
"ICAO": "URMM",
"elevation": "1050",
"TACAN": "",
"runways": [
{
"headings": [
{
"12": {
"magHeading": "108",
"ILS": "111.70"
},
"30": {
"magHeading": "288",
"ILS": "109.30"
}
}
],
"length": "12700"
}
]
},
"Mozdok": {
"ICAO": "XRMF",
"elevation": "507",
"TACAN": "",
"runways": [
{
"headings": [
{
"26": {
"magHeading": "255",
"ILS": ""
},
"08": {
"magHeading": "075",
"ILS": ""
}
}
],
"length": "9400"
}
]
},
"Nalchik": {
"ICAO": "URMN",
"elevation": "1411",
"TACAN": "",
"runways": [
{
"headings": [
{
"24": {
"magHeading": "228",
"ILS": "110.50"
},
"06": {
"magHeading": "048'",
"ILS": ""
}
}
],
"length": "7000"
}
]
},
"Novorossiysk": {
"ICAO": "URKN",
"elevation": "131",
"TACAN": "",
"runways": [
{
"headings": [
{
"22": {
"magHeading": "214",
"ILS": ""
},
"04": {
"magHeading": "034",
"ILS": ""
}
}
],
"length": "5400"
}
]
},
"Senaki-Kolkhi": {
"ICAO": "UGKS",
"elevation": "43",
"TACAN": "31X",
"runways": [
{
"headings": [
{
"27": {
"magHeading": "268",
"ILS": ""
},
"09": {
"magHeading": "088'",
"ILS": "108.90"
}
}
],
"length": "7400"
}
]
},
"Sochi-Adler": {
"ICAO": "URSS",
"elevation": "98",
"TACAN": "",
"runways": [
{
"headings": [
{
"27": {
"magHeading": "235",
"ILS": ""
},
"06": {
"magHeading": "055",
"ILS": "111.10"
}
}
],
"length": "9700"
}
]
},
"Tbilisi-Lochini": {
"ICAO": "UGTB",
"elevation": "1574",
"TACAN": "25X",
"runways": [
{
"headings": [
{
"13": {
"magHeading": "121",
"ILS": "110.30"
},
"31": {
"magHeading": "301",
"ILS": "108.90"
}
}
],
"length": "9300"
}
]
},
"Soganlug": {
"ICAO": "UG24",
"elevation": "1500",
"TACAN": "25X",
"runways": [
{
"headings": [
{
"14": {
"magHeading": "125",
"ILS": ""
},
"32": {
"magHeading": "305",
"ILS": ""
}
}
],
"length": "6500"
}
]
},
"Sukhumi-Babushara": {
"ICAO": "UGSS",
"elevation": "43",
"TACAN": "",
"runways": [
{
"headings": [
{
"12": {
"magHeading": "109",
"ILS": ""
},
"30": {
"magHeading": "289",
"ILS": ""
}
}
],
"length": "11400"
}
]
},
"Vaziani": {
"ICAO": "UG27",
"elevation": "1524",
"TACAN": "22X",
"runways": [
{
"headings": [
{
"13": {
"magHeading": "129",
"ILS": "108.75"
},
"31": {
"magHeading": "309",
"ILS": "108.75"
}
}
],
"length": "7700"
}
]
}
}
}

View File

@ -0,0 +1,558 @@
{
"airfields": {
"Beatty": {
"ICAO": "KBTY",
"elevation": "3173",
"TACAN": "94X",
"runways": [
{
"headings": [
{
"16": {
"magHeading": "168",
"ILS": ""
},
"34": {
"magHeading": "348",
"ILS": ""
}
}
],
"length": "5500"
}
]
},
"Boulder City": {
"ICAO": "KBVU",
"elevation": "2205",
"TACAN": "114X",
"runways": [
{
"headings": [
{
"15": {
"magHeading": "153",
"ILS": ""
},
"33": {
"magHeading": "333",
"ILS": ""
}
}
],
"length": "3700"
},
{
"headings": [
{
"27": {
"magHeading": "267",
"ILS": ""
},
"09": {
"magHeading": "087",
"ILS": ""
}
}
],
"length": "4400"
}
]
},
"Creech": {
"ICAO": "KINS",
"elevation": "3126",
"TACAN": "87X",
"runways": [
{
"headings": [
{
"13": {
"magHeading": "134",
"ILS": ""
},
"31": {
"magHeading": "314",
"ILS": ""
}
}
],
"length": "4700"
},
{
"headings": [
{
"26": {
"magHeading": "260",
"ILS": ""
},
"08": {
"magHeading": "080",
"ILS": "108.70"
}
}
],
"length": "8700"
}
]
},
"Echo Bay": {
"ICAO": "0L9",
"elevation": "1549",
"TACAN": "",
"runways": [
{
"headings": [
{
"24": {
"magHeading": "246",
"ILS": ""
},
"06": {
"magHeading": "066",
"ILS": ""
}
}
],
"length": "3300"
}
]
},
"Groom Lake": {
"ICAO": "KXTA",
"elevation": "4495",
"TACAN": "18X",
"runways": [
{
"headings": [
{
"14L": {
"magHeading": "145",
"ILS": ""
},
"32R": {
"magHeading": "325",
"ILS": "109.30"
}
}
],
"length": "11700"
},
{
"headings": [
{
"14R (CLOSED)": {
"magHeading": "145",
"ILS": ""
},
"32L (CLOSED)": {
"magHeading": "325",
"ILS": ""
}
}
],
"length": "17800"
}
]
},
"Henderson Executive": {
"ICAO": "KHND",
"elevation": "2493",
"TACAN": "",
"runways": [
{
"headings": [
{
"17L": {
"magHeading": "168",
"ILS": ""
},
"35R": {
"magHeading": "348",
"ILS": ""
}
}
],
"length": "4600"
},
{
"headings": [
{
"17R": {
"magHeading": "168",
"ILS": ""
},
"35L": {
"magHeading": "348",
"ILS": ""
}
}
],
"length": "6100"
}
]
},
"Jean": {
"ICAO": "",
"elevation": "2825",
"TACAN": "",
"runways": [
{
"headings": [
{
"02L": {
"magHeading": "020",
"ILS": ""
},
"20R": {
"magHeading": "200",
"ILS": ""
}
}
],
"length": "4500"
},
{
"headings": [
{
"02R": {
"magHeading": "020",
"ILS": ""
},
"20L": {
"magHeading": "200",
"ILS": ""
}
}
],
"length": "3600"
}
]
},
"McCarran International": {
"ICAO": "KLAS",
"elevation": "2178",
"TACAN": "116X",
"runways": [
{
"headings": [
{
"01L": {
"magHeading": "013",
"ILS": ""
},
"19R": {
"magHeading": "193",
"ILS": ""
}
}
],
"length": "8000"
},
{
"headings": [
{
"01R": {
"magHeading": "013",
"ILS": ""
},
"19L": {
"magHeading": "193",
"ILS": ""
}
}
],
"length": "8000"
},
{
"headings": [
{
"07L": {
"magHeading": "078",
"ILS": ""
},
"25R": {
"magHeading": "258",
"ILS": "110.30"
}
}
],
"length": "10600"
},
{
"headings": [
{
"07R": {
"magHeading": "078",
"ILS": ""
},
"25L": {
"magHeading": "258",
"ILS": ""
}
}
],
"length": "10100"
}
]
},
"Laughlin": {
"ICAO": "KIFP",
"elevation": "673",
"TACAN": "",
"runways": [
{
"headings": [
{
"16": {
"magHeading": "164",
"ILS": ""
},
"34": {
"magHeading": "344",
"ILS": ""
}
}
],
"length": "7100"
}
]
},
"Lincoln County": {
"ICAO": "",
"elevation": "4816",
"TACAN": "",
"runways": [
{
"headings": [
{
"17": {
"magHeading": "170",
"ILS": ""
},
"35": {
"magHeading": "350",
"ILS": ""
}
}
],
"length": "4500"
}
]
},
"Mesquite": {
"ICAO": "67L",
"elevation": "1859",
"TACAN": "",
"runways": [
{
"headings": [
{
"19": {
"magHeading": "197",
"ILS": ""
},
"01": {
"magHeading": "017",
"ILS": ""
}
}
],
"length": "5000"
}
]
},
"Mina": {
"ICAO": "",
"elevation": "4560",
"TACAN": "",
"runways": [
{
"headings": [
{
"13": {
"magHeading": "140",
"ILS": ""
},
"31": {
"magHeading": "320",
"ILS": ""
}
}
],
"length": "4100"
}
]
},
"Nellis": {
"ICAO": "KLSV",
"elevation": "1849",
"TACAN": "12X",
"runways": [
{
"headings": [
{
"03L": {
"magHeading": "029",
"ILS": ""
},
"21R": {
"magHeading": "209",
"ILS": ""
}
}
],
"length": "9800"
},
{
"headings": [
{
"03R": {
"magHeading": "029",
"ILS": ""
},
"21L": {
"magHeading": "209",
"ILS": "109.10"
}
}
],
"length": "9800"
}
]
},
"North Las Vegas": {
"ICAO": "KVGT",
"elevation": "2228",
"TACAN": "",
"runways": [
{
"headings": [
{
"25": {
"magHeading": "256",
"ILS": ""
},
"07": {
"magHeading": "076",
"ILS": ""
}
}
],
"length": "4900"
},
{
"headings": [
{
"12L": {
"magHeading": "122",
"ILS": "110.70"
},
"30R": {
"magHeading": "302",
"ILS": "109.10"
}
}
],
"length": "3800"
},
{
"headings": [
{
"12R": {
"magHeading": "122",
"ILS": ""
},
"30L": {
"magHeading": "302",
"ILS": ""
}
}
],
"length": "4600"
}
]
},
"Pahute Mesa": {
"ICAO": "",
"elevation": "5059",
"TACAN": "",
"runways": [
{
"headings": [
{
"18": {
"magHeading": "182",
"ILS": ""
},
"36": {
"magHeading": "002",
"ILS": ""
}
}
],
"length": "5500"
}
]
},
"Tonopah": {
"ICAO": "KTPH",
"elevation": "5390",
"TACAN": "119X",
"runways": [
{
"headings": [
{
"11": {
"magHeading": "113",
"ILS": ""
},
"29": {
"magHeading": "293",
"ILS": ""
}
}
],
"length": "5600"
},
{
"headings": [
{
"15": {
"magHeading": "153",
"ILS": ""
},
"33": {
"magHeading": "333",
"ILS": ""
}
}
],
"length": "6800"
}
]
},
"Tonopah Test Range": {
"ICAO": "KTNX",
"elevation": "5535",
"TACAN": "77X",
"runways": [
{
"headings": [
{
"14": {
"magHeading": "145",
"ILS": "108.30"
},
"32": {
"magHeading": "325",
"ILS": "111.70"
}
}
],
"length": "11700"
}
]
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,769 @@
{
"airfields": {
"Abu Dhabi Intl": {
"elevation": "92",
"ICAO": "OMAA",
"runways": [
{
"headings": [
{
"13L": {
"ILS": "",
"magHeading": "127"
},
"31R": {
"ILS": "",
"magHeading": "307"
}
}
],
"length": "13100"
},
{
"headings": [
{
"13R": {
"ILS": "",
"magHeading": "127"
},
"31L": {
"ILS": "",
"magHeading": "307"
}
}
],
"length": "13200"
}
],
"TACAN": ""
},
"Abu Musa Island": {
"elevation": "16",
"ICAO": "OIBA",
"runways": [
{
"headings": [
{
"26": {
"ILS": "",
"magHeading": "262"
},
"08": {
"ILS": "",
"magHeading": "082"
}
}
],
"length": "7800"
}
],
"TACAN": ""
},
"Al Ain Intl": {
"elevation": "814",
"ICAO": "OMAL",
"runways": [
{
"headings": [
{
"19": {
"ILS": "",
"magHeading": "186"
},
"01": {
"ILS": "",
"magHeading": "006"
}
}
],
"length": "12800"
}
],
"TACAN": ""
},
"Al Dhafra AFB": {
"elevation": "52",
"ICAO": "OMAM",
"runways": [
{
"headings": [
{
"13L": {
"ILS": "111.10",
"magHeading": "126"
},
"31R": {
"ILS": "109.10",
"magHeading": "306"
}
}
],
"length": "11700"
},
{
"headings": [
{
"13R": {
"ILS": "108.70",
"magHeading": "16"
},
"31L": {
"ILS": "108.70",
"magHeading": "306"
}
}
],
"length": "11700"
}
],
"TACAN": "96X"
},
"Al Maktoum Intl": {
"elevation": "125",
"ICAO": "OMDW",
"runways": [
{
"headings": [
{
"12": {
"ILS": "111.75",
"magHeading": "120"
},
"30": {
"ILS": "109.75",
"magHeading": "300"
}
}
],
"length": "14400"
}
],
"TACAN": ""
},
"Al Minhad AFB": {
"elevation": "190",
"ICAO": "OMDM",
"runways": [
{
"headings": [
{
"27": {
"ILS": "110.75",
"magHeading": "268"
},
"09": {
"ILS": "110.70",
"magHeading": "088"
}
}
],
"length": "12600"
}
],
"TACAN": "99X"
},
"Al-Bateen": {
"elevation": "12",
"ICAO": "OMAD",
"runways": [
{
"headings": [
{
"13": {
"ILS": "",
"magHeading": "127"
},
"31": {
"ILS": "",
"magHeading": "307"
}
}
],
"length": "7000"
}
],
"TACAN": ""
},
"Bandar Abbas Intl": {
"elevation": "29",
"ICAO": "OIKB",
"runways": [
{
"headings": [
{
"03L": {
"ILS": "",
"magHeading": "25"
},
"21R": {
"ILS": "",
"magHeading": "205"
}
}
],
"length": "11000"
},
{
"headings": [
{
"03R": {
"ILS": "",
"magHeading": "25"
},
"21L": {
"ILS": "109.90",
"magHeading": "205"
}
}
],
"length": "11700"
}
],
"TACAN": "78X"
},
"Bandar Lengeh": {
"elevation": "82",
"ICAO": "OIBL",
"runways": [
{
"headings": [
{
"26": {
"ILS": "",
"magHeading": "259"
},
"08": {
"ILS": "",
"magHeading": "079"
}
}
],
"length": "7900"
}
],
"TACAN": ""
},
"Bandar-e-Jask": {
"elevation": "26",
"ICAO": "OIZJ",
"runways": [
{
"headings": [
{
"24": {
"ILS": "",
"magHeading": "239"
},
"06": {
"ILS": "",
"magHeading": "059"
}
}
],
"length": "7300"
}
],
"TACAN": "110X"
},
"Dubai Intl": {
"elevation": "16",
"ICAO": "OMDB",
"runways": [
{
"headings": [
{
"12L": {
"ILS": "110.10",
"magHeading": "120"
},
"30R": {
"ILS": "110.90",
"magHeading": "300"
}
}
],
"length": "11400"
},
{
"headings": [
{
"12R": {
"ILS": "109.50",
"magHeading": "120"
},
"30L": {
"ILS": "111.30",
"magHeading": "300"
}
}
],
"length": "11400"
}
],
"TACAN": ""
},
"Fujairah Intl": {
"elevation": "121",
"ICAO": "OMFJ",
"runways": [
{
"headings": [
{
"11": {
"ILS": "",
"magHeading": "111"
},
"29": {
"ILS": "111.50",
"magHeading": "291"
}
}
],
"length": "9700"
}
],
"TACAN": ""
},
"Havadarya": {
"elevation": "52",
"ICAO": "OIKP",
"runways": [
{
"headings": [
{
"26": {
"ILS": "",
"magHeading": "257"
},
"08": {
"ILS": "108.90",
"magHeading": "077"
}
}
],
"length": "7200"
}
],
"TACAN": "47X"
},
"Jiroft": {
"elevation": "2664",
"ICAO": "OIKJ",
"runways": [
{
"headings": [
{
"13": {
"ILS": "",
"magHeading": "125"
},
"31": {
"ILS": "",
"magHeading": "305"
}
}
],
"length": "9600"
}
],
"TACAN": ""
},
"Kerman": {
"elevation": "5745",
"ICAO": "OIKK",
"runways": [
{
"headings": [
{
"16": {
"ILS": "",
"magHeading": "155"
},
"34": {
"ILS": "",
"magHeading": "335"
}
}
],
"length": "12400"
}
],
"TACAN": "97X"
},
"Khasab": {
"elevation": "102",
"ICAO": "OOKB",
"runways": [
{
"headings": [
{
"19": {
"ILS": "110.30",
"magHeading": "192"
},
"01": {
"ILS": "",
"magHeading": "012"
}
}
],
"length": "8000"
}
],
"TACAN": ""
},
"Kish Intl": {
"elevation": "115",
"ICAO": "OIBK",
"runways": [
{
"headings": [
{
"10": {
"ILS": "",
"magHeading": "094"
},
"28": {
"ILS": "",
"magHeading": "274"
}
}
],
"length": "11700"
},
{
"headings": [
{
"09R": {
"ILS": "",
"magHeading": "094"
},
"27L": {
"ILS": "",
"magHeading": "274"
}
}
],
"length": "11700"
}
],
"TACAN": "112X"
},
"Lar": {
"elevation": "2635",
"ICAO": "OISL",
"runways": [
{
"headings": [
{
"27": {
"ILS": "",
"magHeading": "268"
},
"09": {
"ILS": "",
"magHeading": "088"
}
}
],
"length": "10100"
}
],
"TACAN": ""
},
"Lavan Island": {
"elevation": "75",
"ICAO": "OIBV",
"runways": [
{
"headings": [
{
"11": {
"ILS": "",
"magHeading": "110"
},
"29": {
"ILS": "",
"magHeading": "290"
}
}
],
"length": "8600"
}
],
"TACAN": ""
},
"Liwa AFB": {
"elevation": "400",
"ICAO": "OMLW",
"runways": [
{
"headings": [
{
"13": {
"ILS": "",
"magHeading": "130"
},
"31": {
"ILS": "",
"magHeading": "310"
}
}
],
"length": "11600"
}
],
"TACAN": "121X"
},
"Qeshm Island": {
"elevation": "26",
"ICAO": "OIKQ",
"runways": [
{
"headings": [
{
"23": {
"ILS": "",
"magHeading": "227"
},
"05": {
"ILS": "",
"magHeading": "047"
}
}
],
"length": "13600"
}
],
"TACAN": ""
},
"Quasoura_airport": {
"elevation": "26",
"ICAO": "OIKQ",
"runways": [
{
"headings": [
{
"23": {
"ILS": "",
"magHeading": "227"
},
"05": {
"ILS": "",
"magHeading": "047"
}
}
],
"length": "13600"
}
],
"TACAN": ""
},
"Ras Al Khaimah Intl": {
"elevation": "330",
"ICAO": "OMRK",
"runways": [
{
"headings": [
{
"17": {
"ILS": "",
"magHeading": "163"
},
"35": {
"ILS": "",
"magHeading": "343"
}
}
],
"length": "12000"
}
],
"TACAN": ""
},
"Sas Al Nakheel": {
"elevation": "10",
"ICAO": "OMNK",
"runways": [
{
"headings": [
{
"16": {
"ILS": "",
"magHeading": "160"
},
"34": {
"ILS": "",
"magHeading": "340"
}
}
],
"length": "6000"
}
],
"TACAN": ""
},
"Sharjah Intl": {
"elevation": "26",
"ICAO": "OMSJ",
"runways": [
{
"headings": [
{
"12L": {
"ILS": "108.55",
"magHeading": "121"
},
"30R": {
"ILS": "111.95",
"magHeading": "301"
}
}
],
"length": "10500"
},
{
"headings": [
{
"12R": {
"ILS": "",
"magHeading": "121"
},
"30L": {
"ILS": "",
"magHeading": "301"
}
}
],
"length": "10500"
}
],
"TACAN": ""
},
"Shiraz Intl": {
"elevation": "4879",
"ICAO": "OISS",
"runways": [
{
"headings": [
{
"11L": {
"ILS": "",
"magHeading": "113"
},
"29R": {
"ILS": "",
"magHeading": "293"
}
}
],
"length": "14000"
},
{
"headings": [
{
"11R": {
"ILS": "",
"magHeading": "113"
},
"29L": {
"ILS": "108.50",
"magHeading": "293"
}
}
],
"length": "13800"
}
],
"TACAN": "94X"
},
"Sir Abu Nuayr": {
"elevation": "26",
"ICAO": "OMSN",
"runways": [
{
"headings": [
{
"10": {
"ILS": "",
"magHeading": "097"
},
"28": {
"ILS": "",
"magHeading": "277"
}
}
],
"length": "2300"
}
],
"TACAN": ""
},
"Sirri Island": {
"elevation": "20",
"ICAO": "OIBS",
"runways": [
{
"headings": [
{
"12": {
"ILS": "",
"magHeading": "125"
},
"30": {
"ILS": "",
"magHeading": "305"
}
}
],
"length": "7900"
}
],
"TACAN": ""
},
"Tunb Island AFB": {
"elevation": "43",
"ICAO": "OIGI",
"runways": [
{
"headings": [
{
"21": {
"ILS": "",
"magHeading": "205"
},
"03": {
"ILS": "",
"magHeading": "025"
}
}
],
"length": "6200"
}
],
"TACAN": ""
},
"Tunb Kochak": {
"elevation": "16",
"ICAO": "OITK",
"runways": [
{
"headings": [
{
"26": {
"ILS": "",
"magHeading": "259"
},
"08": {
"ILS": "",
"magHeading": "079"
}
}
],
"length": "2500"
}
],
"TACAN": "89X"
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,525 @@
{
"airfields": {
"High Halden": {
"runways": [
{
"headings": [
{
"11": {
"magHeading": "102",
"Heading": "102",
"ILS": ""
}
},
{
"29": {
"magHeading": "282",
"Heading": "282",
"ILS": ""
}
}
],
"length": "3027"
},
{
"headings": [
{
"21": {
"magHeading": "211",
"Heading": "211",
"ILS": ""
}
},
{
"03": {
"magHeading": "31",
"Heading": "31",
"ILS": ""
}
}
],
"length": "3027"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "104"
},
"Manston": {
"runways": [
{
"headings": [
{
"10": {
"magHeading": "102",
"Heading": "102",
"ILS": ""
}
},
{
"28": {
"magHeading": "282",
"Heading": "282",
"ILS": ""
}
}
],
"length": "9114"
},
{
"headings": [
{
"FIELD N": {
"magHeading": "57",
"Heading": "57",
"ILS": ""
}
},
{
"FIELD S": {
"magHeading": "237",
"Heading": "237",
"ILS": ""
}
}
],
"length": "5261"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "160"
},
"Biggin Hill": {
"runways": [
{
"headings": [
{
"23": {
"magHeading": "227",
"Heading": "228",
"ILS": ""
}
},
{
"05": {
"magHeading": "47",
"Heading": "48",
"ILS": ""
}
}
],
"length": "2430"
},
{
"headings": [
{
"28": {
"magHeading": "287",
"Heading": "288",
"ILS": ""
}
},
{
"10": {
"magHeading": "107",
"Heading": "108",
"ILS": ""
}
}
],
"length": "2594"
},
{
"headings": [
{
"21": {
"magHeading": "208",
"Heading": "208",
"ILS": ""
}
},
{
"03": {
"magHeading": "28",
"Heading": "28",
"ILS": ""
}
}
],
"length": "4939"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "552"
},
"Headcorn": {
"runways": [
{
"headings": [
{
"10": {
"magHeading": "92",
"Heading": "93",
"ILS": ""
}
},
{
"28": {
"magHeading": "272",
"Heading": "273",
"ILS": ""
}
}
],
"length": "3680"
},
{
"headings": [
{
"01": {
"magHeading": "12",
"Heading": "12",
"ILS": ""
}
},
{
"19": {
"magHeading": "192",
"Heading": "192",
"ILS": ""
}
}
],
"length": "3680"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "114"
},
"Detling": {
"runways": [
{
"headings": [
{
"FIELD S": {
"magHeading": "227",
"Heading": "227",
"ILS": ""
}
},
{
"FIELD N": {
"magHeading": "47",
"Heading": "47",
"ILS": ""
}
}
],
"length": "3482"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "623"
},
"Eastchurch": {
"runways": [
{
"headings": [
{
"10": {
"magHeading": "97",
"Heading": "97",
"ILS": ""
}
},
{
"28": {
"magHeading": "277",
"Heading": "277",
"ILS": ""
}
}
],
"length": "2983"
},
{
"headings": [
{
"20": {
"magHeading": "203",
"Heading": "203",
"ILS": ""
}
},
{
"02": {
"magHeading": "23",
"Heading": "23",
"ILS": ""
}
}
],
"length": "2983"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "40"
},
"Abbeville Drucat": {
"runways": [
{
"headings": [
{
"20": {
"magHeading": "203",
"Heading": "203",
"ILS": ""
}
},
{
"2": {
"magHeading": "23",
"Heading": "23",
"ILS": ""
}
}
],
"length": "4877"
},
{
"headings": [
{
"27": {
"magHeading": "270",
"Heading": "270",
"ILS": ""
}
},
{
"09": {
"magHeading": "90",
"Heading": "90",
"ILS": ""
}
}
],
"length": "4877"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "183"
},
"Hawkinge": {
"runways": [
{
"headings": [
{
"FIELD S": {
"magHeading": "180",
"Heading": "180",
"ILS": ""
}
},
{
"FIELD N": {
"magHeading": "0",
"Heading": "0",
"ILS": ""
}
}
],
"length": "2336"
},
{
"headings": [
{
"FIELD W ": {
"magHeading": "218",
"Heading": "219",
"ILS": ""
}
},
{
"FIELD E": {
"magHeading": "38",
"Heading": "39",
"ILS": ""
}
}
],
"length": "2336"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "524"
},
"Lympne": {
"runways": [
{
"headings": [
{
"FIELD E": {
"magHeading": "134",
"Heading": "134",
"ILS": ""
}
},
{
"FIELD W": {
"magHeading": "314",
"Heading": "314",
"ILS": ""
}
}
],
"length": "3054"
},
{
"headings": [
{
"FIELD N": {
"magHeading": "19",
"Heading": "19",
"ILS": ""
}
},
{
"FIELD S": {
"magHeading": "199",
"Heading": "199",
"ILS": ""
}
}
],
"length": "2706"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "351"
},
"Merville Calonne": {
"runways": [
{
"headings": [
{
"32": {
"magHeading": "318",
"Heading": "319",
"ILS": ""
}
},
{
"14": {
"magHeading": "138",
"Heading": "139",
"ILS": ""
}
}
],
"length": "3899"
},
{
"headings": [
{
"26": {
"magHeading": "258",
"Heading": "258",
"ILS": ""
}
},
{
"08": {
"magHeading": "78",
"Heading": "78",
"ILS": ""
}
}
],
"length": "3899"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "52"
},
"Dunkirk Mardyck": {
"runways": [
{
"headings": [
{
"08": {
"magHeading": "80",
"Heading": "81",
"ILS": ""
}
},
{
"26": {
"magHeading": "260",
"Heading": "261",
"ILS": ""
}
}
],
"length": "1839"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "16"
},
"Saint Omer Longuenesse": {
"runways": [
{
"headings": [
{
"08": {
"magHeading": "86",
"Heading": "87",
"ILS": ""
}
},
{
"26": {
"magHeading": "266",
"Heading": "267",
"ILS": ""
}
}
],
"length": "2001"
},
{
"headings": [
{
"FIELD S": {
"magHeading": "208",
"Heading": "208",
"ILS": ""
}
},
{
"FIELD N": {
"magHeading": "28",
"Heading": "28",
"ILS": ""
}
}
],
"length": "1762"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "219"
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,8 @@
#define FRAMERATE_TIME_INTERVAL 0.05
#define OLYMPUS_JSON_PATH "..\\olympus.json"
#define AIRCRAFT_DATABASE_PATH "..\\client\\public\\databases\\units\\aircraftdatabase.json"
#define HELICOPTER_DATABASE_PATH "..\\client\\public\\databases\\units\\helicopterdatabase.json"
#define GROUNDUNIT_DATABASE_PATH "..\\client\\public\\databases\\units\\groundunitdatabase.json"
#define NAVYUNIT_DATABASE_PATH "..\\client\\public\\databases\\units\\navyunitdatabase.json"
#define OLYMPUS_JSON_PATH "..\\..\\..\\..\\Config\\olympus.json"
#define AIRCRAFT_DATABASE_PATH "..\\databases\\aircraftdatabase.json"
#define HELICOPTER_DATABASE_PATH "..\\databases\\helicopterdatabase.json"
#define GROUNDUNIT_DATABASE_PATH "..\\databases\\groundunitdatabase.json"
#define NAVYUNIT_DATABASE_PATH "..\\databases\\navyunitdatabase.json"