Merge branch 'release-candidate' into 673-status-bar-hit-box
6
.github/workflows/documentation.yml
vendored
@ -24,11 +24,11 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
working-directory: ./client
|
||||
working-directory: ./frontend/website
|
||||
|
||||
- name: Create the docs directory locally in CI
|
||||
run: npx typedoc --out ../docs/client @types/*.d.ts src/**/*.ts
|
||||
working-directory: ./client
|
||||
run: npx typedoc --out ../../docs/website @types/*.d.ts src/**/*.ts
|
||||
working-directory: ./frontend/website
|
||||
|
||||
- name: Install Doxygen
|
||||
uses: ssciwr/doxygen-install@v1
|
||||
|
||||
18
.gitignore
vendored
@ -7,12 +7,12 @@ hgt
|
||||
|
||||
/backend/vcpkg_installed
|
||||
|
||||
/client/TODO.txt
|
||||
/client/public/javascripts/bundle.js
|
||||
/client/public/plugins
|
||||
/client/plugins/controltips/index.js
|
||||
/client/public/databases/units/old
|
||||
/client/plugins/databasemanager/index.js
|
||||
/frontend/server/TODO.txt
|
||||
/frontend/server/public/javascripts/bundle.js
|
||||
/frontend/server/public/plugins
|
||||
/frontend/server/plugins/controltips/index.js
|
||||
/frontend/server/public/databases/units/old
|
||||
/frontend/server/plugins/databasemanager/index.js
|
||||
|
||||
/src/html
|
||||
/src/latex
|
||||
@ -30,4 +30,8 @@ leaflet.nauticscale.js
|
||||
leaflet.css
|
||||
package-lock.json
|
||||
|
||||
!client/bin
|
||||
!frontend/server/bin
|
||||
/mock-dcs
|
||||
/frontend/setup
|
||||
frontend/server/public/plugins/controltipsplugin/index.js
|
||||
frontend/website/plugins/controltips/index.js
|
||||
|
||||
BIN
DCS Olympus Manager.lnk
Normal file
@ -36,14 +36,14 @@ INSTALLATION INSTRUCTIONS
|
||||
7) Open Olympus via the shortcut and login using any username and the Game Master password set using the Manager. (NOTE: not your DCS server password).
|
||||
Local installation: run the client from the provided desktop shortcut or start it using the "View and manage instances" page of the Manager.
|
||||
Dedicated server: users must first start the Olympus server from the provided desktop shortcut or using the "View and manage instances" page of the Manager.
|
||||
Then log in using any browser and visiting "http:\\<server IP>:<client port>" (client port is 3000 by default, but can be edited using the Manager)
|
||||
Then log in using any browser and visiting "http:\\<server IP>:<frontend port>" (frontend port is 3000 by default, but can be edited using the Manager)
|
||||
|
||||
8) You can use the manager at any time to change the ports and/or passwords. If you do, REMEMBER TO RESTART OLYMPUS AND DCS.
|
||||
|
||||
|
||||
NOTES:
|
||||
a) when launching the Manager you will be prompted to allow Electron to create a firewall rule. This is optional and can be denied without effect on the operation of the Manager;
|
||||
b) if you are using Olympus on a dedicated server with a router, you must enable port forwarding on the client port (3000 by default);
|
||||
b) if you are using Olympus on a dedicated server with a router, you must enable port forwarding on the frontend port (3000 by default);
|
||||
c) unlike Olympus v1.0.3, running the netsh command is no longer required. It is also no longer required to create firewall rules or port forwarding for the backend port. (Optional) If you already performed this steps in the past you can delete the firewall and netsh rules.
|
||||
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
# DCS Olympus
|
||||
|
||||

|
||||

