Merge pull request #763 from Pax1601/747-improve-configurator-for-automatic-saved-games-folder-detection
747 improve configurator for automatic saved games folder detection
6
.gitignore
vendored
@ -22,4 +22,8 @@ client/public/javascripts/leaflet.nauticscale.js
|
||||
client/public/javascripts/L.Path.Drag.js
|
||||
/installer/archive/Scripts
|
||||
/installer/archive/Mods
|
||||
/installer/installer/DCSOlympus*.exe
|
||||
/installer/installer/DCSOlympus*.exe
|
||||
|
||||
L.Path.Drag.js
|
||||
leaflet-gesture-handling.css
|
||||
package-lock.json
|
||||
|
||||
@ -1,49 +1,59 @@
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
var cookieParser = require('cookie-parser');
|
||||
var logger = require('morgan');
|
||||
var fs = require('fs');
|
||||
var bodyParser = require('body-parser');
|
||||
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');
|
||||
|
||||
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');
|
||||
|
||||
var app = express();
|
||||
/* Load the config and create the express app */
|
||||
let config = {}
|
||||
console.log(`Loading configuration file from ${configLocation}`)
|
||||
if (fs.existsSync(configLocation)){
|
||||
let rawdata = fs.readFileSync(configLocation);
|
||||
config = JSON.parse(rawdata);
|
||||
}
|
||||
else {
|
||||
console.error("Error loading configuration file.")
|
||||
return undefined;
|
||||
}
|
||||
var app = express();
|
||||
|
||||
app.use(logger('dev'));
|
||||
app.use(bodyParser.json({limit: '50mb'}));
|
||||
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
|
||||
app.use(cookieParser());
|
||||
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')));
|
||||
|
||||
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);
|
||||
/* 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');
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
let rawdata = fs.readFileSync('../olympus.json');
|
||||
let config = JSON.parse(rawdata);
|
||||
if (config["server"] != undefined)
|
||||
app.get('/config', (req, res) => res.send(config["server"]));
|
||||
|
||||
module.exports = app;
|
||||
|
||||
const DemoDataGenerator = require('./demo.js');
|
||||
var demoDataGenerator = new DemoDataGenerator(app, config);
|
||||
|
||||
|
||||
|
||||
|
||||
116
client/bin/demo
Normal file
@ -0,0 +1,116 @@
|
||||
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* _____ _____ _____ ____ _ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | __ \\ / ____|/ ____| / __ \\| | *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | | | | | | (___ | | | | |_ _ _ __ ___ _ __ _ _ ___ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | | | | | \\___ \\ | | | | | | | | '_ ` _ \\| '_ \\| | | / __| *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | |__| | |____ ____) | | |__| | | |_| | | | | | | |_) | |_| \\__ \\ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* |_____/ \\_____|_____/ \\____/|_|\\__, |_| |_| |_| .__/ \\__,_|___/ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* __/ | | | *");
|
||||
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 DEMO Backend Server starts up...");
|
||||
|
||||
var fs = require('fs');
|
||||
let rawdata = fs.readFileSync('../olympus.json');
|
||||
let config = JSON.parse(rawdata);
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var app = require('../demo');
|
||||
var debug = require('debug')('client:server');
|
||||
var http = require('http');
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var configPort = null;
|
||||
if (config["server"] != undefined && config["server"]["port"] != undefined) {
|
||||
configPort = config["server"]["port"];
|
||||
}
|
||||
|
||||
var port = normalizePort(configPort || '3000');
|
||||
app.set('port', port);
|
||||
console.log("Express server listening on port: " + port)
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
||||
|
||||
console.log("DCS Olympus DEMO Backend Server {{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}} started correctly!")
|
||||
console.log("Waiting for connections...")
|
||||
|
||||
process.title = `DCS Olympus DEMO Backend Server {{OLYMPUS_VERSION_NUMBER}} (${port})`;
|
||||
133
client/bin/www
@ -1,4 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
const yargs = require('yargs');
|
||||
var fs = require('fs');
|
||||
|
||||
/* Define configuration parameter */
|
||||
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', "* _____ _____ _____ ____ _ *");
|
||||
@ -12,107 +17,89 @@ 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);
|
||||
/* Load the configuration file */
|
||||
var clientPort = 0;
|
||||
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, aborting!");
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
/* Wait a bit before closing the window */
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
return;
|
||||
}
|
||||
|
||||
var app = require('../app');
|
||||
/* Load the dependencies. The app is loaded providing the configuration file location */
|
||||
var app = require('../app')(args["config"]);
|
||||
var debug = require('debug')('client:server');
|
||||
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');
|
||||
/* Normalize port */
|
||||
var port = normalizePort(clientPort);
|
||||
app.set('port', port);
|
||||
console.log("Express server listening on port: " + port)
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
/* Create HTTP server */
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
/* Listen on provided port, on all network interfaces. */
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
/* Normalize a port into a number, string, or false. */
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
if (isNaN(port)) {
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
if (port >= 0) {
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
/* Event listener for HTTP server "error" event. */
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
/* Handle specific listen errors with friendly messages */
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
/* Event listener for HTTP server "listening" event. */
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
||||
|
||||
/* Final user friendly printing */
|
||||
console.log("DCS Olympus server {{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}} started correctly!")
|
||||
console.log("Waiting for connections...")
|
||||
|
||||
process.title = `DCS Olympus server {{OLYMPUS_VERSION_NUMBER}} (${port})`;
|
||||
57
client/client.js
Normal file
@ -0,0 +1,57 @@
|
||||
const { app, BrowserWindow } = require('electron/main')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const { spawn } = require('child_process');
|
||||
const yargs = require('yargs');
|
||||
|
||||
yargs.alias('c', 'config').describe('c', 'olympus.json config location').string('rp');
|
||||
args = yargs.argv;
|
||||
|
||||
console.log(`Config location: ${args["config"]}`)
|
||||
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");
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
const win = new BrowserWindow({
|
||||
icon: "./../img/olympus.ico"
|
||||
})
|
||||
|
||||
win.loadURL(`http://localhost:${clientPort}`);
|
||||
win.setMenuBarVisibility(false);
|
||||
win.maximize();
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const server = spawn('node', [path.join('.', 'bin', 'www'), "--config", args["config"]]);
|
||||
|
||||
server.stdout.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
|
||||
server.stderr.on('data', (data) => {
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
server.on('close', (code) => {
|
||||
console.log(`Child process exited with code ${code}`);
|
||||
});
|
||||
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
1
client/client.vbs
Normal file
@ -0,0 +1 @@
|
||||
CreateObject("Wscript.Shell").Run "npm run client -- --config """&WScript.Arguments(0)&"""", 0
|
||||
@ -3,7 +3,11 @@ const path = require('path')
|
||||
const yargs = require('yargs');
|
||||
const prompt = require('prompt-sync')({sigint: true});
|
||||
const sha256 = require('sha256');
|
||||
const jsonPath = path.join('..', 'olympus.json');
|
||||
var jsonPath = path.join('..', 'olympus.json');
|
||||
var regedit = require('regedit')
|
||||
|
||||
const shellFoldersKey = 'HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders'
|
||||
const saveGamesKey = '{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}'
|
||||
|
||||
/* Set the acceptable values */
|
||||
yargs.alias('a', 'address').describe('a', 'Backend address').string('a');
|
||||
@ -12,6 +16,7 @@ yargs.alias('c', 'clientPort').describe('c', 'Client port').number('c');
|
||||
yargs.alias('p', 'gameMasterPassword').describe('p', 'Game Master password').string('p');
|
||||
yargs.alias('bp', 'blueCommanderPassword').describe('bp', 'Blue Commander password').string('bp');
|
||||
yargs.alias('rp', 'redCommanderPassword').describe('rp', 'Red Commander password').string('rp');
|
||||
yargs.alias('d', 'directory').describe('d', 'Directory where the DCS Olympus configurator is located').string('rp');
|
||||
args = yargs.argv;
|
||||
|
||||
async function run() {
|
||||
@ -30,21 +35,6 @@ async function run() {
|
||||
if (args.address === undefined && args.clientPort === undefined && args.backendPort === undefined &&
|
||||
args.gameMasterPassword === undefined && args.blueCommanderPassword === undefined && args.redCommanderPassword === undefined) {
|
||||
|
||||
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* _____ _____ _____ ____ _ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | __ \\ / ____|/ ____| / __ \\| | *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | | | | | | (___ | | | | |_ _ _ __ ___ _ __ _ _ ___ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | | | | | \\___ \\ | | | | | | | | '_ ` _ \\| '_ \\| | | / __| *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | |__| | |____ ____) | | |__| | | |_| | | | | | | |_) | |_| \\__ \\ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* |_____/ \\_____|_____/ \\____/|_|\\__, |_| |_| |_| .__/ \\__,_|___/ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* __/ | | | *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* |___/ |_| *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
|
||||
console.log('\x1b[36m%s\x1b[0m', "");
|
||||
|
||||
console.log("DCS Olympus configurator {{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}");
|
||||
console.log("");
|
||||
|
||||
var newValue;
|
||||
var result;
|
||||
|
||||
@ -113,5 +103,65 @@ async function run() {
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
}
|
||||
|
||||
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* _____ _____ _____ ____ _ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | __ \\ / ____|/ ____| / __ \\| | *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | | | | | | (___ | | | | |_ _ _ __ ___ _ __ _ _ ___ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | | | | | \\___ \\ | | | | | | | | '_ ` _ \\| '_ \\| | | / __| *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | |__| | |____ ____) | | |__| | | |_| | | | | | | |_) | |_| \\__ \\ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* |_____/ \\_____|_____/ \\____/|_|\\__, |_| |_| |_| .__/ \\__,_|___/ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* __/ | | | *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* |___/ |_| *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
|
||||
console.log('\x1b[36m%s\x1b[0m', "");
|
||||
|
||||
console.log("DCS Olympus configurator {{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}");
|
||||
console.log("");
|
||||
|
||||
/* Run the configurator */
|
||||
run();
|
||||
if (args.directory) {
|
||||
jsonPath = path.join(args.directory, "olympus.json");
|
||||
}
|
||||
else {
|
||||
/* Automatically detect possible DCS installation folders */
|
||||
regedit.list(shellFoldersKey, function(err, result) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
else {
|
||||
if (result[shellFoldersKey] !== undefined && result[shellFoldersKey]["exists"] && result[shellFoldersKey]['values'][saveGamesKey] !== undefined && result[shellFoldersKey]['values'][saveGamesKey]['value'] !== undefined)
|
||||
{
|
||||
const searchpath = result[shellFoldersKey]['values'][saveGamesKey]['value'];
|
||||
const folders = fs.readdirSync(searchpath);
|
||||
var options = [];
|
||||
folders.forEach((folder) => {
|
||||
if (fs.existsSync(path.join(searchpath, folder, "Logs", "dcs.log"))) {
|
||||
options.push(folder);
|
||||
}
|
||||
})
|
||||
console.log("The following DCS Saved Games folders have been automatically detected.")
|
||||
options.forEach((folder, index) => {
|
||||
console.log(`(${index + 1}) ${folder}`)
|
||||
});
|
||||
while (true) {
|
||||
var newValue = prompt(`Please choose a folder onto which the configurator shall operate by typing the associated number: `)
|
||||
result = Number(newValue);
|
||||
|
||||
if (!isNaN(result) && Number.isInteger(result) && result > 0 && result <= options.length) {
|
||||
jsonPath = path.join(searchpath, options[result - 1], "Config", "olympus.json");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
console.log(`Please type a number between 1 and ${options.length}`);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
console.error("An error occured while trying to fetch the location of the DCS folder. Please type the folder location manually.")
|
||||
jsonPath = path.join(prompt(`DCS Saved Games folder location: `), "olympus.json");
|
||||
}
|
||||
console.log(`Configurator will run on ${jsonPath}, if this is incorrect please restart the configurator`)
|
||||
run();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
start cmd /k "npm run start"
|
||||
start cmd /k "watchify .\src\index.ts --debug -o .\public\javascripts\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]
|
||||
1
client/demo.bat
Normal file
@ -0,0 +1 @@
|
||||
node .\bin\demo
|
||||
@ -1,7 +1,17 @@
|
||||
const { random } = require('@turf/turf');
|
||||
var basicAuth = require('express-basic-auth')
|
||||
var logger = require('morgan');
|
||||
var enc = new TextEncoder();
|
||||
|
||||
var express = require('express');
|
||||
var fs = require('fs');
|
||||
|
||||
let rawdata = fs.readFileSync('../olympus.json');
|
||||
let config = JSON.parse(rawdata);
|
||||
|
||||
var app = express();
|
||||
|
||||
app.use(logger('dev'));
|
||||
|
||||
const aircraftDatabase = require('./public/databases/units/aircraftdatabase.json');
|
||||
const helicopterDatabase = require('./public/databases/units/helicopterdatabase.json');
|
||||
const groundUnitDatabase = require('./public/databases/units/groundunitdatabase.json');
|
||||
@ -16,16 +26,16 @@ const DEMO_WEAPONS_DATA = {
|
||||
class DemoDataGenerator {
|
||||
constructor(app, config)
|
||||
{
|
||||
app.get('/demo/units', (req, res) => this.units(req, res));
|
||||
app.get('/demo/weapons', (req, res) => this.weapons(req, res));
|
||||
app.get('/demo/logs', (req, res) => this.logs(req, res));
|
||||
app.get('/demo/bullseyes', (req, res) => this.bullseyes(req, res));
|
||||
app.get('/demo/airbases', (req, res) => this.airbases(req, res));
|
||||
app.get('/demo/mission', (req, res) => this.mission(req, res));
|
||||
app.get('/demo/commands', (req, res) => this.command(req, res));
|
||||
app.put('/demo', (req, res) => this.put(req, res));
|
||||
app.get('/olympus/units', (req, res) => this.units(req, res));
|
||||
app.get('/olympus/weapons', (req, res) => this.weapons(req, res));
|
||||
app.get('/olympus/logs', (req, res) => this.logs(req, res));
|
||||
app.get('/olympus/bullseyes', (req, res) => this.bullseyes(req, res));
|
||||
app.get('/olympus/airbases', (req, res) => this.airbases(req, res));
|
||||
app.get('/olympus/mission', (req, res) => this.mission(req, res));
|
||||
app.get('/olympus/commands', (req, res) => this.command(req, res));
|
||||
app.put('/olympus', (req, res) => this.put(req, res));
|
||||
|
||||
app.use('/demo', basicAuth({
|
||||
app.use('/olympus', basicAuth({
|
||||
users: {
|
||||
'admin': config["authentication"]["gameMasterPassword"],
|
||||
'blue': config["authentication"]["blueCommanderPassword"],
|
||||
@ -511,4 +521,6 @@ class DemoDataGenerator {
|
||||
|
||||
}
|
||||
|
||||
module.exports = DemoDataGenerator;
|
||||
var demoDataGenerator = new DemoDataGenerator(app, config);
|
||||
|
||||
module.exports = app;
|
||||
|
||||
@ -1,2 +1 @@
|
||||
call npm install --omit=dev
|
||||
call npm install yargs prompt-sync sha256 tcp-ping-port
|
||||
npm install --omit=dev
|
||||
4014
client/package-lock.json
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "DCSOlympus",
|
||||
"node-main": "./bin/www",
|
||||
"main": "http://localhost:3000",
|
||||
"main": "client.js",
|
||||
"version": "{{OLYMPUS_VERSION_NUMBER}}",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@ -10,27 +10,37 @@
|
||||
"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\"",
|
||||
"watch": "watchify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]"
|
||||
"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 ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@turf/turf": "^6.5.0",
|
||||
"appjs": "^0.0.20",
|
||||
"appjs-win32": "^0.0.19",
|
||||
"body-parser": "^1.20.2",
|
||||
"cookie-parser": "~1.4.4",
|
||||
"debug": "~2.6.9",
|
||||
"ejs": "^3.1.8",
|
||||
"express": "~4.16.1",
|
||||
"electron": "^28.0.0",
|
||||
"express": "^4.18.2",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"js-sha256": "^0.10.1",
|
||||
"leaflet-gesture-handling": "^1.2.2",
|
||||
"morgan": "~1.9.1",
|
||||
"node-hide-console-window": "^2.2.0",
|
||||
"open": "^10.0.0",
|
||||
"prompt-sync": "^4.2.0",
|
||||
"regedit": "^5.1.2",
|
||||
"save": "^2.9.0",
|
||||
"sha256": "^0.2.0",
|
||||
"srtm-elevation": "^2.1.2",
|
||||
"uuid": "^9.0.1"
|
||||
"tcp-ping-port": "^1.0.1",
|
||||
"uuid": "^9.0.1",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.21.4",
|
||||
"@tanem/svg-injector": "^10.1.68",
|
||||
"@turf/turf": "^6.5.0",
|
||||
"@types/formatcoords": "^1.1.0",
|
||||
"@types/geojson": "^7946.0.10",
|
||||
"@types/leaflet": "^1.9.0",
|
||||
@ -46,22 +56,16 @@
|
||||
"geodesy": "^1.1.2",
|
||||
"leaflet": "^1.9.3",
|
||||
"leaflet-control-mini-map": "^0.4.0",
|
||||
"leaflet-gesture-handling": "^1.2.2",
|
||||
"leaflet-path-drag": "*",
|
||||
"leaflet.nauticscale": "^1.1.0",
|
||||
"nodemon": "^2.0.20",
|
||||
"nodemon": "^3.0.2",
|
||||
"requirejs": "^2.3.6",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tinyify": "^4.0.0",
|
||||
"tsify": "^5.0.4",
|
||||
"tslib": "latest",
|
||||
"typescript": "^4.9.4",
|
||||
"usng.js": "^0.4.5",
|
||||
"watchify": "^4.0.0"
|
||||
},
|
||||
"window": {
|
||||
"width": 1000,
|
||||
"height": 800,
|
||||
"position": "center",
|
||||
"icon": "public/images/icon.png"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
L.Control.ScaleNautic = L.Control.Scale.extend({
|
||||
options: {
|
||||
nautic: false
|
||||
},
|
||||
|
||||
_addScales: function(options, className, container) {
|
||||
L.Control.Scale.prototype._addScales.call(this, options, className, container);
|
||||
L.setOptions(options);
|
||||
if (this.options.nautic) {
|
||||
this._nScale = L.DomUtil.create('div', className, container);
|
||||
}
|
||||
},
|
||||
|
||||
_updateScales: function (maxMeters) {
|
||||
L.Control.Scale.prototype._updateScales.call(this, maxMeters);
|
||||
if (this.options.nautic && maxMeters) {
|
||||
this._updateNautic(maxMeters);
|
||||
}
|
||||
},
|
||||
|
||||
_updateNautic: function (maxMeters) {
|
||||
var scale = this._nScale,
|
||||
maxNauticalMiles = maxMeters / 1852, nauticalMiles;
|
||||
|
||||
if(maxMeters >= 1852) {
|
||||
nauticalMiles = L.Control.Scale.prototype._getRoundNum.call(this, maxNauticalMiles);
|
||||
} else {
|
||||
nauticalMiles = maxNauticalMiles > 0.1 ? Math.round(maxNauticalMiles * 10) / 10 : Math.round(maxNauticalMiles * 100) / 100;
|
||||
}
|
||||
|
||||
scale.style.width = Math.round(this.options.maxWidth * (nauticalMiles / maxNauticalMiles)) - 10 + 'px';
|
||||
scale.innerHTML = nauticalMiles + ' nm';
|
||||
}
|
||||
});
|
||||
|
||||
L.control.scalenautic = function (options) {
|
||||
return new L.Control.ScaleNautic(options);
|
||||
};
|
||||
@ -1,47 +0,0 @@
|
||||
@-webkit-keyframes leaflet-gestures-fadein {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
@keyframes leaflet-gestures-fadein {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
.leaflet-container:after {
|
||||
-webkit-animation: leaflet-gestures-fadein 0.8s backwards;
|
||||
animation: leaflet-gestures-fadein 0.8s backwards;
|
||||
color: #fff;
|
||||
font-family: "Roboto", Arial, sans-serif;
|
||||
font-size: 22px;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 461;
|
||||
pointer-events: none; }
|
||||
|
||||
.leaflet-gesture-handling-touch-warning:after,
|
||||
.leaflet-gesture-handling-scroll-warning:after {
|
||||
-webkit-animation: leaflet-gestures-fadein 0.8s forwards;
|
||||
animation: leaflet-gestures-fadein 0.8s forwards; }
|
||||
|
||||
.leaflet-gesture-handling-touch-warning:after {
|
||||
content: attr(data-gesture-handling-touch-content); }
|
||||
|
||||
.leaflet-gesture-handling-scroll-warning:after {
|
||||
content: attr(data-gesture-handling-scroll-content); }
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,23 +1,8 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
var themesMap = {};
|
||||
|
||||
router.get('/theme/*', function (req, res, next) {
|
||||
/* If this is the first time this session makes a request, create a uuid and save it to the map. Default theme is the olympus theme */
|
||||
if (!req.cookies.id) {
|
||||
const id = uuidv4();
|
||||
res.cookie('id', id, { httpOnly: true });
|
||||
themesMap[id] = "olympus";
|
||||
reqTheme = "olympus";
|
||||
}
|
||||
else {
|
||||
/* If it is present, recover the session theme from the map */
|
||||
if (!(req.cookies.id in themesMap))
|
||||
themesMap[req.cookies.id] = "olympus";
|
||||
reqTheme = themesMap[req.cookies.id];
|
||||
}
|
||||
var reqTheme = "olympus";
|
||||
|
||||
/* Yes, this in an easter egg! :D Feel free to ignore it, or activate the parrot theme to check what it does. Why parrots? The story is a bit long, come to the Discord and ask :D */
|
||||
if (reqTheme === "parrot" && !req.url.includes(".css"))
|
||||
@ -27,15 +12,6 @@ router.get('/theme/*', function (req, res, next) {
|
||||
});
|
||||
|
||||
router.put('/theme/:newTheme', function (req, res, next) {
|
||||
/* Add the theme to the map, if this session already has an id */
|
||||
const newTheme = req.params.newTheme;
|
||||
if (req.cookies.id) {
|
||||
themesMap[req.cookies.id] = newTheme;
|
||||
console.log("Theme set to " + newTheme + " for session " + req.cookies.id);
|
||||
} else {
|
||||
console.log("Failed to set theme to " + newTheme + ", no session id");
|
||||
}
|
||||
|
||||
res.end("Ok");
|
||||
});
|
||||
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { exec } = require("child_process");
|
||||
const { tcpPingPort } = require("tcp-ping-port")
|
||||
const jsonPath = path.join('..', 'olympus.json');
|
||||
const options = {
|
||||
socketTimeout: 1000
|
||||
}
|
||||
|
||||
var attempt = 0;
|
||||
const maxAttempt = 3;
|
||||
|
||||
function checkServer() {
|
||||
console.log("Checking DCS Olympus server availability...");
|
||||
tcpPingPort(`localhost`, json["client"]["port"], options).then(res => {
|
||||
if (res.online) {
|
||||
run();
|
||||
}
|
||||
else {
|
||||
if (attempt < maxAttempt) {
|
||||
attempt++;
|
||||
console.log(`DCS Olympus server not found, starting it up! Attempt ${attempt} of ${maxAttempt}`);
|
||||
startServer();
|
||||
} else {
|
||||
console.log("Failed to start DCS Olympus server!")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function startServer() {
|
||||
exec(`START /min "" "../DCS Olympus Server.lnk"`)
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
checkServer();
|
||||
}
|
||||
|
||||
function run() {
|
||||
exec(`start http://localhost:${json["client"]["port"]}`)
|
||||
}
|
||||
|
||||
/* Check that we can read the json */
|
||||
if (fs.existsSync(jsonPath)) {
|
||||
var json = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
|
||||
|
||||
checkServer();
|
||||
}
|
||||
1
client/server.vbs
Normal file
@ -0,0 +1 @@
|
||||
CreateObject("Wscript.Shell").Run "npm run start -- --config """&WScript.Arguments(0)&"""", 1
|
||||
@ -11,11 +11,6 @@ declare global {
|
||||
function getOlympusPlugin(): OlympusPlugin;
|
||||
}
|
||||
|
||||
export interface ConfigurationOptions {
|
||||
port: number;
|
||||
address: string;
|
||||
}
|
||||
|
||||
export interface ContextMenuOption {
|
||||
tooltip: string;
|
||||
src: string;
|
||||
|
||||
@ -24,13 +24,11 @@ import { aircraftDatabase } from "./unit/databases/aircraftdatabase";
|
||||
import { helicopterDatabase } from "./unit/databases/helicopterdatabase";
|
||||
import { groundUnitDatabase } from "./unit/databases/groundunitdatabase";
|
||||
import { navyUnitDatabase } from "./unit/databases/navyunitdatabase";
|
||||
import { ConfigurationOptions } from "./interfaces";
|
||||
import { UnitListPanel } from "./panels/unitlistpanel";
|
||||
import { ContextManager } from "./context/contextmanager";
|
||||
import { Context } from "./context/context";
|
||||
|
||||
var VERSION = "{{OLYMPUS_VERSION_NUMBER}}";
|
||||
var DEBUG = false;
|
||||
|
||||
export class OlympusApp {
|
||||
/* Global data */
|
||||
@ -216,19 +214,8 @@ export class OlympusApp {
|
||||
|
||||
this.#pluginsManager = new PluginsManager();
|
||||
|
||||
/* Load the config file from the app server*/
|
||||
this.getServerManager().getConfig((config: ConfigurationOptions) => {
|
||||
if (config && config.address != undefined && config.port != undefined) {
|
||||
const address = config.address;
|
||||
const port = config.port;
|
||||
if (typeof address === 'string' && typeof port == 'number') {
|
||||
this.getServerManager().setAddress(address == "*" ? window.location.hostname : address, port);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error('Could not read configuration file');
|
||||
}
|
||||
});
|
||||
/* Set the address of the server */
|
||||
this.getServerManager().setAddress(window.location.href.split('?')[0]);
|
||||
|
||||
/* Setup all global events */
|
||||
this.#setupEvents();
|
||||
@ -294,16 +281,7 @@ export class OlympusApp {
|
||||
});
|
||||
|
||||
const shortcutManager = this.getShortcutManager();
|
||||
shortcutManager.addKeyboardShortcut("toggleDemo", {
|
||||
"altKey": false,
|
||||
"callback": () => {
|
||||
if (DEBUG === true) this.getServerManager().toggleDemoEnabled();
|
||||
},
|
||||
"code": "KeyT",
|
||||
"context": "olympus",
|
||||
"ctrlKey": false,
|
||||
"shiftKey": false
|
||||
}).addKeyboardShortcut("togglePause", {
|
||||
shortcutManager.addKeyboardShortcut("togglePause", {
|
||||
"altKey": false,
|
||||
"callback": () => {
|
||||
this.getServerManager().setPaused(!this.getServerManager().getPaused());
|
||||
|
||||
@ -11,13 +11,11 @@ import { zeroAppend } from '../other/utils';
|
||||
export class ServerManager {
|
||||
#connected: boolean = false;
|
||||
#paused: boolean = false;
|
||||
#REST_ADDRESS = "http://localhost:30000/olympus";
|
||||
#DEMO_ADDRESS = window.location.href.split('?')[0] + "demo"; /* Remove query parameters */
|
||||
#REST_ADDRESS = "http://localhost:3001/olympus";
|
||||
#username = "";
|
||||
#password = "";
|
||||
#sessionHash: string | null = null;
|
||||
#lastUpdateTimes: { [key: string]: number } = {}
|
||||
#demoEnabled = false;
|
||||
#previousMissionElapsedTime: number = 0; // Track if mission elapsed time is increasing (i.e. is the server paused)
|
||||
#serverIsPaused: boolean = false;
|
||||
#intervals: number[] = [];
|
||||
@ -32,10 +30,6 @@ export class ServerManager {
|
||||
this.#lastUpdateTimes[MISSION_URI] = Date.now();
|
||||
}
|
||||
|
||||
toggleDemoEnabled() {
|
||||
this.#demoEnabled = !this.#demoEnabled;
|
||||
}
|
||||
|
||||
setCredentials(newUsername: string, newPassword: string) {
|
||||
this.#username = newUsername;
|
||||
this.#password = newPassword;
|
||||
@ -63,7 +57,7 @@ export class ServerManager {
|
||||
optionsString = `commandHash=${options.commandHash}`;
|
||||
|
||||
/* On the connection */
|
||||
xmlHttp.open("GET", `${this.#demoEnabled ? this.#DEMO_ADDRESS : this.#REST_ADDRESS}/${uri}${optionsString ? `?${optionsString}` : ''}`, true);
|
||||
xmlHttp.open("GET", `${this.#REST_ADDRESS}/${uri}${optionsString ? `?${optionsString}` : ''}`, true);
|
||||
|
||||
/* If provided, set the credentials */
|
||||
if (this.#username && this.#password)
|
||||
@ -106,7 +100,7 @@ export class ServerManager {
|
||||
|
||||
PUT(request: object, callback: CallableFunction) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("PUT", this.#demoEnabled ? this.#DEMO_ADDRESS : this.#REST_ADDRESS);
|
||||
xmlHttp.open("PUT", this.#REST_ADDRESS);
|
||||
xmlHttp.setRequestHeader("Content-Type", "application/json");
|
||||
if (this.#username && this.#password)
|
||||
xmlHttp.setRequestHeader("Authorization", "Basic " + btoa(`${this.#username}:${this.#password}`));
|
||||
@ -130,8 +124,8 @@ export class ServerManager {
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
setAddress(address: string, port: number) {
|
||||
this.#REST_ADDRESS = `http://${address}:${port}/olympus`
|
||||
setAddress(address: string) {
|
||||
this.#REST_ADDRESS = `${address}olympus`
|
||||
console.log(`Setting REST address to ${this.#REST_ADDRESS}`)
|
||||
}
|
||||
|
||||
|
||||
@ -43,21 +43,27 @@ fs.readFile("./version.json", "utf8", (error, data) => {
|
||||
}
|
||||
if (data.search(/{{OLYMPUS_VERSION_NUMBER}}/g) >= 0) {
|
||||
console.log(`Replacing version in ${file}`);
|
||||
|
||||
|
||||
data = data.replace(/{{OLYMPUS_VERSION_NUMBER}}/g, `v${major}.${minor}.${minorminor}`);
|
||||
data = data.replace(/{{OLYMPUS_COMMIT_HASH}}/g, revision);
|
||||
fileChanged = true;
|
||||
}
|
||||
|
||||
if (data.search(/{{OLYMPUS_VS_VERSION_NUMBER_1}}/g) >= 0) {
|
||||
if (data.search(/FILEVERSION \d,\d,\d/g) >= 0) {
|
||||
console.log(`Replacing version in ${file}`);
|
||||
var data = data.replace(/{{OLYMPUS_VS_VERSION_NUMBER_1}}/g, `${major},${minor},${minorminor}`);
|
||||
var data = data.replace(/FILEVERSION \d,\d,\d/g, `FILEVERSION ${major},${minor},${minorminor}`);
|
||||
fileChanged = true;
|
||||
}
|
||||
|
||||
if (data.search(/{{OLYMPUS_VS_VERSION_NUMBER_2}}/g) >= 0) {
|
||||
if (data.search(/VALUE "FileVersion", "\d.\d.\d.0"/g) >= 0) {
|
||||
console.log(`Replacing version in ${file}`);
|
||||
data = data.replace(/{{OLYMPUS_VS_VERSION_NUMBER_2}}/g, `${major}.${minor}.${minorminor}`);
|
||||
data = data.replace(/VALUE "FileVersion", "\d.\d.\d.0"/g, `VALUE "FileVersion", "${major}.${minor}.${minorminor}.0"`);
|
||||
fileChanged = true;
|
||||
}
|
||||
|
||||
if (data.search(/VALUE "ProductVersion", "\d.\d.\d.0"/g) >= 0) {
|
||||
console.log(`Replacing version in ${file}`);
|
||||
data = data.replace(/VALUE "ProductVersion", "\d.\d.\d.0"/g, `VALUE "ProductVersion", "${major}.${minor}.${minorminor}.0"`);
|
||||
fileChanged = true;
|
||||
}
|
||||
|
||||
|
||||
@ -3,15 +3,16 @@
|
||||
[Setup]
|
||||
AppName=DCS Olympus
|
||||
AppVerName=DCS Olympus {#version}
|
||||
DefaultDirName={usersavedgames}\DCS.openbeta
|
||||
DefaultDirName={usersavedgames}\DCS Olympus
|
||||
DefaultGroupName=DCSOlympus
|
||||
OutputBaseFilename=DCSOlympus_{#version}
|
||||
UninstallFilesDir={app}\Mods\Services\Olympus
|
||||
UninstallFilesDir={app}
|
||||
SetupIconFile="..\img\olympus.ico"
|
||||
DirExistsWarning=no
|
||||
AppendDefaultDirName=no
|
||||
LicenseFile="..\LEGAL.txt"
|
||||
ChangesEnvironment=yes
|
||||
PrivilegesRequired=lowest
|
||||
InfoBeforeFile="..\notes.txt"
|
||||
|
||||
[Messages]
|
||||
WizardSelectDir=Select the location of DCS's Saved Games folder
|
||||
@ -20,511 +21,58 @@ SelectDirLabel3=DCS Olympus must be installed within DCS's Saved Games folder.
|
||||
SelectDirBrowseLabel=This is the detected path. If this is incorrect, click Browse to set the correct folder.
|
||||
|
||||
[Tasks]
|
||||
; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required.
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
Name: "desktopicon"; Description: "Create desktop shortcut"; GroupDescription: "Additional icons"; Flags: unchecked
|
||||
Name: "installmodules"; Description: "Install node.js modules"; GroupDescription: "Dependencies";
|
||||
|
||||
[Files]
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
Source: "..\olympus.json"; DestDir: "{app}\Mods\Services\Olympus"; Flags: onlyifdoesntexist
|
||||
Source: "..\olympus.json"; DestDir: "{app}";
|
||||
|
||||
Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts\Hooks"; Flags: ignoreversion
|
||||
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\templates.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\mist.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\mods.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\OlympusCommand.lua"; DestDir: "{app}\mod\scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\unitPayloads.lua"; DestDir: "{app}\mod\scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\templates.lua"; DestDir: "{app}\mod\scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\mist.lua"; DestDir: "{app}\mod\scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\mods.lua"; DestDir: "{app}\mod\scripts"; Flags: ignoreversion
|
||||
|
||||
Source: "..\mod\*"; DestDir: "{app}\Mods\Services\Olympus"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\mod\*"; DestDir: "{app}\mod"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\bin\*.dll"; DestDir: "{app}\mod\bin"; Flags: ignoreversion;
|
||||
Source: "..\client\public\databases\*"; DestDir: "{app}\mod\databases"; Flags: ignoreversion recursesubdirs;
|
||||
|
||||
Source: "..\bin\*.dll"; DestDir: "{app}\Mods\Services\Olympus\bin"; Flags: ignoreversion;
|
||||
Source: "..\client\bin\*"; DestDir: "{app}\client\bin"; Flags: ignoreversion;
|
||||
Source: "..\client\public\*"; DestDir: "{app}\client\public"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\routes\*"; DestDir: "{app}\client\routes"; Flags: ignoreversion recursesubdirs;
|
||||
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: "..\client\bin\*"; DestDir: "{app}\Mods\Services\Olympus\client\bin"; Flags: ignoreversion;
|
||||
Source: "..\client\public\*"; DestDir: "{app}\Mods\Services\Olympus\client\public"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\routes\*"; DestDir: "{app}\Mods\Services\Olympus\client\routes"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\views\*"; DestDir: "{app}\Mods\Services\Olympus\client\views"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\app.js"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\demo.js"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\package.json"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\run_client.js"; DestDir: "{app}\Mods\Services\Olympus\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: "..\client\configurator.js"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\install.bat"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\img\olympus.ico"; DestDir: "{app}\img"; Flags: ignoreversion;
|
||||
Source: "..\img\olympus_server.ico"; DestDir: "{app}\img"; Flags: ignoreversion;
|
||||
Source: "..\img\olympus_configurator.ico"; DestDir: "{app}\img"; Flags: ignoreversion;
|
||||
Source: "..\img\configurator_logo.png"; DestDir: "{app}\img"; Flags: ignoreversion;
|
||||
Source: "..\img\OlympusLogoFinal_4k.png"; DestDir: "{app}\img"; Flags: ignoreversion;
|
||||
|
||||
Source: "..\img\olympus.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
Source: "..\img\olympus_server.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
Source: "..\img\olympus_configurator.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
Source: "..\img\configurator_logo.png"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
|
||||
Source: "..\LEGAL.txt"; DestDir: "{app}\Mods\Services\Olympus"; Flags: ignoreversion;
|
||||
Source: "..\LEGAL.txt"; DestDir: "{app}"; Flags: ignoreversion;
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\Mods\Services\Olympus\client\install.bat"; WorkingDir:"{app}\Mods\Services\Olympus\client"; Flags: runhidden; StatusMsg: "Installing node.js modules, this may take some time...";
|
||||
Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; Parameters: configurator.js -a {code:GetAddress} -c {code:GetClientPort} -b {code:GetBackendPort} -p {code:GetPassword} --bp {code:GetBluePassword} --rp {code:GetRedPassword}; Check: CheckCallConfigurator; Flags: runhidden; StatusMsg: "Applying configuration...";
|
||||
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\manager.vbs"; WorkingDir: "{app}\manager"; Description: "Launch the Olympus manager"; Flags: postinstall shellexec;
|
||||
|
||||
[Icons]
|
||||
Name: "{userdesktop}\DCS Olympus Client"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico"; Check: CheckLocalInstall; Parameters: "run_client.js"; Flags: runminimized;
|
||||
Name: "{userdesktop}\DCS Olympus Server"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_server.ico"; Parameters: ".\bin\www";
|
||||
Name: "{userdesktop}\DCS Olympus Configurator"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_configurator.ico"; Check: CheckServerInstall; Parameters: "configurator.js";
|
||||
Name: "{app}\Mods\Services\Olympus\DCS Olympus Client"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico"; Check: CheckLocalInstall; Parameters: "run_client.js"; Flags: runminimized;
|
||||
Name: "{app}\Mods\Services\Olympus\DCS Olympus Server"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_server.ico"; Parameters: ".\bin\www";
|
||||
Name: "{app}\Mods\Services\Olympus\DCS Olympus Configurator"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_configurator.ico"; Check: CheckServerInstall; Parameters: "configurator.js";
|
||||
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}\Mods\Services\Olympus"
|
||||
|
||||
[Code]
|
||||
var
|
||||
lblLocalInstall: TLabel;
|
||||
lblLocalInstallInstructions: TNewStaticText;
|
||||
lblServerInstall: TLabel;
|
||||
lblServerInstallInstructions: TNewStaticText;
|
||||
lblKeepOld: TLabel;
|
||||
lblClientPort: TLabel;
|
||||
lblBackendPort: TLabel;
|
||||
lblPassword: TLabel;
|
||||
lblBluePassword: TLabel;
|
||||
lblRedPassword: TLabel;
|
||||
radioLocalInstall: TNewRadioButton;
|
||||
radioServerInstall: TNewRadioButton;
|
||||
checkKeepOld: TNewCheckBox;
|
||||
txtClientPort: TEdit;
|
||||
txtBackendPort: TEdit;
|
||||
txtPassword: TPasswordEdit;
|
||||
txtBluePassword: TPasswordEdit;
|
||||
txtRedPassword: TPasswordEdit;
|
||||
InstallationTypePage: Integer;
|
||||
PasswordPage: Integer;
|
||||
lblPasswordInstructions: TNewStaticText;
|
||||
|
||||
procedure AcceptNumbersOnlyKeyPress(Sender: TObject; var Key: Char);
|
||||
var
|
||||
KeyCode: Integer;
|
||||
begin
|
||||
// allow only numbers
|
||||
KeyCode := Ord(Key);
|
||||
if not ((KeyCode = 8) or ((KeyCode >= 48) and (KeyCode <= 57))) then
|
||||
Key := #0;
|
||||
end;
|
||||
|
||||
procedure frmAddress_Activate(Page: TWizardPage);
|
||||
begin
|
||||
end;
|
||||
|
||||
function frmAddress_ShouldSkipPage(Page: TWizardPage): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function frmAddress_BackButtonClick(Page: TWizardPage): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function frmAddress_NextButtonClick(Page: TWizardPage): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure frmAddress_CancelButtonClick(Page: TWizardPage; var Cancel, Confirm: Boolean);
|
||||
begin
|
||||
end;
|
||||
|
||||
function frmInstallationType_CreatePage(PreviousPageId: Integer): Integer;
|
||||
var
|
||||
Page: TWizardPage;
|
||||
begin
|
||||
Page := CreateCustomPage(
|
||||
PreviousPageId,
|
||||
'DCS Olympus configuration',
|
||||
'Select installation type'
|
||||
);
|
||||
|
||||
{ lblLocalInstall }
|
||||
lblLocalInstall := TLabel.Create(Page);
|
||||
with lblLocalInstall do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(30);
|
||||
Top := ScaleY(14);
|
||||
Width := ScaleX(35);
|
||||
Height := ScaleY(10);
|
||||
Font.Style := [fsBold];
|
||||
Caption := 'Local installation';
|
||||
end;
|
||||
|
||||
{ lblLocalInstallInstructions }
|
||||
lblLocalInstallInstructions := TNewStaticText.Create(Page);
|
||||
with lblLocalInstallInstructions do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(30);
|
||||
Top := ScaleY(31);
|
||||
Width := ScaleX(340);
|
||||
Height := ScaleY(23);
|
||||
WordWrap := True;
|
||||
Caption := 'Select this to install DCS Olympus locally. DCS Olympus will not be reachable by external clients (i.e. browsers running on different PCs)';
|
||||
end;
|
||||
|
||||
{ radioLocalInstall }
|
||||
radioLocalInstall := TNewRadioButton.Create(Page);
|
||||
with radioLocalInstall do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(10);
|
||||
Top := ScaleY(12);
|
||||
Width := ScaleX(185);
|
||||
Height := ScaleY(21);
|
||||
TabOrder := 0;
|
||||
Checked := True
|
||||
end;
|
||||
|
||||
{ lblServerInstall }
|
||||
lblServerInstall := TLabel.Create(Page);
|
||||
with lblServerInstall do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(30);
|
||||
Top := ScaleY(76);
|
||||
Width := ScaleX(52);
|
||||
Height := ScaleY(13);
|
||||
Font.Style := [fsBold];
|
||||
Caption := 'Dedicated server installation';
|
||||
end;
|
||||
|
||||
{ lblServerInstallInstructions }
|
||||
lblServerInstallInstructions := TNewStaticText.Create(Page);
|
||||
with lblServerInstallInstructions do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(30);
|
||||
Top := ScaleY(93);
|
||||
Width := ScaleX(340);
|
||||
Height := ScaleY(13);
|
||||
WordWrap := True;
|
||||
Caption := 'Select this to install DCS Olympus on a dedicated server. DCS Olympus will be reachable by external clients. NOTE: to enable external connections, TCP port forwarding must be enabled on the selected ports.';
|
||||
end;
|
||||
|
||||
{ radioServerInstall }
|
||||
radioServerInstall := TNewRadioButton.Create(Page);
|
||||
with radioServerInstall do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(10);
|
||||
Top := ScaleY(72);
|
||||
Width := ScaleX(185);
|
||||
Height := ScaleY(21);
|
||||
TabOrder := 1;
|
||||
end;
|
||||
|
||||
with Page do
|
||||
begin
|
||||
OnActivate := @frmAddress_Activate;
|
||||
OnShouldSkipPage := @frmAddress_ShouldSkipPage;
|
||||
OnBackButtonClick := @frmAddress_BackButtonClick;
|
||||
OnNextButtonClick := @frmAddress_NextButtonClick;
|
||||
OnCancelButtonClick := @frmAddress_CancelButtonClick;
|
||||
end;
|
||||
|
||||
Result := Page.ID;
|
||||
end;
|
||||
|
||||
procedure frmPassword_Activate(Page: TWizardPage);
|
||||
begin
|
||||
checkKeepOld.Enabled := FileExists(ExpandConstant('{app}\Mods\Services\Olympus\olympus.json'));
|
||||
checkKeepOld.Checked := FileExists(ExpandConstant('{app}\Mods\Services\Olympus\olympus.json'));
|
||||
end;
|
||||
|
||||
function frmPassword_ShouldSkipPage(Page: TWizardPage): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function frmPassword_BackButtonClick(Page: TWizardPage): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function frmPassword_NextButtonClick(Page: TWizardPage): Boolean;
|
||||
begin
|
||||
if checkKeepOld.Checked or ((Trim(txtClientPort.Text) <> '') and (Trim(txtBackendPort.Text) <> '') and (Trim(txtPassword.Text) <> '') and (Trim(txtBluePassword.Text) <> '') and (Trim(txtRedPassword.Text) <> '')) then begin
|
||||
Result := True;
|
||||
end else
|
||||
begin
|
||||
MsgBox('Either keep the configuration from the previous installation (if present) or fill all the fields to continue.', mbInformation, MB_OK);
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure frmPassword_CancelButtonClick(Page: TWizardPage; var Cancel, Confirm: Boolean);
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure checkKeepOldOnChange(Sender: TObject);
|
||||
begin
|
||||
txtPassword.Enabled := not checkKeepOld.Checked;
|
||||
txtBluePassword.Enabled := not checkKeepOld.Checked;
|
||||
txtRedPassword.Enabled := not checkKeepOld.Checked;
|
||||
txtBackendPort.Enabled := not checkKeepOld.Checked;
|
||||
txtClientPort.Enabled := not checkKeepOld.Checked;
|
||||
end;
|
||||
|
||||
function frmPassword_CreatePage(PreviousPageId: Integer): Integer;
|
||||
var
|
||||
Page: TWizardPage;
|
||||
begin
|
||||
Page := CreateCustomPage(
|
||||
PreviousPageId,
|
||||
'DCS Olympus passwords',
|
||||
'Set DCS Olympus ports and passwords'
|
||||
);
|
||||
|
||||
{ lblKeepOld }
|
||||
lblKeepOld := TLabel.Create(Page);
|
||||
with lblKeepOld do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(54);
|
||||
Top := ScaleY(0);
|
||||
Width := ScaleX(46);
|
||||
Height := ScaleY(13);
|
||||
Caption := 'Keep configuration from previous installation';
|
||||
end;
|
||||
|
||||
{ checkKeepOld }
|
||||
checkKeepOld := TNewCheckBox.Create(Page);
|
||||
with checkKeepOld do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(24);
|
||||
Top := ScaleY(0);
|
||||
Width := ScaleX(46);
|
||||
Height := ScaleY(13);
|
||||
OnClick := @checkKeepOldOnChange;
|
||||
end;
|
||||
|
||||
{ lblPassword }
|
||||
lblPassword := TLabel.Create(Page);
|
||||
with lblPassword do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(24);
|
||||
Top := ScaleY(38);
|
||||
Width := ScaleX(46);
|
||||
Height := ScaleY(13);
|
||||
Caption := 'Game Master password';
|
||||
end;
|
||||
|
||||
{ txtPassword }
|
||||
txtPassword := TPasswordEdit.Create(Page);
|
||||
with txtPassword do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(180);
|
||||
Top := ScaleY(35);
|
||||
Width := ScaleX(185);
|
||||
Height := ScaleY(21);
|
||||
TabOrder := 1;
|
||||
end;
|
||||
|
||||
{ lblBluePassword }
|
||||
lblBluePassword := TLabel.Create(Page);
|
||||
with lblBluePassword do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(24);
|
||||
Top := ScaleY(66);
|
||||
Width := ScaleX(46);
|
||||
Height := ScaleY(13);
|
||||
Caption := 'Blue Commander password';
|
||||
end;
|
||||
|
||||
{ txtBluePassword }
|
||||
txtBluePassword := TPasswordEdit.Create(Page);
|
||||
with txtBluePassword do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(180);
|
||||
Top := ScaleY(63);
|
||||
Width := ScaleX(185);
|
||||
Height := ScaleY(21);
|
||||
TabOrder := 2;
|
||||
end;
|
||||
|
||||
{ lblRedPassword }
|
||||
lblRedPassword := TLabel.Create(Page);
|
||||
with lblRedPassword do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(24);
|
||||
Top := ScaleY(94);
|
||||
Width := ScaleX(46);
|
||||
Height := ScaleY(13);
|
||||
Caption := 'Red Commander password';
|
||||
end;
|
||||
|
||||
{ txtRedPassword }
|
||||
txtRedPassword := TPasswordEdit.Create(Page);
|
||||
with txtRedPassword do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(180);
|
||||
Top := ScaleY(91);
|
||||
Width := ScaleX(185);
|
||||
Height := ScaleY(21);
|
||||
TabOrder := 3;
|
||||
end;
|
||||
|
||||
|
||||
{ lblClientPort }
|
||||
lblClientPort := TLabel.Create(Page);
|
||||
with lblClientPort do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(24);
|
||||
Top := ScaleY(122);
|
||||
Width := ScaleX(46);
|
||||
Height := ScaleY(13);
|
||||
Caption := 'Webserver port';
|
||||
end;
|
||||
|
||||
{ txtClientPort }
|
||||
txtClientPort := TEdit.Create(Page);
|
||||
with txtClientPort do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(180);
|
||||
Top := ScaleY(119);
|
||||
Width := ScaleX(185);
|
||||
Height := ScaleY(21);
|
||||
Text := '3000';
|
||||
OnKeyPress := @AcceptNumbersOnlyKeyPress;
|
||||
TabOrder := 4;
|
||||
end;
|
||||
|
||||
{ lblBackendPort }
|
||||
lblBackendPort := TLabel.Create(Page);
|
||||
with lblBackendPort do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(24);
|
||||
Top := ScaleY(149);
|
||||
Width := ScaleX(46);
|
||||
Height := ScaleY(13);
|
||||
Caption := 'Backend port';
|
||||
end;
|
||||
|
||||
{ txtBackendPort }
|
||||
txtBackendPort := TEdit.Create(Page);
|
||||
with txtBackendPort do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(180);
|
||||
Top := ScaleY(147);
|
||||
Width := ScaleX(185);
|
||||
Height := ScaleY(21);
|
||||
Text := '3001';
|
||||
OnKeyPress := @AcceptNumbersOnlyKeyPress;
|
||||
TabOrder := 5;
|
||||
end;
|
||||
|
||||
{ lblPasswordInstructions }
|
||||
lblPasswordInstructions := TNewStaticText.Create(Page);
|
||||
with lblPasswordInstructions do
|
||||
begin
|
||||
Parent := Page.Surface;
|
||||
Left := ScaleX(24);
|
||||
Top := ScaleY(180);
|
||||
Width := ScaleX(340);
|
||||
Height := ScaleY(13);
|
||||
WordWrap := True;
|
||||
Caption := 'Passwords and ports can be changed in the future by using the DCS Olympus configurator. For more information, see the DCS Olympus Wiki.';
|
||||
end;
|
||||
|
||||
with Page do
|
||||
begin
|
||||
OnActivate := @frmPassword_Activate;
|
||||
OnShouldSkipPage := @frmPassword_ShouldSkipPage;
|
||||
OnBackButtonClick := @frmPassword_BackButtonClick;
|
||||
OnNextButtonClick := @frmPassword_NextButtonClick;
|
||||
OnCancelButtonClick := @frmPassword_CancelButtonClick;
|
||||
end;
|
||||
|
||||
Result := Page.ID;
|
||||
end;
|
||||
|
||||
procedure InitializeWizard();
|
||||
begin
|
||||
{this page will come after welcome page}
|
||||
InstallationTypePage := frmInstallationType_CreatePage(wpSelectDir);
|
||||
PasswordPage := frmPassword_CreatePage(InstallationTypePage);
|
||||
end;
|
||||
|
||||
function CheckLocalInstall(): boolean;
|
||||
begin
|
||||
if radioLocalInstall.Checked then begin
|
||||
Result := True
|
||||
end else
|
||||
begin
|
||||
Result := False
|
||||
end
|
||||
end;
|
||||
|
||||
function CheckServerInstall(): boolean;
|
||||
begin
|
||||
if radioLocalInstall.Checked then begin
|
||||
Result := False
|
||||
end else
|
||||
begin
|
||||
Result := True
|
||||
end
|
||||
end;
|
||||
|
||||
function CheckCallConfigurator(): boolean;
|
||||
begin
|
||||
if checkKeepOld.Checked then begin
|
||||
Result := False
|
||||
end else
|
||||
begin
|
||||
Result := True
|
||||
end
|
||||
end;
|
||||
|
||||
function GetAddress(Value: string): string;
|
||||
begin
|
||||
if radioLocalInstall.Checked then begin
|
||||
Result := 'localhost'
|
||||
end else
|
||||
begin
|
||||
Result := '*'
|
||||
end
|
||||
end;
|
||||
|
||||
function GetClientPort(Value: string): string;
|
||||
begin
|
||||
Result := txtClientPort.Text;
|
||||
end;
|
||||
|
||||
function GetBackendPort(Value: string): string;
|
||||
begin
|
||||
Result := txtBackendPort.Text;
|
||||
end;
|
||||
|
||||
function GetPassword(Value: string): string;
|
||||
begin
|
||||
Result := txtPassword.Text;
|
||||
end;
|
||||
|
||||
function GetBluePassword(Value: string): string;
|
||||
begin
|
||||
Result := txtBluePassword.Text;
|
||||
end;
|
||||
|
||||
function GetRedPassword(Value: string): string;
|
||||
begin
|
||||
Result := txtRedPassword.Text;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
Type: filesandordirs; Name: "{app}"
|
||||
|
||||
|
||||
13
manager/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": [ "start" ],
|
||||
"port": 9229
|
||||
}
|
||||
]
|
||||
}
|
||||
68
manager/ejs/instanceDiv.ejs
Normal file
@ -0,0 +1,68 @@
|
||||
<div class="instance-div">
|
||||
<div class="folder-name">
|
||||
<div class="icon folder"></div>
|
||||
<span><%= folder %></span>
|
||||
</div>
|
||||
<div class="version">
|
||||
Detected .dll version: <span class="<%= version === "n/a"? '' : (version === newVersion? 'accent-green': 'accent-red blink')%>"><%= version %></span> <br>
|
||||
Available .dll version: <span class="accent-green"><%= newVersion %></span>
|
||||
</div>
|
||||
<div class="instance-content">
|
||||
<table class="input-table">
|
||||
<tr>
|
||||
<td>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<div class="action-buttons">
|
||||
<button class="button add <%= installed? "hide": "" %>" tabindex="<%= index + 6 %>" title="Clicking on this will install all the necessary files in your DCS instance. Remember to close DCS before doing this!">Install Olympus to instance</button>
|
||||
<button class="button apply <%= !installed? "hide": "" %>" tabindex="<%= index + 7 %>" title="Clicking on this will apply your changes to the configuration. Remember to restart any running mission!">Apply changes</button>
|
||||
<button class="button remove <%= !installed? "hide": "" %>" tabindex="<%= index + 8 %>" title="Clicking on this will remove Olympus from your DCS folder.">Remove Olympus</button>
|
||||
<button class="button update <%= !(version !== "n/a" && version !== newVersion)? "hide": "" %>" tabindex="<%= index + 9 %>" title="Clicking on this will update Olympus in your DCS folder.">Update</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
10
manager/ejs/popup.ejs
Normal 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>
|
||||
1
manager/icons/check-solid.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="14" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path fill="#F2F2F2" d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>
|
||||
|
After Width: | Height: | Size: 449 B |
1
manager/icons/circle-info-solid.svg
Normal 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 fill="#F2F2F2" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>
|
||||
|
After Width: | Height: | Size: 521 B |
1
manager/icons/folder-open-solid.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="18" viewBox="0 0 576 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path fill="#F2F2F2" d="M88.7 223.8L0 375.8V96C0 60.7 28.7 32 64 32H181.5c17 0 33.3 6.7 45.3 18.7l26.5 26.5c12 12 28.3 18.7 45.3 18.7H416c35.3 0 64 28.7 64 64v32H144c-22.8 0-43.8 12.1-55.3 31.8zm27.6 16.1C122.1 230 132.6 224 144 224H544c11.5 0 22 6.1 27.7 16.1s5.7 22.2-.1 32.1l-112 192C453.9 474 443.4 480 432 480H32c-11.5 0-22-6.1-27.7-16.1s-5.7-22.2 .1-32.1l112-192z"/></svg>
|
||||
|
After Width: | Height: | Size: 614 B |
1
manager/icons/plus-solid.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="14" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path fill="#F2F2F2" d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32V224H48c-17.7 0-32 14.3-32 32s14.3 32 32 32H192V432c0 17.7 14.3 32 32 32s32-14.3 32-32V288H400c17.7 0 32-14.3 32-32s-14.3-32-32-32H256V80z"/></svg>
|
||||
|
After Width: | Height: | Size: 450 B |
1
manager/icons/rotate-right-solid.svg
Normal 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="M463.5 224H472c13.3 0 24-10.7 24-24V72c0-9.7-5.8-18.5-14.8-22.2s-19.3-1.7-26.2 5.2L413.4 96.6c-87.6-86.5-228.7-86.2-315.8 1c-87.5 87.5-87.5 229.3 0 316.8s229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3c62.2-62.2 162.7-62.5 225.3-1L327 183c-6.9 6.9-8.9 17.2-5.2 26.2s12.5 14.8 22.2 14.8H463.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 639 B |
1
manager/icons/trash-can-regular.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="14" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path fill="#F2F2F2" d="M170.5 51.6L151.5 80h145l-19-28.4c-1.5-2.2-4-3.6-6.7-3.6H177.1c-2.7 0-5.2 1.3-6.7 3.6zm147-26.6L354.2 80H368h48 8c13.3 0 24 10.7 24 24s-10.7 24-24 24h-8V432c0 44.2-35.8 80-80 80H112c-44.2 0-80-35.8-80-80V128H24c-13.3 0-24-10.7-24-24S10.7 80 24 80h8H80 93.8l36.7-55.1C140.9 9.4 158.4 0 177.1 0h93.7c18.7 0 36.2 9.4 46.6 24.9zM80 128V432c0 17.7 14.3 32 32 32H336c17.7 0 32-14.3 32-32V128H80zm80 64V400c0 8.8-7.2 16-16 16s-16-7.2-16-16V192c0-8.8 7.2-16 16-16s16 7.2 16 16zm80 0V400c0 8.8-7.2 16-16 16s-16-7.2-16-16V192c0-8.8 7.2-16 16-16s16 7.2 16 16zm80 0V400c0 8.8-7.2 16-16 16s-16-7.2-16-16V192c0-8.8 7.2-16 16-16s16 7.2 16 16z"/></svg>
|
||||
|
After Width: | Height: | Size: 896 B |
1
manager/icons/window-maximize-regular.svg
Normal 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 |
1
manager/icons/window-minimize-regular.svg
Normal 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 |
1
manager/icons/window-restore-regular.svg
Normal 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 |
1
manager/icons/xmark-solid.svg
Normal 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 |
72
manager/index.html
Normal file
@ -0,0 +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 {{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">{{OLYMPUS_VERSION_NUMBER}}</div>
|
||||
</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>
|
||||
<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>
|
||||
1
manager/install.bat
Normal file
@ -0,0 +1 @@
|
||||
npm install --omit=dev
|
||||
463
manager/javascripts/preload.js
Normal file
@ -0,0 +1,463 @@
|
||||
var regedit = require('regedit')
|
||||
var fs = require('fs')
|
||||
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 createShortcut = require('create-desktop-shortcuts');
|
||||
const vi = require('win-version-info');
|
||||
|
||||
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) {
|
||||
console.error(`Port ${port} already in use`);
|
||||
callback(false);
|
||||
} else {
|
||||
callback(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function installOlympus(folder) {
|
||||
console.log(`Installing Olympus in ${folder}`);
|
||||
try {
|
||||
fs.cpSync(path.join("..", "mod"), path.join(folder, "Mods", "Services", "Olympus"), { recursive: true });
|
||||
fs.cpSync(path.join("..", "scripts", "OlympusHook.lua"), path.join(folder, "Scripts", "Hook", "OlympusHook.lua"));
|
||||
fs.cpSync(path.join("..", "olympus.json"), path.join(folder, "Config", "olympus.json"));
|
||||
if (createShortcut({
|
||||
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')
|
||||
}
|
||||
}) &&
|
||||
createShortcut({
|
||||
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 {
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
loadDivs();
|
||||
return true;
|
||||
}
|
||||
|
||||
function uninstallOlympus(folder) {
|
||||
console.log(`Uninstalling Olympus from ${folder}`);
|
||||
try {
|
||||
fs.rmSync(path.join(folder, "Mods", "Services", "Olympus"), { recursive: true });
|
||||
fs.rmSync(path.join(folder, "Config", "olympus.json"));
|
||||
loadDivs();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function applyConfiguration(folder, data) {
|
||||
console.log(`Applying configuration to Olympus from ${folder}`);
|
||||
|
||||
if (fs.existsSync(path.join(folder, "Config", "olympus.json"))) {
|
||||
var config = JSON.parse(fs.readFileSync(path.join(folder, "Config", "olympus.json")));
|
||||
|
||||
config["client"]["port"] = data["clientPort"];
|
||||
config["server"]["port"] = data["backendPort"];
|
||||
config["server"]["address"] = data["backendAddress"];
|
||||
config["authentication"]["gameMasterPassword"] = sha256(data["gameMasterPassword"]);
|
||||
config["authentication"]["blueCommanderPassword"] = sha256(data["blueCommanderPassword"]);
|
||||
config["authentication"]["redCommanderPassword"] = sha256(data["redCommanderPassword"]);
|
||||
|
||||
try {
|
||||
fs.writeFileSync(path.join(folder, "Config", "olympus.json"), JSON.stringify(config, null, 4));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function updateOlympus(folder) {
|
||||
console.log(`Updating Olympus in ${folder}`);
|
||||
try {
|
||||
fs.cpSync(path.join("..", "mod"), path.join(folder, "Mods", "Services", "Olympus"), { recursive: true });
|
||||
fs.cpSync(path.join("..", "scripts", "OlympusHook.lua"), path.join(folder, "Scripts", "Hook", "OlympusHook.lua"));
|
||||
loadDivs();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function createDesktopShortcuts(folder) {
|
||||
if (createShortcut({
|
||||
windows: {
|
||||
filePath: path.resolve(__dirname, '..', '..', 'client', 'client.vbs'),
|
||||
name: "DCS Olympus Client",
|
||||
arguments: `"${path.join(folder, "Config", "olympus.json")}"`,
|
||||
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus.ico'),
|
||||
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
|
||||
}
|
||||
}) && createShortcut({
|
||||
windows: {
|
||||
filePath: path.resolve(__dirname, '..', '..', 'client', 'server.vbs'),
|
||||
name: "DCS Olympus Server",
|
||||
arguments: `"${path.join(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.")
|
||||
}
|
||||
}
|
||||
|
||||
class InstanceDiv {
|
||||
element = null;
|
||||
parent = null;
|
||||
folder = "";
|
||||
|
||||
constructor(parent, folder) {
|
||||
this.element = parent;
|
||||
this.folder = folder;
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.element = document.createElement("div");
|
||||
|
||||
var data = {
|
||||
folder: this.folder,
|
||||
installed: false,
|
||||
index: instanceDivs.length * 10
|
||||
};
|
||||
|
||||
var newVersionInfo = vi(path.join("..", "mod", "bin", "olympus.dll"));
|
||||
data["newVersion"] = newVersionInfo.ProductVersion;
|
||||
data["version"] = "n/a";
|
||||
|
||||
if (fs.existsSync(path.join(this.folder, "Config", "olympus.json"))) {
|
||||
var config = JSON.parse(fs.readFileSync(path.join(this.folder, "Config", "olympus.json")));
|
||||
data = {
|
||||
...data,
|
||||
...config
|
||||
}
|
||||
data["installed"] = true;
|
||||
|
||||
try {
|
||||
data["version"] = vi(path.join(this.folder, "Mods", "Services", "Olympus", "bin", "olympus.dll")).ProductVersion;
|
||||
} catch (e) {
|
||||
data["version"] = "n/a";
|
||||
}
|
||||
}
|
||||
|
||||
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")) {
|
||||
showPopup("Please wait while Olympus is being installed");
|
||||
window.setTimeout(() => {
|
||||
if (installOlympus(this.folder)) {
|
||||
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", () => {
|
||||
createDesktopShortcuts(this.folder);
|
||||
});
|
||||
} else {
|
||||
showPopup("An error has occurred during installation");
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
this.element.querySelector(".remove").addEventListener("click", (e) => {
|
||||
if (!e.srcElement.classList.contains("disabled")) {
|
||||
showPopup("Please wait while Olympus is being uninstalled from DCS instance");
|
||||
window.setTimeout(() => {
|
||||
if (uninstallOlympus(this.folder)) {
|
||||
showPopup("Olympus uninstalled successfully from DCS instance!");
|
||||
} else {
|
||||
showPopup("An error has occurred during uninstallation");
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
this.element.querySelector(".apply").addEventListener("click", (e) => {
|
||||
e.srcElement.classList.remove("blink");
|
||||
if (!e.srcElement.classList.contains("disabled")) {
|
||||
showPopup("Please wait while the configuration is being applied");
|
||||
window.setTimeout(() => {
|
||||
if (applyConfiguration(this.folder, this.getFields())) {
|
||||
showPopup("Olympus configuration applied successfully!");
|
||||
} else {
|
||||
showPopup("An error has occurred while applying the configuration");
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
});
|
||||
|
||||
this.element.querySelector(".update").addEventListener("click", (e) => {
|
||||
if (!e.srcElement.classList.contains("disabled")) {
|
||||
showPopup("Please wait while Olympus is being updated in the DCS instance");
|
||||
window.setTimeout(() => {
|
||||
if (updateOlympus(this.folder)) {
|
||||
showPopup("Olympus updated successfully from DCS instance!");
|
||||
} else {
|
||||
showPopup("An error has occurred during the update");
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
var inputs = this.element.querySelectorAll("input");
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
inputs[i].addEventListener("change", () => {
|
||||
inputs[i].classList.remove("error");
|
||||
instanceDivs.forEach((instanceDiv) => instanceDiv.checkFields())
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getDiv() {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
getFields() {
|
||||
return {
|
||||
clientPort: Number(this.element.querySelector("#client-port").value),
|
||||
backendPort: Number(this.element.querySelector("#backend-port").value),
|
||||
backendAddress: this.element.querySelector("#backend-address").value,
|
||||
gameMasterPassword: this.element.querySelector("#game-master-password").value,
|
||||
blueCommanderPassword: this.element.querySelector("#blue-commander-password").value,
|
||||
redCommanderPassword: this.element.querySelector("#red-commander-password").value,
|
||||
}
|
||||
}
|
||||
|
||||
checkFields() {
|
||||
var data = this.getFields();
|
||||
|
||||
/* Clear existing errors */
|
||||
var inputs = this.element.querySelectorAll("input");
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
inputs[i].classList.remove("error");
|
||||
}
|
||||
var messages = this.element.querySelectorAll(".error");
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
messages[i].innerText = "";
|
||||
}
|
||||
|
||||
/* Enable the button */
|
||||
this.element.querySelector(".apply").classList.remove("disabled");
|
||||
|
||||
if (data["clientPort"] !== 0 && data["backendPort"] !== 0) {
|
||||
if (data["clientPort"] === data["backendPort"]) {
|
||||
this.element.querySelector("#client-port").classList.add("error");
|
||||
this.element.querySelector("#client-port-error").innerText = "Ports must be different";
|
||||
this.element.querySelector("#backend-port").classList.add("error");
|
||||
this.element.querySelector("#backend-port-error").innerText = "Ports must be different";
|
||||
this.element.querySelector(".apply").classList.add("disabled");
|
||||
}
|
||||
else {
|
||||
checkPort(data["clientPort"], (res) => {
|
||||
var otherInstanceUsesPort = instanceDivs.find((instanceDiv) => {
|
||||
if (instanceDiv != this) {
|
||||
var fields = instanceDiv.getFields();
|
||||
if (fields["clientPort"] === data["clientPort"] || fields["backendPort"] === data["clientPort"]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!res || otherInstanceUsesPort) {
|
||||
this.element.querySelector("#client-port").classList.add("error");
|
||||
this.element.querySelector("#client-port-error").innerText = "Port already in use";
|
||||
this.element.querySelector(".apply").classList.add("disabled");
|
||||
}
|
||||
});
|
||||
|
||||
checkPort(data["backendPort"], (res) => {
|
||||
var otherInstanceUsesPort = instanceDivs.find((instanceDiv) => {
|
||||
if (instanceDiv != this) {
|
||||
var fields = instanceDiv.getFields();
|
||||
if (fields["clientPort"] === data["backendPort"] || fields["backendPort"] === data["backendPort"]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!res || otherInstanceUsesPort) {
|
||||
this.element.querySelector("#backend-port").classList.add("error");
|
||||
this.element.querySelector("#backend-port-error").innerText = "Port already in use";
|
||||
this.element.querySelector(".apply").classList.add("disabled");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (data["gameMasterPassword"] !== "" && data["blueCommanderPassword"] !== "" && data["gameMasterPassword"] === data["blueCommanderPassword"]) {
|
||||
this.element.querySelector("#game-master-password").classList.add("error");
|
||||
this.element.querySelector("#game-master-password-error").innerText = "Passwords must be different";
|
||||
this.element.querySelector("#blue-commander-password").classList.add("error");
|
||||
this.element.querySelector("#blue-commander-password-error").innerText = "Passwords must be different";
|
||||
this.element.querySelector(".apply").classList.add("disabled");
|
||||
}
|
||||
|
||||
if (data["gameMasterPassword"] !== "" && data["redCommanderPassword"] !== "" && data["gameMasterPassword"] === data["redCommanderPassword"]) {
|
||||
this.element.querySelector("#game-master-password").classList.add("error");
|
||||
this.element.querySelector("#game-master-password-error").innerText = "Passwords must be different";
|
||||
this.element.querySelector("#red-commander-password").classList.add("error");
|
||||
this.element.querySelector("#red-commander-password-error").innerText = "Passwords must be different";
|
||||
this.element.querySelector(".apply").classList.add("disabled");
|
||||
}
|
||||
|
||||
if (data["blueCommanderPassword"] !== "" && data["redCommanderPassword"] !== "" && data["blueCommanderPassword"] === data["redCommanderPassword"]) {
|
||||
this.element.querySelector("#blue-commander-password").classList.add("error");
|
||||
this.element.querySelector("#blue-commander-password-error").innerText = "Passwords must be different";
|
||||
this.element.querySelector("#red-commander-password").classList.add("error");
|
||||
this.element.querySelector("#red-commander-password-error").innerText = "Passwords must be different";
|
||||
this.element.querySelector(".apply").classList.add("disabled");
|
||||
}
|
||||
|
||||
if (data["gameMasterPassword"] === "" || data["blueCommanderPassword"] === "" || data["redCommanderPassword"] === "") {
|
||||
this.element.querySelector(".apply").classList.add("disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadDivs() {
|
||||
regedit.list(shellFoldersKey, function (err, result) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
else {
|
||||
if (result[shellFoldersKey] !== undefined && result[shellFoldersKey]["exists"] && result[shellFoldersKey]['values'][saveGamesKey] !== undefined && result[shellFoldersKey]['values'][saveGamesKey]['value'] !== undefined) {
|
||||
const searchpath = result[shellFoldersKey]['values'][saveGamesKey]['value'];
|
||||
const folders = fs.readdirSync(searchpath);
|
||||
instanceDivs = [];
|
||||
const mainDiv = document.getElementById("main-div");
|
||||
|
||||
folders.forEach((folder) => {
|
||||
if (fs.existsSync(path.join(searchpath, folder, "Config", "appsettings.lua")) ||
|
||||
fs.existsSync(path.join(searchpath, folder, "Config", "serversettings.lua"))) {
|
||||
instanceDivs.push(new InstanceDiv(mainDiv, path.join(searchpath, folder)));
|
||||
}
|
||||
});
|
||||
|
||||
mainDiv.replaceChildren(...instanceDivs.map((instanceDiv) => {
|
||||
return instanceDiv.getDiv();
|
||||
}));
|
||||
|
||||
instanceDivs.forEach((instanceDiv) => instanceDiv.checkFields())
|
||||
|
||||
} else {
|
||||
console.error("An error occured while trying to fetch the location of the DCS folders.")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
loadDivs();
|
||||
})
|
||||
66
manager/manager.js
Normal file
@ -0,0 +1,66 @@
|
||||
const electronApp = require('electron').app;
|
||||
const electronBrowserWindow = require('electron').BrowserWindow;
|
||||
const electronIpcMain = require('electron').ipcMain;
|
||||
const path = require('path');
|
||||
|
||||
let window;
|
||||
|
||||
function createWindow() {
|
||||
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_configurator.ico"
|
||||
});
|
||||
|
||||
window.loadFile('index.html').then(() => { window.show(); });
|
||||
|
||||
window.on("maximize", () => {
|
||||
window.webContents.send('event:maximized')
|
||||
})
|
||||
|
||||
window.on("unmaximize", () => {
|
||||
window.webContents.send('event:unmaximized')
|
||||
})
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
electronApp.on('ready', () => {
|
||||
window = 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();
|
||||
})
|
||||
|
||||
electronIpcMain.on('window:maximize', () => {
|
||||
window.maximize();
|
||||
})
|
||||
|
||||
electronIpcMain.on('window:restore', () => {
|
||||
window.restore();
|
||||
})
|
||||
|
||||
electronIpcMain.on('window:close', () => {
|
||||
window.close();
|
||||
})
|
||||
1
manager/manager.vbs
Normal file
@ -0,0 +1 @@
|
||||
CreateObject("Wscript.Shell").Run "npm start", 0
|
||||
21
manager/package.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "dcsolympus_manager",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "manager.js",
|
||||
"scripts": {
|
||||
"start": "electron ."
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"create-desktop-shortcuts": "^1.10.1",
|
||||
"create-windowless-app": "^11.0.0",
|
||||
"ejs": "^3.1.9",
|
||||
"electron": "^28.0.0",
|
||||
"portfinder": "^1.0.32",
|
||||
"regedit": "^5.1.2",
|
||||
"sha256": "^0.2.0",
|
||||
"win-version-info": "^6.0.1"
|
||||
}
|
||||
}
|
||||
353
manager/stylesheets/style.css
Normal file
@ -0,0 +1,353 @@
|
||||
* {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
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: start;
|
||||
color: #F2F2F2;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
padding: 20px;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
#header>div:first-of-type{
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#header>div:last-child {
|
||||
font-size: 13px;
|
||||
margin-left: 30px;
|
||||
font-weight: 400;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
#main-div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
row-gap: 30px;
|
||||
column-gap: 30px;
|
||||
flex-wrap: wrap;
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: auto;
|
||||
scrollbar-color: white transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
border-bottom-right-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: white;
|
||||
border-radius: 100px;
|
||||
margin-top: 10px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.instance-div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
background-color: #3d4651;
|
||||
height: fit-content;
|
||||
padding: 20px 40px;
|
||||
border-radius: 5px;
|
||||
border-left: 5px solid #017DC1;
|
||||
width: 600px;
|
||||
box-shadow: 0px 0px 5px #000A;
|
||||
}
|
||||
|
||||
.instance-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 15px;
|
||||
}
|
||||
|
||||
.folder-name {
|
||||
color: #F2F2F2;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
border-bottom: 1px solid #F2F2F2;
|
||||
padding-bottom: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.folder-name span {
|
||||
width: 500px;
|
||||
overflow: hidden;
|
||||
text-wrap: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
direction: rtl;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.folder {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("../icons/folder-open-solid.svg");
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.version {
|
||||
font-size: 13px;
|
||||
color: #F2F2F2;
|
||||
}
|
||||
|
||||
.input-table {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
border-width: 0px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.input-table td {
|
||||
color: #F2F2F2;
|
||||
padding: 5px 0px;
|
||||
font-size: 13px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.input-table td>div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
column-gap: 12px;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 5px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: fit-content;
|
||||
height: 40px;
|
||||
color: #F2F2F2;
|
||||
border: 1px solid #F2F2F2;
|
||||
background-size: 40px 60%;
|
||||
background-position: 0px 50%;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 5px;
|
||||
padding: 5px 15px 5px 45px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.button:not(.disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.apply {
|
||||
background-image: url("../icons/check-solid.svg");
|
||||
background-color: #017DC1;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.add {
|
||||
padding: 5px 15px 5px 15px;
|
||||
}
|
||||
|
||||
.update {
|
||||
background-image: url("../icons/rotate-right-solid.svg");
|
||||
}
|
||||
|
||||
.other {
|
||||
padding: 5px 15px 5px 15px;
|
||||
}
|
||||
|
||||
.remove {
|
||||
background-image: url("../icons/trash-can-regular.svg");
|
||||
}
|
||||
|
||||
.disabled {
|
||||
background-color: #797E83;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message {
|
||||
font-weight: 600;
|
||||
height: 20px;
|
||||
font-size: 13px;
|
||||
color: #F2F2F2;
|
||||
}
|
||||
|
||||
input {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
width: 240px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
input:focus{
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input.error {
|
||||
border-color: #FF5858;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-weight: bold;
|
||||
color: #FF5858;
|
||||
}
|
||||
|
||||
.accent-red {
|
||||
color: #FF5858;
|
||||
}
|
||||
|
||||
.accent-green {
|
||||
color: #8bff63;
|
||||
}
|
||||
|
||||
.info {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-image: url("../icons/circle-info-solid.svg");
|
||||
background-position: 50% 50%;
|
||||
}
|
||||
|
||||
.blink {
|
||||
animation: blinker 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes blinker {
|
||||
50% {
|
||||
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;
|
||||
}
|
||||
19
moc_dcs/Config/olympus.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
466
moc_dcs/Mods/Services/Olympus/databases/airbases/caucasus.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
838
moc_dcs/Mods/Services/Olympus/databases/airbases/falklands.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
466
moc_dcs/Mods/Services/Olympus/databases/airbases/marianas.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
558
moc_dcs/Mods/Services/Olympus/databases/airbases/nevada.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
2633
moc_dcs/Mods/Services/Olympus/databases/airbases/normandy.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
1374
moc_dcs/Mods/Services/Olympus/databases/airbases/sinaimap.json
Normal file
1366
moc_dcs/Mods/Services/Olympus/databases/airbases/syria.json
Normal file
525
moc_dcs/Mods/Services/Olympus/databases/airbases/thechannel.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
33295
moc_dcs/Mods/Services/Olympus/databases/units/aircraftdatabase.json
Normal file
10359
moc_dcs/Mods/Services/Olympus/databases/units/groundunitdatabase.json
Normal file
1748
moc_dcs/Mods/Services/Olympus/databases/units/navyunitdatabase.json
Normal file
33295
moc_dcs/Mods/Services/Olympus/databases/units/old/aircraftdatabase.json
Normal file
19
notes.txt
Normal file
@ -0,0 +1,19 @@
|
||||
v1.0.4 ====================
|
||||
Changes:
|
||||
1) Added Olympus Manager for unified configuration management;
|
||||
2) Added proxy middleware to reroute requests to backend from frontend port (netsh command no longer required);
|
||||
3) Moved installation folder outside of DCS Saved Games folder. Only necessary and unique files are installed in DCS Saved Games folder by Manager;
|
||||
4) olympus.json configuration file moved to <DCS Saved Games>/Config folder;
|
||||
5) olympus_log.txt log file moved to <DCS Saved Games>/Logs folder;
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
CRITICAL NOTICE PLEASE READ!!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
THIS VERSION INTRODUCES MAJOR CHANGES IN THE INSTALLATION AND MANAGEMENT OF OLYMPUS. PLEASE MAKE SURE TO READ THE UPDATE INSTRUCTIONS BEFORE INSTALLING.
|
||||
ALSO, PLEASE MAKE SURE TO UNINSTALL ANY PREVIOUSLY INSTALLED VERSION OF OLYMPUS BEFORE PROCEEDING!
|
||||
|
||||
v1.0.3 ====================
|
||||
|
||||
First public release.
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
"port": 3001
|
||||
},
|
||||
"authentication": {
|
||||
"gameMasterPassword": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6",
|
||||
"blueCommanderPassword": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6",
|
||||
"redCommanderPassword": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6"
|
||||
"gameMasterPassword": "4b8823ed9e5c2392ab4a791913bb8ce41956ea32e308b760eefb97536746dd33",
|
||||
"blueCommanderPassword": "b0ea4230c1558c5313165eda1bdb7fced008ca7f2ca6b823fb4d26292f309098",
|
||||
"redCommanderPassword": "302bcbaf2a3fdcf175b689bf102d6cdf9328f68a13d4096101bba806482bfed9"
|
||||
},
|
||||
"client": {
|
||||
"port": 3000,
|
||||
|
||||
@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
FILEVERSION 1,0,3,0
|
||||
PRODUCTVERSION 1,0,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -79,12 +79,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "FileVersion", "1.0.3.0"
|
||||
VALUE "InternalName", "core.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "core.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "ProductVersion", "1.0.3.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@ -212,4 +212,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "logger.h"
|
||||
#include "luatools.h"
|
||||
#include "dcstools.h"
|
||||
#include "defines.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -38,9 +39,9 @@ void registerLuaFunctions(lua_State* L)
|
||||
log("protectedCall registered successfully");
|
||||
}
|
||||
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\mist.lua");
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\OlympusCommand.lua");
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\unitPayloads.lua");
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\templates.lua");
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\mods.lua");
|
||||
executeLuaScript(L, instancePath + MIST_SCRIPT);
|
||||
executeLuaScript(L, instancePath + OLYMPUS_COMMAND_SCRIPT);
|
||||
executeLuaScript(L, instancePath + UNIT_PAYLOADS_SCRIPT);
|
||||
executeLuaScript(L, instancePath + TEMPLATES_SCRIPT);
|
||||
executeLuaScript(L, instancePath + MODS_SCRIPT);
|
||||
}
|
||||
|
||||
@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
FILEVERSION 1,0,3,0
|
||||
PRODUCTVERSION 1,0,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -79,12 +79,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "FileVersion", "1.0.3.0"
|
||||
VALUE "InternalName", "dcstools.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "dcstools.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "ProductVersion", "1.0.3.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@ -172,4 +172,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "framework.h"
|
||||
|
||||
void DllExport setLogDirectory(std::string m_dirPath);
|
||||
void DllExport log(const std::string& sMessage, bool addToJSON = false);
|
||||
void DllExport log(const std::wstring& sMessage, bool addToJSON = false);
|
||||
void DllExport getLogsJSON(json::value& json, unsigned long long time);
|
||||
|
||||
@ -8,6 +8,7 @@ public:
|
||||
void log(const string& sMessage, bool addToJSON);
|
||||
void log(const wstring& sMessage, bool addToJSON);
|
||||
void toJSON(json::value& json, unsigned long long time);
|
||||
void setDirectory(string newDirPath);
|
||||
|
||||
static Logger* GetLogger();
|
||||
|
||||
@ -20,6 +21,7 @@ private:
|
||||
static Logger* m_pThis;
|
||||
static ofstream m_Logfile;
|
||||
static std::map<unsigned long long, std::string> m_logs;
|
||||
static string m_dirPath;
|
||||
|
||||
mutex mutexLock;
|
||||
|
||||
|
||||
@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
FILEVERSION 1,0,3,0
|
||||
PRODUCTVERSION 1,0,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -79,12 +79,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "FileVersion", "1.0.3.0"
|
||||
VALUE "InternalName", "logger.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "logger.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "ProductVersion", "1.0.3.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@ -169,4 +169,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@ -4,6 +4,11 @@
|
||||
|
||||
#define LOGGER Logger::GetLogger()
|
||||
|
||||
void setLogDirectory(string m_dirPath)
|
||||
{
|
||||
LOGGER->setDirectory(m_dirPath);
|
||||
}
|
||||
|
||||
void log(const string& message, bool addToJSON)
|
||||
{
|
||||
LOGGER->log(message, addToJSON);
|
||||
|
||||
@ -8,25 +8,35 @@ const string Logger::m_sFileName = LOG_NAME;
|
||||
Logger* Logger::m_pThis = NULL;
|
||||
ofstream Logger::m_Logfile;
|
||||
std::map<unsigned long long, std::string> Logger::m_logs;
|
||||
std::string Logger::m_dirPath;
|
||||
|
||||
Logger::Logger()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Logger* Logger::GetLogger()
|
||||
{
|
||||
if (m_pThis == NULL) {
|
||||
m_pThis = new Logger();
|
||||
std::filesystem::path dirPath = std::filesystem::temp_directory_path();
|
||||
m_Logfile.open((dirPath.string() + m_sFileName).c_str(), ios::out);
|
||||
}
|
||||
return m_pThis;
|
||||
}
|
||||
|
||||
void Logger::setDirectory(string newDirPath)
|
||||
{
|
||||
m_dirPath = newDirPath;
|
||||
}
|
||||
|
||||
void Logger::Open()
|
||||
{
|
||||
std::filesystem::path dirPath = std::filesystem::temp_directory_path();
|
||||
m_Logfile.open((dirPath.string() + m_sFileName).c_str(), ios::out | ios::app);
|
||||
try {
|
||||
m_Logfile.open((m_dirPath + m_sFileName).c_str(), ios::out | ios::app);
|
||||
}
|
||||
catch (...) {
|
||||
std::filesystem::path m_dirPath = std::filesystem::temp_directory_path();
|
||||
m_Logfile.open((m_dirPath.string() + m_sFileName).c_str(), ios::out | ios::app);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::Close()
|
||||
|
||||
@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
FILEVERSION 1,0,3,0
|
||||
PRODUCTVERSION 1,0,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -79,12 +79,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "FileVersion", "1.0.3.0"
|
||||
VALUE "InternalName", "luatools.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "luatools.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "ProductVersion", "1.0.3.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@ -173,4 +173,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
FILEVERSION 1,0,3,0
|
||||
PRODUCTVERSION 1,0,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -79,12 +79,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "FileVersion", "1.0.3.0"
|
||||
VALUE "InternalName", "olympus.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "olympus.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "ProductVersion", "1.0.3.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@ -127,4 +127,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@ -49,6 +49,9 @@ static int onSimulationStart(lua_State* L)
|
||||
{
|
||||
LogInfo(L, "Trying to load core.dll from " + modPath);
|
||||
SetDllDirectoryA(modPath.c_str());
|
||||
|
||||
setLogDirectory(modPath);
|
||||
|
||||
log("onSimulationStart callback called successfully");
|
||||
|
||||
string dllLocation = modPath + "\\core.dll";
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION "{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}"
|
||||
#define LOG_NAME "Olympus_log.txt"
|
||||
#define REST_ADDRESS "http://localhost:30000"
|
||||
#define LOG_NAME "..\\..\\..\\..\\Logs\\Olympus_log.txt"
|
||||
|
||||
#define REST_ADDRESS "http://localhost:3001"
|
||||
#define REST_URI "olympus"
|
||||
#define UNITS_URI "units"
|
||||
#define WEAPONS_URI "weapons"
|
||||
@ -14,8 +15,14 @@
|
||||
|
||||
#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\\units\\aircraftdatabase.json"
|
||||
#define HELICOPTER_DATABASE_PATH "..\\databases\\units\\helicopterdatabase.json"
|
||||
#define GROUNDUNIT_DATABASE_PATH "..\\databases\\units\\groundunitdatabase.json"
|
||||
#define NAVYUNIT_DATABASE_PATH "..\\databases\\units\\navyunitdatabase.json"
|
||||
|
||||
#define MIST_SCRIPT "..\\Scripts\\mist.lua"
|
||||
#define OLYMPUS_COMMAND_SCRIPT "..\\Scripts\\OlympusCommand.lua"
|
||||
#define UNIT_PAYLOADS_SCRIPT "..\\Scripts\\unitPayloads.lua"
|
||||
#define TEMPLATES_SCRIPT "..\\Scripts\\templates.lua"
|
||||
#define MODS_SCRIPT "..\\Scripts\\mods.lua"
|
||||
|
||||
@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0
|
||||
FILEVERSION 1,0,3,0
|
||||
PRODUCTVERSION 1,0,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -79,12 +79,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "FileVersion", "1.0.3.0"
|
||||
VALUE "InternalName", "utils.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "utils.dll"
|
||||
VALUE "ProductName", "TODO: <Product name>"
|
||||
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0"
|
||||
VALUE "ProductVersion", "1.0.3.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||