|
||||
|
||||
### What is this?
|
||||
DCS: Olympus is a free and open-source mod for DCS that enables dynamic real-time control through a map interface. The user is able to spawn units/groups, deploy a variety of effects such as smoke, flares, or explosions, and waypoints/tasks can be given to AI units in real-time in a way similar to a classic RTS game.
|
||||
|
||||
@ -296,14 +296,14 @@ void Server::task()
|
||||
ss << ifstream.rdbuf();
|
||||
std::error_code errorCode;
|
||||
json::value config = json::value::parse(ss.str(), errorCode);
|
||||
if (config.is_object() && config.has_object_field(L"server") &&
|
||||
config[L"server"].has_string_field(L"address") && config[L"server"].has_number_field(L"port"))
|
||||
if (config.is_object() && config.has_object_field(L"backend") &&
|
||||
config[L"backend"].has_string_field(L"address") && config[L"backend"].has_number_field(L"port"))
|
||||
{
|
||||
address = "http://" + to_string(config[L"server"][L"address"]) + ":" + to_string(config[L"server"][L"port"].as_number().to_int32());
|
||||
log("Starting server on " + address);
|
||||
address = "http://" + to_string(config[L"backend"][L"address"]) + ":" + to_string(config[L"backend"][L"port"].as_number().to_int32());
|
||||
log("Starting backend on " + address);
|
||||
}
|
||||
else
|
||||
log("Error reading configuration file. Starting server on " + address);
|
||||
log("Error reading configuration file. Starting backend on " + address);
|
||||
|
||||
if (config.is_object() && config.has_object_field(L"authentication"))
|
||||
{
|
||||
|
||||
2
client/.vscode/settings.json
vendored
@ -1,2 +0,0 @@
|
||||
{
|
||||
}
|
||||
19
client/.vscode/tasks.json
vendored
@ -1,19 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "server",
|
||||
"type": "shell",
|
||||
"command": "npm run debug",
|
||||
"isBackground": true
|
||||
},
|
||||
{
|
||||
"label": "server-nodcs",
|
||||
"type": "shell",
|
||||
"command": "npm run debug-nodcs",
|
||||
"isBackground": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
FROM node:20-alpine AS appbuild
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
COPY package.json ./
|
||||
COPY package-lock.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build-release-linux
|
||||
|
||||
FROM node:20-alpine
|
||||
WORKDIR /usr/src/app
|
||||
COPY package.json ./
|
||||
COPY package-lock.json ./
|
||||
RUN npm install --omit=dev
|
||||
COPY . .
|
||||
COPY --from=appbuild /usr/src/app/public ./public
|
||||
EXPOSE 3000
|
||||
CMD npm start
|
||||
@ -1,194 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const yargs = require('yargs');
|
||||
const prompt = require('prompt-sync')({sigint: true});
|
||||
const sha256 = require('sha256');
|
||||
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');
|
||||
yargs.alias('b', 'backendPort').describe('b', 'Backend port').number('b');
|
||||
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() {
|
||||
/* Check that we can read the json */
|
||||
if (fs.existsSync(jsonPath)) {
|
||||
var json = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
|
||||
|
||||
var address = args.address ?? json["server"]["address"];
|
||||
var clientPort = args.clientPort ?? json["client"]["port"];
|
||||
var backendPort = args.backendPort ?? json["server"]["port"];
|
||||
var gameMasterPassword = args.gameMasterPassword? sha256(args.gameMasterPassword): json["authentication"]["gameMasterPassword"];
|
||||
var blueCommanderPassword = args.blueCommanderPassword? sha256(args.blueCommanderPassword): json["authentication"]["blueCommanderPassword"];
|
||||
var redCommanderPassword = args.redCommanderPassword? sha256(args.redCommanderPassword): json["authentication"]["redCommanderPassword"];
|
||||
|
||||
/* Run in interactive mode */
|
||||
if (args.address === undefined && args.clientPort === undefined && args.backendPort === undefined &&
|
||||
args.gameMasterPassword === undefined && args.blueCommanderPassword === undefined && args.redCommanderPassword === undefined) {
|
||||
|
||||
var newValue;
|
||||
var result;
|
||||
|
||||
/* Get the new address */
|
||||
newValue = prompt(`Insert an address or press Enter to keep current value ${address}. Use * for any address: `);
|
||||
address = newValue !== ""? newValue: address;
|
||||
|
||||
/* Get the new client port */
|
||||
while (true) {
|
||||
newValue = prompt(`Insert a client port or press Enter to keep current value ${clientPort}. Integers between 1025 and 65535: `);
|
||||
if (newValue === "")
|
||||
break;
|
||||
result = Number(newValue);
|
||||
|
||||
if (!isNaN(result) && Number.isInteger(result) && result > 1024 && result <= 65535)
|
||||
break;
|
||||
}
|
||||
clientPort = newValue? result: clientPort;
|
||||
|
||||
/* Get the new backend port */
|
||||
while (true) {
|
||||
newValue = prompt(`Insert a backend port or press Enter to keep current value ${backendPort}. Integers between 1025 and 65535: `);
|
||||
if (newValue === "")
|
||||
break;
|
||||
result = Number(newValue);
|
||||
|
||||
if (!isNaN(result) && Number.isInteger(result) && result > 1024 && result <= 65535 && result != clientPort)
|
||||
break;
|
||||
|
||||
if (result === clientPort)
|
||||
console.log("Client port and backend port must be different.");
|
||||
}
|
||||
backendPort = newValue? result: backendPort;
|
||||
|
||||
/* Get the new Game Master password */
|
||||
while (true) {
|
||||
newValue = prompt(`Insert a new Game Master password or press Enter to keep current value: `, {echo: "*"});
|
||||
gameMasterPassword = newValue !== ""? sha256(newValue): gameMasterPassword;
|
||||
|
||||
// Check if Game Master password is unique
|
||||
if (gameMasterPassword === blueCommanderPassword || gameMasterPassword === redCommanderPassword) {
|
||||
console.log("Game Master password must be different from other passwords. Please try again.");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the new Blue Commander password */
|
||||
while (true) {
|
||||
newValue = prompt(`Insert a new Blue Commander password or press Enter to keep current value: `, {echo: "*"});
|
||||
blueCommanderPassword = newValue !== ""? sha256(newValue): blueCommanderPassword;
|
||||
|
||||
// Check if Blue Commander password is unique
|
||||
if (blueCommanderPassword === gameMasterPassword || blueCommanderPassword === redCommanderPassword) {
|
||||
console.log("Blue Commander password must be different from other passwords. Please try again.");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the new Red Commander password */
|
||||
while (true) {
|
||||
newValue = prompt(`Insert a new Red Commander password or press Enter to keep current value: `, {echo: "*"});
|
||||
redCommanderPassword = newValue !== ""? sha256(newValue): redCommanderPassword;
|
||||
|
||||
// Check if Red Commander password is unique
|
||||
if (redCommanderPassword === gameMasterPassword || redCommanderPassword === blueCommanderPassword) {
|
||||
console.log("Red Commander password must be different from other passwords. Please try again.");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply the inputs */
|
||||
json["server"]["address"] = address;
|
||||
json["client"]["port"] = clientPort;
|
||||
json["server"]["port"] = backendPort;
|
||||
json["authentication"]["gameMasterPassword"] = gameMasterPassword;
|
||||
json["authentication"]["blueCommanderPassword"] = blueCommanderPassword;
|
||||
json["authentication"]["redCommanderPassword"] = redCommanderPassword;
|
||||
|
||||
/* Write the result to disk */
|
||||
const serialized = JSON.stringify(json, null, 4);
|
||||
fs.writeFileSync(jsonPath, serialized, 'utf8');
|
||||
console.log("Olympus.json updated correctly, goodbye!");
|
||||
}
|
||||
else {
|
||||
console.error("Error, could not read olympus.json file!")
|
||||
}
|
||||
|
||||
/* Wait a bit before closing the window */
|
||||
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 */
|
||||
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 +0,0 @@
|
||||
cp ./node_modules/leaflet/dist/leaflet.css ./public/stylesheets/leaflet/leaflet.css
|
||||
cp ./node_modules/leaflet-gesture-handling/dist/leaflet-gesture-handling.css ./public/stylesheets/leaflet/leaflet-gesture-handling.css
|
||||
cp ./node_modules/leaflet.nauticscale/dist/leaflet.nauticscale.js ./public/javascripts/leaflet.nauticscale.js
|
||||
cp ./node_modules/leaflet-path-drag/dist/L.Path.Drag.js ./public/javascripts/L.Path.Drag.js
|
||||
@ -1,8 +0,0 @@
|
||||
mkdir .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin
|
||||
|
||||
copy .\\index.js .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\index.js
|
||||
copy .\\plugin.json .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\plugin.json
|
||||
copy .\\style.css .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\style.css
|
||||
|
||||
mkdir .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\images
|
||||
copy .\\images\\*.* .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\images\\
|
||||
@ -1,5 +0,0 @@
|
||||
mkdir .\\..\\..\\public\\plugins\\controltipsplugin
|
||||
|
||||
copy .\\index.js .\\..\\..\\public\\plugins\\controltipsplugin\\index.js
|
||||
copy .\\plugin.json .\\..\\..\\public\\plugins\\controltipsplugin\\plugin.json
|
||||
copy .\\style.css .\\..\\..\\public\\plugins\\controltipsplugin\\style.css
|
||||
6317
client/plugins/controltips/package-lock.json
generated
@ -1,5 +0,0 @@
|
||||
mkdir .\\..\\..\\public\\plugins\\databasemanager
|
||||
|
||||
copy .\\index.js .\\..\\..\\public\\plugins\\databasemanager\\index.js
|
||||
copy .\\plugin.json .\\..\\..\\public\\plugins\\databasemanager\\plugin.json
|
||||
copy .\\style.css .\\..\\..\\public\\plugins\\databasemanager\\style.css
|
||||
6214
client/plugins/databasemanager/package-lock.json
generated
@ -1,661 +0,0 @@
|
||||
/* required styles */
|
||||
|
||||
.leaflet-pane,
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-tile-container,
|
||||
.leaflet-pane > svg,
|
||||
.leaflet-pane > canvas,
|
||||
.leaflet-zoom-box,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-layer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
/* Prevents IE11 from highlighting tiles in blue */
|
||||
.leaflet-tile::selection {
|
||||
background: transparent;
|
||||
}
|
||||
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
||||
.leaflet-safari .leaflet-tile {
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
}
|
||||
/* hack that prevents hw layers "stretching" when loading new tiles */
|
||||
.leaflet-safari .leaflet-tile-container {
|
||||
width: 1600px;
|
||||
height: 1600px;
|
||||
-webkit-transform-origin: 0 0;
|
||||
}
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
|
||||
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
|
||||
.leaflet-container .leaflet-overlay-pane svg {
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
.leaflet-container .leaflet-marker-pane img,
|
||||
.leaflet-container .leaflet-shadow-pane img,
|
||||
.leaflet-container .leaflet-tile-pane img,
|
||||
.leaflet-container img.leaflet-image-layer,
|
||||
.leaflet-container .leaflet-tile {
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.leaflet-container img.leaflet-tile {
|
||||
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
|
||||
mix-blend-mode: plus-lighter;
|
||||
}
|
||||
|
||||
.leaflet-container.leaflet-touch-zoom {
|
||||
-ms-touch-action: pan-x pan-y;
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag {
|
||||
-ms-touch-action: pinch-zoom;
|
||||
/* Fallback for FF which doesn't support pinch-zoom */
|
||||
touch-action: none;
|
||||
touch-action: pinch-zoom;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.leaflet-container {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.leaflet-container a {
|
||||
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
|
||||
}
|
||||
.leaflet-tile {
|
||||
filter: inherit;
|
||||
visibility: hidden;
|
||||
}
|
||||
.leaflet-tile-loaded {
|
||||
visibility: inherit;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
width: 0;
|
||||
height: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 800;
|
||||
}
|
||||
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
||||
.leaflet-overlay-pane svg {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.leaflet-pane { z-index: 400; }
|
||||
|
||||
.leaflet-tile-pane { z-index: 200; }
|
||||
.leaflet-overlay-pane { z-index: 400; }
|
||||
.leaflet-shadow-pane { z-index: 500; }
|
||||
.leaflet-marker-pane { z-index: 600; }
|
||||
.leaflet-tooltip-pane { z-index: 650; }
|
||||
.leaflet-popup-pane { z-index: 700; }
|
||||
|
||||
.leaflet-map-pane canvas { z-index: 100; }
|
||||
.leaflet-map-pane svg { z-index: 200; }
|
||||
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.lvml {
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
/* control positioning */
|
||||
|
||||
.leaflet-control {
|
||||
position: relative;
|
||||
z-index: 800;
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-top {
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-right {
|
||||
right: 0;
|
||||
}
|
||||
.leaflet-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.leaflet-left {
|
||||
left: 0;
|
||||
}
|
||||
.leaflet-control {
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
float: right;
|
||||
}
|
||||
.leaflet-top .leaflet-control {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.leaflet-left .leaflet-control {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* zoom and fade animations */
|
||||
|
||||
.leaflet-fade-anim .leaflet-popup {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||
opacity: 1;
|
||||
}
|
||||
.leaflet-zoom-animated {
|
||||
-webkit-transform-origin: 0 0;
|
||||
-ms-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
svg.leaflet-zoom-animated {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-tile,
|
||||
.leaflet-pan-anim .leaflet-tile {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-hide {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* cursors */
|
||||
|
||||
.leaflet-interactive {
|
||||
cursor: pointer;
|
||||
}
|
||||
.leaflet-grab {
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: grab;
|
||||
}
|
||||
.leaflet-crosshair,
|
||||
.leaflet-crosshair .leaflet-interactive {
|
||||
cursor: crosshair;
|
||||
}
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-control {
|
||||
cursor: auto;
|
||||
}
|
||||
.leaflet-dragging .leaflet-grab,
|
||||
.leaflet-dragging .leaflet-grab .leaflet-interactive,
|
||||
.leaflet-dragging .leaflet-marker-draggable {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* marker & overlays interactivity */
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-pane > svg path,
|
||||
.leaflet-tile-container {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.leaflet-marker-icon.leaflet-interactive,
|
||||
.leaflet-image-layer.leaflet-interactive,
|
||||
.leaflet-pane > svg path.leaflet-interactive,
|
||||
svg.leaflet-image-layer.leaflet-interactive path {
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* visual tweaks */
|
||||
|
||||
.leaflet-container {
|
||||
background: #ddd;
|
||||
outline-offset: 1px;
|
||||
}
|
||||
.leaflet-container a {
|
||||
color: #0078A8;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
border: 2px dotted #38f;
|
||||
background: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
|
||||
/* general typography */
|
||||
.leaflet-container {
|
||||
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
/* general toolbar styles */
|
||||
|
||||
.leaflet-bar {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
.leaflet-bar a,
|
||||
.leaflet-control-layers-toggle {
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-bar a:hover,
|
||||
.leaflet-bar a:focus {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.leaflet-bar a:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.leaflet-bar a.leaflet-disabled {
|
||||
cursor: default;
|
||||
background-color: #f4f4f4;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-bar a {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:first-child {
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
/* zoom control */
|
||||
|
||||
.leaflet-control-zoom-in,
|
||||
.leaflet-control-zoom-out {
|
||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||
text-indent: 1px;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
|
||||
/* layers control */
|
||||
|
||||
.leaflet-control-layers {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers.png);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.leaflet-retina .leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers-2x.png);
|
||||
background-size: 26px 26px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers-toggle {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.leaflet-control-layers .leaflet-control-layers-list,
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||
display: none;
|
||||
}
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.leaflet-control-layers-expanded {
|
||||
padding: 6px 10px 6px 6px;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-layers-scrollbar {
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.leaflet-control-layers-selector {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
.leaflet-control-layers label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
font-size: 1.08333em;
|
||||
}
|
||||
.leaflet-control-layers-separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 5px -10px 5px -6px;
|
||||
}
|
||||
|
||||
/* Default icon URLs */
|
||||
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
|
||||
background-image: url(images/marker-icon.png);
|
||||
}
|
||||
|
||||
|
||||
/* attribution and scale controls */
|
||||
|
||||
.leaflet-container .leaflet-control-attribution {
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
margin: 0;
|
||||
}
|
||||
.leaflet-control-attribution,
|
||||
.leaflet-control-scale-line {
|
||||
padding: 0 5px;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.leaflet-control-attribution a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.leaflet-control-attribution a:hover,
|
||||
.leaflet-control-attribution a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.leaflet-attribution-flag {
|
||||
display: inline !important;
|
||||
vertical-align: baseline !important;
|
||||
width: 1em;
|
||||
height: 0.6669em;
|
||||
}
|
||||
.leaflet-left .leaflet-control-scale {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control-scale {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.leaflet-control-scale-line {
|
||||
border: 2px solid #777;
|
||||
border-top: none;
|
||||
line-height: 1.1;
|
||||
padding: 2px 5px 1px;
|
||||
white-space: nowrap;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
text-shadow: 1px 1px #fff;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child) {
|
||||
border-top: 2px solid #777;
|
||||
border-bottom: none;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||
border-bottom: 2px solid #777;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-attribution,
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
border: 2px solid rgba(0,0,0,0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
|
||||
/* popup */
|
||||
|
||||
.leaflet-popup {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
text-align: left;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
margin: 13px 24px 13px 20px;
|
||||
line-height: 1.3;
|
||||
font-size: 13px;
|
||||
font-size: 1.08333em;
|
||||
min-height: 1px;
|
||||
}
|
||||
.leaflet-popup-content p {
|
||||
margin: 17px 0;
|
||||
margin: 1.3em 0;
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-top: -1px;
|
||||
margin-left: -20px;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-popup-tip {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
padding: 1px;
|
||||
|
||||
margin: -10px auto 0;
|
||||
pointer-events: auto;
|
||||
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.leaflet-popup-content-wrapper,
|
||||
.leaflet-popup-tip {
|
||||
background: white;
|
||||
color: #333;
|
||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border: none;
|
||||
text-align: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font: 16px/24px Tahoma, Verdana, sans-serif;
|
||||
color: #757575;
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button:hover,
|
||||
.leaflet-container a.leaflet-popup-close-button:focus {
|
||||
color: #585858;
|
||||
}
|
||||
.leaflet-popup-scrolled {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||
-ms-zoom: 1;
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
width: 24px;
|
||||
margin: 0 auto;
|
||||
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-control-zoom,
|
||||
.leaflet-oldie .leaflet-control-layers,
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper,
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
|
||||
/* div icon */
|
||||
|
||||
.leaflet-div-icon {
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||
|
||||
|
||||
/* Tooltip */
|
||||
/* Base styles for the element that has a tooltip */
|
||||
.leaflet-tooltip {
|
||||
position: absolute;
|
||||
padding: 6px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
color: #222;
|
||||
white-space: nowrap;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-tooltip.leaflet-interactive {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-tooltip-top:before,
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border: 6px solid transparent;
|
||||
background: transparent;
|
||||
content: "";
|
||||
}
|
||||
|
||||
/* Directions */
|
||||
|
||||
.leaflet-tooltip-bottom {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.leaflet-tooltip-top {
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-top:before {
|
||||
left: 50%;
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-top:before {
|
||||
bottom: 0;
|
||||
margin-bottom: -12px;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before {
|
||||
top: 0;
|
||||
margin-top: -12px;
|
||||
margin-left: -6px;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-left {
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-right {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
top: 50%;
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before {
|
||||
right: 0;
|
||||
margin-right: -12px;
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-right:before {
|
||||
left: 0;
|
||||
margin-left: -12px;
|
||||
border-right-color: #fff;
|
||||
}
|
||||
|
||||
/* Printing */
|
||||
|
||||
@media print {
|
||||
/* Prevent printers from removing background-images of controls. */
|
||||
.leaflet-control {
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
cd scripts
|
||||
call copy.bat
|
||||
cd ..
|
||||
call browserify ./src/index.ts --debug -o ./public/javascripts/bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]
|
||||
@ -1,15 +0,0 @@
|
||||
cd scripts
|
||||
call copy.bat
|
||||
cd ..
|
||||
call browserify ./src/index.ts -o ./public/javascripts/bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]
|
||||
|
||||
echo D|xcopy /Y /S /E .\bin ..\build\client\bin
|
||||
echo D|xcopy /Y /S /E .\public ..\build\client\public
|
||||
echo D|xcopy /Y /S /E .\routes ..\build\client\routes
|
||||
echo D|xcopy /Y /S /E .\views ..\build\client\views
|
||||
|
||||
echo F|xcopy /Y .\app.js ..\build\client\app.js
|
||||
echo F|xcopy /Y .\client.js ..\build\client\client.js
|
||||
echo F|xcopy /Y .\package.json ..\build\client\package.json
|
||||
|
||||
echo F|xcopy /Y /I .\*.vbs ..\build\client
|
||||
@ -1,6 +0,0 @@
|
||||
cd ..
|
||||
echo F|xcopy /Y .\node_modules\leaflet\dist\leaflet.css .\public\stylesheets\leaflet\leaflet.css
|
||||
echo F|xcopy /Y .\node_modules\leaflet-gesture-handling\dist\leaflet-gesture-handling.css .\public\stylesheets\leaflet\leaflet-gesture-handling.css
|
||||
echo F|xcopy /Y .\node_modules\leaflet.nauticscale\dist\leaflet.nauticscale.js .\public\javascripts\leaflet.nauticscale.js
|
||||
echo F|xcopy /Y .\node_modules\leaflet-path-drag\dist\L.Path.Drag.js .\public\javascripts\L.Path.Drag.js
|
||||
cd scripts
|
||||
@ -1,10 +0,0 @@
|
||||
cd scripts
|
||||
call ./copy.bat
|
||||
cd ..
|
||||
|
||||
REM create a "fake" dcs Saved Games folder
|
||||
mkdir "%temp%\DCS Olympus\dcs"
|
||||
echo F|xcopy /Y "..\olympus.json" "%temp%\DCS Olympus\dcs\Config\olympus.json"
|
||||
echo D|xcopy /Y /S /E "..\databases" "%temp%\DCS Olympus\dcs\Mods\Services\Olympus\databases"
|
||||
|
||||
concurrently --kill-others "node ./bin/demo --config \"%temp%\DCS Olympus\dcs\Config\olympus.json\"" "npm run watch" "nodemon --ignore ./public/databases/ ./bin/www -- --config \"%temp%\DCS Olympus\dcs\Config\olympus.json\""
|
||||
@ -1,7 +0,0 @@
|
||||
@echo off
|
||||
cd scripts
|
||||
call ./copy.bat
|
||||
cd ..
|
||||
|
||||
set /p "config=Enter DCS Saved Games folder location: "
|
||||
concurrently --kill-others "npm run watch" "nodemon --ignore ./public/databases/ ./bin/www -- --config \"%config%\Config\Olympus.json\""
|
||||
@ -1 +0,0 @@
|
||||
watchify ./src/index.ts --debug -o ./public/javascripts/bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]
|
||||
@ -1,82 +0,0 @@
|
||||
import Ajv from "ajv";
|
||||
import { AnySchemaObject } from "ajv/dist/core";
|
||||
|
||||
|
||||
// For future extension
|
||||
abstract class JSONSchemaValidator {
|
||||
|
||||
#ajv:Ajv;
|
||||
#compiledValidator:any;
|
||||
#schema!:AnySchemaObject;
|
||||
|
||||
constructor( schema:AnySchemaObject ) {
|
||||
this.#schema = schema;
|
||||
|
||||
this.#ajv = new Ajv({
|
||||
"allErrors": true
|
||||
});
|
||||
|
||||
this.#compiledValidator = this.getAjv().compile(this.getSchema());
|
||||
|
||||
}
|
||||
|
||||
getAjv() {
|
||||
return this.#ajv;
|
||||
}
|
||||
|
||||
getCompiledValidator() {
|
||||
return this.#compiledValidator;
|
||||
}
|
||||
|
||||
getErrors() {
|
||||
return this.getCompiledValidator().errors;
|
||||
}
|
||||
|
||||
getSchema() {
|
||||
return this.#schema;
|
||||
}
|
||||
|
||||
validate(data:any) {
|
||||
return (this.getCompiledValidator())(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export class AirbasesJSONSchemaValidator extends JSONSchemaValidator {
|
||||
|
||||
constructor() {
|
||||
|
||||
const schema = require("../schemas/airbases.schema.json");
|
||||
|
||||
super( schema );
|
||||
|
||||
[
|
||||
require( "../../public/databases/airbases/caucasus.json" ),
|
||||
require( "../../public/databases/airbases/falklands.json" ),
|
||||
require( "../../public/databases/airbases/marianas.json" ),
|
||||
require( "../../public/databases/airbases/nevada.json" ),
|
||||
require( "../../public/databases/airbases/normandy.json" ),
|
||||
require( "../../public/databases/airbases/persiangulf.json" ),
|
||||
require( "../../public/databases/airbases/sinaimap.json" ),
|
||||
require( "../../public/databases/airbases/syria.json" ),
|
||||
require( "../../public/databases/airbases/thechannel.json" )
|
||||
].forEach( data => {
|
||||
const validate = this.getAjv().compile(this.getSchema());
|
||||
const valid = validate(data);
|
||||
|
||||
if (!valid) console.error(validate.errors);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export class ImportFileJSONSchemaValidator extends JSONSchemaValidator {
|
||||
|
||||
constructor() {
|
||||
const schema = require("../schemas/importdata.schema.json");
|
||||
super( schema );
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
client:
|
||||
build: client
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- ./olympus.json:/usr/src/olympus.json
|
||||
10
frontend/check_setup.bat
Normal file
@ -0,0 +1,10 @@
|
||||
@echo off
|
||||
|
||||
echo check_setup starting...
|
||||
if exist "setup" (
|
||||
echo setup.bat has already been called, skipping...
|
||||
) else (
|
||||
echo setup.bat has not been called yet, installing!
|
||||
call .\setup.bat
|
||||
)
|
||||
echo check_setup completed!
|
||||
5
frontend/server/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"rioj7.command-variable"
|
||||
]
|
||||
}
|
||||
41
frontend/server/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Server (DCS)",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"args": ["--config", "${input:enterDir}/Config/olympus.json"],
|
||||
"program": "./bin/www"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Server (No DCS)",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"args": ["--config", "${input:enterDir}/Config/olympus.json"],
|
||||
"program": "./bin/www",
|
||||
"preLaunchTask": "demo-server"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "enterDir",
|
||||
"type": "command",
|
||||
"command": "extension.commandvariable.promptStringRemember",
|
||||
"args": {
|
||||
"key": "dir",
|
||||
"description": "DCS Saved Games folder (leave default for mock dcs)",
|
||||
"default": "../../mock-dcs"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
38
frontend/server/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "check-setup",
|
||||
"type": "shell",
|
||||
"command": "cd .. ; ./check_setup.bat",
|
||||
"isBackground": false
|
||||
},
|
||||
{
|
||||
"label": "demo-server",
|
||||
"type": "shell",
|
||||
"command": "./scripts/demo-server.bat",
|
||||
"args": ["${input:enterDir}/Config/olympus.json"],
|
||||
"isBackground": true,
|
||||
"dependsOn": ["check-setup"],
|
||||
"problemMatcher":{
|
||||
"owner": "custom",
|
||||
"base": "$tsc-watch",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "Please wait",
|
||||
"endsPattern": "Waiting for connections..."
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "enterDir",
|
||||
"type": "command",
|
||||
"command": "extension.commandvariable.remember",
|
||||
"args": { "key": "dir" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -33,7 +33,7 @@ module.exports = function (configLocation) {
|
||||
|
||||
/* Define middleware */
|
||||
app.use(logger('dev'));
|
||||
app.use('/olympus', createProxyMiddleware({ target: `http://${config["server"]["address"]}:${config["server"]["port"]}`, changeOrigin: true }));
|
||||
app.use('/olympus', createProxyMiddleware({ target: `http://${config["backend"]["address"]}:${config["backend"]["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')));
|
||||
@ -36,11 +36,11 @@ var http = require('http');
|
||||
*/
|
||||
|
||||
var configPort = null;
|
||||
if (config["server"] != undefined && config["server"]["port"] != undefined) {
|
||||
configPort = config["server"]["port"];
|
||||
if (config["backend"] != undefined && config["backend"]["port"] != undefined) {
|
||||
configPort = config["backend"]["port"];
|
||||
}
|
||||
|
||||
var port = normalizePort(configPort || '3000');
|
||||
var port = normalizePort(configPort || '3001');
|
||||
app.set('port', port);
|
||||
console.log("Express server listening on port: " + port)
|
||||
|
||||
@ -20,10 +20,10 @@ console.log("Please wait while DCS Olympus Server starts up...");
|
||||
console.log(`Config location: ${args["config"]}`)
|
||||
|
||||
/* Load the configuration file */
|
||||
var clientPort = 0;
|
||||
var frontendPort = 0;
|
||||
if (fs.existsSync(args["config"])) {
|
||||
var json = JSON.parse(fs.readFileSync(args["config"], 'utf-8'));
|
||||
clientPort = json["client"]["port"];
|
||||
frontendPort = json["frontend"]["port"];
|
||||
} else {
|
||||
console.log("Failed to read config, aborting!");
|
||||
return;
|
||||
@ -35,7 +35,7 @@ var debug = require('debug')('client:server');
|
||||
var http = require('http');
|
||||
|
||||
/* Normalize port */
|
||||
var port = normalizePort(clientPort);
|
||||
var port = normalizePort(frontendPort);
|
||||
app.set('port', port);
|
||||
console.log("Express server listening on port: " + port)
|
||||
|
||||
@ -8,10 +8,10 @@ yargs.alias('c', 'config').describe('c', 'olympus.json config location').string(
|
||||
args = yargs.argv;
|
||||
|
||||
console.log(`Config location: ${args["config"]}`)
|
||||
var clientPort = 3000;
|
||||
var frontendPort = 3000;
|
||||
if (fs.existsSync(args["config"])) {
|
||||
var json = JSON.parse(fs.readFileSync(args["config"], 'utf-8'));
|
||||
clientPort = json["client"]["port"];
|
||||
frontendPort = json["frontend"]["port"];
|
||||
} else {
|
||||
console.log("Failed to read config, trying default port");
|
||||
}
|
||||
@ -21,7 +21,7 @@ function createWindow() {
|
||||
icon: "./../img/olympus.ico"
|
||||
})
|
||||
|
||||
win.loadURL(`http://localhost:${clientPort}`);
|
||||
win.loadURL(`http://localhost:${frontendPort}`);
|
||||
win.setMenuBarVisibility(false);
|
||||
win.maximize();
|
||||
}
|
||||
31
frontend/server/package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "DCSOlympus Server",
|
||||
"main": "client.js",
|
||||
"version": "{{OLYMPUS_VERSION_NUMBER}}",
|
||||
"scripts": {
|
||||
"build-release": "call ./scripts/build-release.bat",
|
||||
"server": "node ./bin/www",
|
||||
"client": "electron ."
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"appjs": "^0.0.20",
|
||||
"appjs-win32": "^0.0.19",
|
||||
"body-parser": "^1.20.2",
|
||||
"debug": "~2.6.9",
|
||||
"ejs": "^3.1.8",
|
||||
"electron": "^28.0.0",
|
||||
"express": "^4.18.2",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"morgan": "~1.9.1",
|
||||
"open": "^10.0.0",
|
||||
"regedit": "^5.1.2",
|
||||
"save": "^2.9.0",
|
||||
"sha256": "^0.2.0",
|
||||
"srtm-elevation": "^2.1.2",
|
||||
"tcp-ping-port": "^1.0.1",
|
||||
"uuid": "^9.0.1",
|
||||
"yargs": "^17.7.2"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 251 B After Width: | Height: | Size: 251 B |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 756 B After Width: | Height: | Size: 756 B |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 237 B After Width: | Height: | Size: 237 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 556 B After Width: | Height: | Size: 556 B |
|
Before Width: | Height: | Size: 509 B After Width: | Height: | Size: 509 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 613 B After Width: | Height: | Size: 613 B |
|
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
|
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 287 B |
|
Before Width: | Height: | Size: 353 B After Width: | Height: | Size: 353 B |
|
Before Width: | Height: | Size: 283 B After Width: | Height: | Size: 283 B |
|
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 252 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 499 B After Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 231 B After Width: | Height: | Size: 231 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 221 B |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 549 B |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 582 B After Width: | Height: | Size: 582 B |
|
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 249 B |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 643 B After Width: | Height: | Size: 643 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
|
Before Width: | Height: | Size: 910 B After Width: | Height: | Size: 910 B |
|
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 484 B After Width: | Height: | Size: 484 B |
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
|
Before Width: | Height: | Size: 277 B After Width: | Height: | Size: 277 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 560 B After Width: | Height: | Size: 560 B |
|
Before Width: | Height: | Size: 841 B After Width: | Height: | Size: 841 B |
|
Before Width: | Height: | Size: 813 B After Width: | Height: | Size: 813 B |
|
Before Width: | Height: | Size: 286 B After Width: | Height: | Size: 286 B |
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 289 B |