From 396c061a3ea34d87bfd10d65eaaa09b5d259dc4f Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Sun, 10 Mar 2024 18:38:55 +0100 Subject: [PATCH 1/2] Multiple manager improvements and bug fixes --- manager/ejs/passwords.ejs | 8 +-- manager/javascripts/dcsinstance.js | 97 ++++++++++++++++++++---------- manager/javascripts/filesystem.js | 12 +++- manager/javascripts/manager.js | 81 +++++++++++++++++++++---- manager/main.js | 6 +- manager/package.json | 1 + olympus.json | 2 +- 7 files changed, 154 insertions(+), 53 deletions(-) diff --git a/manager/ejs/passwords.ejs b/manager/ejs/passwords.ejs index cf8f45d0..c4ad8ca2 100644 --- a/manager/ejs/passwords.ejs +++ b/manager/ejs/passwords.ejs @@ -19,21 +19,21 @@ Game Master Password - "> + ">
Blue Commander Password - "> + ">
Red Commander Password - "> + ">
-
" style="color: var(--offwhite); font-size: var(--normal); color: var(--lightgray);"> +
Note: to keep the old passwords, click Next without editing any value.
diff --git a/manager/javascripts/dcsinstance.js b/manager/javascripts/dcsinstance.js index 4f5c87ff..2e2c58bb 100644 --- a/manager/javascripts/dcsinstance.js +++ b/manager/javascripts/dcsinstance.js @@ -1,4 +1,5 @@ const { getManager } = require('./managerfactory') +const { dialog } = require('@electron/remote'); var regedit = require('regedit').promisified; var fs = require('fs') var path = require('path') @@ -23,8 +24,8 @@ class DCSInstance { * @returns The list of DCS instances */ static async getInstances(force = false) { - if (this.instances === null || force) - DCSInstance.instances = this.findInstances(); + if (this.instances === null || force) + DCSInstance.instances = this.findInstances(); return DCSInstance.instances; } @@ -49,29 +50,45 @@ class DCSInstance { var result = await regedit.list(shellFoldersKey); /* Check that the registry read was successfull */ - if (result[shellFoldersKey] !== undefined && result[shellFoldersKey]["exists"] && result[shellFoldersKey]['values'][saveGamesKey] !== undefined && result[shellFoldersKey]['values'][saveGamesKey]['value'] !== undefined) { - /* Read all the folders in Saved Games */ - const searchpath = result[shellFoldersKey]['values'][saveGamesKey]['value']; - var folders = fs.readdirSync(searchpath).map((folder) => {return path.join(searchpath, folder);}); - var instances = []; - folders = folders.concat(getManager().getAdditionalDCSInstances()); - /* A DCS Instance is created if either the appsettings.lua or serversettings.lua file is detected */ - for (let i = 0; i < folders.length; i++) { - const folder = folders[i]; - if (fs.existsSync(path.join(folder, "Config", "appsettings.lua")) || fs.existsSync(path.join(folder, "Config", "serversettings.lua")) || getManager().getAdditionalDCSInstances().includes(folder)) { - logger.log(`Found instance in ${folder}, checking for Olympus`) - var newInstance = new DCSInstance(path.join(folder)); + let customSavedGamesFolder = (await getManager().getOptions()).savedGamesFolder; + console.log((await getManager().getOptions())) + if (customSavedGamesFolder !== undefined || (result[shellFoldersKey] !== undefined && result[shellFoldersKey]["exists"] && result[shellFoldersKey]['values'][saveGamesKey] !== undefined && result[shellFoldersKey]['values'][saveGamesKey]['value'] !== undefined)) { + try { + /* Read all the folders in Saved Games */ + const searchpath = customSavedGamesFolder !== undefined ? customSavedGamesFolder : result[shellFoldersKey]['values'][saveGamesKey]['value']; + var folders = fs.readdirSync(searchpath).map((folder) => { return path.join(searchpath, folder); }); + var instances = []; + folders = folders.concat(getManager().getAdditionalDCSInstances()); - /* Check if Olympus is already installed */ - getManager().setLoadingProgress(`Found instance in ${folder}, checking for Olympus...`, (i + 1) / folders.length * 100); - await newInstance.checkInstallation(); - instances.push(newInstance); + /* A DCS Instance is created if either the appsettings.lua or serversettings.lua file is detected */ + for (let i = 0; i < folders.length; i++) { + const folder = folders[i]; + if (fs.existsSync(path.join(folder, "Config", "appsettings.lua")) || fs.existsSync(path.join(folder, "Config", "serversettings.lua")) || getManager().getAdditionalDCSInstances().includes(folder)) { + logger.log(`Found instance in ${folder}, checking for Olympus`) + var newInstance = new DCSInstance(path.join(folder)); + + /* Check if Olympus is already installed */ + getManager().setLoadingProgress(`Found instance in ${folder}, checking for Olympus...`, (i + 1) / folders.length * 100); + await newInstance.checkInstallation(); + instances.push(newInstance); + } } + } catch (err) { + showErrorPopup(`
A critical error has occurred while detecting your DCS Instances locations.
You can find more info in ${path.join(__dirname, "..", "manager.log")}
`) + logger.error(err) } } else { logger.error("An error occured while trying to fetch the location of the DCS instances.") - showErrorPopup(`
An error occured while trying to fetch the location of the DCS instances.
You can find more info in ${getManager().getLogLocation()}
`); + showErrorPopup(`
An error occured while trying to fetch the location of the DCS instances.
After clicking Close, please select the location of your Saved Games folder.
`, async () => { + let res = await dialog.showOpenDialog({ properties: ["openDirectory"] }); + if (!res.canceled) { + getManager().setSavedGamesFolder(res.filePaths[0]); + } + else { + window.location.reload(); + } + }); } getManager().setLoadingProgress(`All DCS instances found!`, 100); @@ -104,7 +121,7 @@ class DCSInstance { setPopupLoadingProgress(`Installing hook scripts in ${instance.folder}...`, (i * 4 + 4) / (instancesToFix.length * 4) * 100); await sleep(100); - await installHooks(instance.folder); + await installHooks(instance.folder); } setPopupLoadingProgress(`All instances fixed!`, 100); @@ -114,7 +131,7 @@ class DCSInstance { folder = ""; name = ""; frontendPort = 3000; - backendPort = 3001; + backendPort = 4512; backendAddress = "localhost"; gameMasterPassword = ""; blueCommanderPassword = ""; @@ -156,10 +173,10 @@ class DCSInstance { this.installationType = 'singleplayer'; this.connectionsType = 'auto'; this.installCameraPlugin = 'install'; - + /* Check if the olympus.json file is detected. If true, Olympus is considered to be installed */ if (fs.existsSync(path.join(this.folder, "Config", "olympus.json"))) { - + getManager().setLoadingProgress(`Olympus installed in ${this.folder}`); try { /* Read the olympus.json */ @@ -459,7 +476,7 @@ class DCSInstance { /** Stop any node process running on the server port. This will stop either the server or the client depending on what is running * - */ + */ stop() { find('port', this.frontendPort) .then((list) => { @@ -494,24 +511,34 @@ class DCSInstance { await sleep(500); await applyConfiguration(getManager().getActiveInstance().folder, getManager().getActiveInstance()); + if (getManager().getActiveInstance().installCameraPlugin === 'install') { + setPopupLoadingProgress("Installing camera plugin...", 50); + await sleep(100); + await installCameraPlugin(getManager().getActiveInstance().folder); + } else { + setPopupLoadingProgress("Removing camera plugin (if installed)...", 50); + await sleep(100); + await deleteCameraPlugin(getManager().getActiveInstance().folder); + } + setPopupLoadingProgress("Editing completed!", 100); await sleep(1500); logger.log(`Editing completed successfully`); hidePopup(); - getManager().getMode() === "basic"? getManager().settingsPage.show(): getManager().instancesPage.show(); + getManager().getMode() === "basic" ? getManager().settingsPage.show() : getManager().instancesPage.show(); } catch (err) { logger.log(`An error occurred during editing: ${err}`); getManager().getActiveInstance().error = true; - + showErrorPopup(`
A critical error occurred!
Check ${getManager().getLogLocation()} for more info.
`) - getManager().getMode() === "basic"? getManager().settingsPage.show(): getManager().instancesPage.show(); + getManager().getMode() === "basic" ? getManager().settingsPage.show() : getManager().instancesPage.show(); } } /** Install this instance * - */ + */ async install() { showWaitLoadingPopup(`Please wait while Olympus is being installed in ${this.name}`); try { @@ -540,6 +567,10 @@ class DCSInstance { setPopupLoadingProgress("Installing camera plugin...", 83); await sleep(100); await installCameraPlugin(getManager().getActiveInstance().folder); + } else { + setPopupLoadingProgress("Removing camera plugin (if installed)...", 83); + await sleep(100); + await deleteCameraPlugin(getManager().getActiveInstance().folder); } setPopupLoadingProgress("Installation completed!", 100); @@ -605,9 +636,9 @@ class DCSInstance { hidePopup(); await getManager().reload(); - if (getManager().getMode() === 'basic') + if (getManager().getMode() === 'basic') getManager().settingsPage.show(); - else + else getManager().instancesPage.show(); return true; } catch (err) { @@ -616,12 +647,12 @@ class DCSInstance { /* Nested popup calls need to wait for animation to complete */ await sleep(300); showErrorPopup(`
An error has occurred while uninstalling the Olympus instance.
Make sure Olympus and DCS are not running.
You can find more info in ${path.join(__dirname, "..", "manager.log")}
`, () => { - if (getManager().getMode() === 'basic') + if (getManager().getMode() === 'basic') getManager().settingsPage.show(); - else + else getManager().instancesPage.show(); }); - } + } }, () => { getManager().setState('IDLE'); }); diff --git a/manager/javascripts/filesystem.js b/manager/javascripts/filesystem.js index 75b394e7..80cd7e21 100644 --- a/manager/javascripts/filesystem.js +++ b/manager/javascripts/filesystem.js @@ -163,9 +163,15 @@ async function applyConfiguration(folder, instance) { config["frontend"]["port"] = instance.frontendPort; config["backend"]["port"] = instance.backendPort; config["backend"]["address"] = instance.backendAddress; - config["authentication"]["gameMasterPassword"] = sha256(instance.gameMasterPassword); - config["authentication"]["blueCommanderPassword"] = sha256(instance.blueCommanderPassword); - config["authentication"]["redCommanderPassword"] = sha256(instance.redCommanderPassword); + + if (instance.gameMasterPassword !== "") + config["authentication"]["gameMasterPassword"] = sha256(instance.gameMasterPassword); + + if (instance.blueCommanderPassword !== "") + config["authentication"]["blueCommanderPassword"] = sha256(instance.blueCommanderPassword); + + if (instance.redCommanderPassword !== "") + config["authentication"]["redCommanderPassword"] = sha256(instance.redCommanderPassword); await fsp.writeFile(path.join(folder, "Config", "olympus.json"), JSON.stringify(config, null, 4)); logger.log(`Config succesfully applied in ${folder}`) diff --git a/manager/javascripts/manager.js b/manager/javascripts/manager.js index 1d59808a..8f4b701e 100644 --- a/manager/javascripts/manager.js +++ b/manager/javascripts/manager.js @@ -2,7 +2,7 @@ const path = require("path") const fs = require("fs"); const DCSInstance = require('./dcsinstance'); -const { showErrorPopup, showWaitPopup, showConfirmPopup } = require('./popup'); +const { showErrorPopup, showConfirmPopup } = require('./popup'); const { logger } = require("./filesystem") const ManagerPage = require("./managerpage"); @@ -236,6 +236,17 @@ class Manager { location.reload(); } + async setSavedGamesFolder(folder) { + var options = JSON.parse(fs.readFileSync("options.json")); + options.savedGamesFolder = folder; + fs.writeFileSync("options.json", JSON.stringify(options, null, 2)); + location.reload(); + } + + async getOptions() { + return JSON.parse(fs.readFileSync("options.json")); + } + /************************************************/ /* CALLBACKS */ /************************************************/ @@ -341,8 +352,8 @@ class Manager { /* When the camera control installation is selected */ async onInstallCameraControlClicked(type) { - this.connectionsTypePage.getElement().querySelector(`.install`).classList.toggle("selected", type === 'install'); - this.connectionsTypePage.getElement().querySelector(`.no-install`).classList.toggle("selected", type === 'no-install'); + this.cameraPage.getElement().querySelector(`.install`).classList.toggle("selected", type === 'install'); + this.cameraPage.getElement().querySelector(`.no-install`).classList.toggle("selected", type === 'no-install'); if (this.getActiveInstance()) this.getActiveInstance().installCameraPlugin = type; else { @@ -406,13 +417,33 @@ class Manager { } /* Installation type page */ } else if (this.activePage == this.cameraPage) { - this.activePage.hide(); - this.getState() === 'INSTALL' ? this.getActiveInstance().install() : this.getActiveInstance().edit(); + if (await this.checkDCSRunning()) { + showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to add Olympus to, then select Accept
`, async () => { + /* Nested popup calls need to wait for animation to complete */ + await sleep(300); + + this.activePage.hide(); + this.getState() === 'INSTALL' ? this.getActiveInstance().install() : this.getActiveInstance().edit(); + }); + } else { + this.activePage.hide(); + this.getState() === 'INSTALL' ? this.getActiveInstance().install() : this.getActiveInstance().edit(); + } /* Expert settings page */ } else if (this.activePage == this.expertSettingsPage) { if (await this.checkPorts() && await this.checkPasswords()) { - this.activePage.hide(); - this.getState() === 'INSTALL' ? this.getActiveInstance().install() : this.getActiveInstance().edit(); + if (await this.checkDCSRunning()) { + showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to add Olympus to, then select Accept
`, async () => { + /* Nested popup calls need to wait for animation to complete */ + await sleep(300); + + this.activePage.hide(); + this.getState() === 'INSTALL' ? this.getActiveInstance().install() : this.getActiveInstance().edit(); + }); + } else { + this.activePage.hide(); + this.getState() === 'INSTALL' ? this.getActiveInstance().install() : this.getActiveInstance().edit(); + } } } } @@ -541,7 +572,7 @@ class Manager { async checkPasswords() { if (this.getActiveInstance()) { - if (this.getActiveInstance().installed && !this.getActiveInstance().arePasswordsEdited()) { + if (this.getState() === 'EDIT' && !this.getActiveInstance().arePasswordsEdited()) { return true; } else { @@ -609,10 +640,20 @@ class Manager { var instance = await this.getClickedInstance(name); this.setActiveInstance(instance); await this.setState('UNINSTALL'); - if (instance.webserverOnline || instance.backendOnline) + if (instance.webserverOnline || instance.backendOnline) { showErrorPopup("
The selected Olympus instance is currently active
Please stop DCS and Olympus Server/Client before removing it!
") - else - await instance.uninstall(); + } else { + if (await this.checkDCSRunning()) { + showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to remove Olympus from, then select Accept
`, async () => { + /* Nested popup calls need to wait for animation to complete */ + await sleep(300); + + await instance.uninstall(); + }); + } else { + await instance.uninstall(); + } + } } async onLinkClicked(url) { @@ -758,6 +799,24 @@ class Manager { this.setActiveInstance(undefined); } + async checkDCSRunning() { + let ps = new Promise((res, rej) => { + exec('tasklist', function(err, stdout, stderr) { + console.log(stdout) + if (stdout.toLowerCase().includes("dcs.exe") || stdout.includes("dcs_server.exe")) { + res(true); + } else { + res(false); + } + }); + }) + try { + return await ps; + } catch { + return false; // An error occurred, let's hope DCS is not running! + } + } + /** Get the currently active instance, i.e. the instance that is being edited/installed/removed * * @returns The active instance diff --git a/manager/main.js b/manager/main.js index 4319a3ff..4f13d8d4 100644 --- a/manager/main.js +++ b/manager/main.js @@ -8,6 +8,8 @@ let window; /* Add the System32 folder to the environment for the shortcuts creation to work properly */ process.env['PATH'] = process.env['PATH'] + "%WINDIR%\\System32;" +require('@electron/remote/main').initialize() + function createWindow() { const window = new electronBrowserWindow({ width: 1200, @@ -18,11 +20,13 @@ function createWindow() { webPreferences: { contextIsolation: true, preload: path.join(__dirname, "javascripts", 'preload.js'), - nodeIntegration: true, + nodeIntegration: true }, icon: "./../img/olympus_configurator.ico" }); + require("@electron/remote/main").enable(window.webContents); + window.loadFile('index.html').then(() => { window.show(); }); window.on("maximize", () => { diff --git a/manager/package.json b/manager/package.json index 45b8f75c..fda57f6e 100644 --- a/manager/package.json +++ b/manager/package.json @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "dependencies": { + "@electron/remote": "^2.1.2", "adm-zip": "^0.5.10", "create-desktop-shortcuts": "^1.10.1", "dir-compare": "^4.2.0", diff --git a/olympus.json b/olympus.json index 1fe78bc0..d6f2b804 100644 --- a/olympus.json +++ b/olympus.json @@ -1,7 +1,7 @@ { "backend": { "address": "localhost", - "port": 3001 + "port": 4512 }, "authentication": { "gameMasterPassword": "4b8823ed9e5c2392ab4a791913bb8ce41956ea32e308b760eefb97536746dd33", From 9aad81588a2e8c5310935341d8491b1550d7fce3 Mon Sep 17 00:00:00 2001 From: Davide Passoni Date: Mon, 11 Mar 2024 17:25:35 +0100 Subject: [PATCH 2/2] Minor manager bugfixes --- manager/javascripts/dcsinstance.js | 1 - manager/javascripts/manager.js | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/manager/javascripts/dcsinstance.js b/manager/javascripts/dcsinstance.js index 2e2c58bb..c5fea078 100644 --- a/manager/javascripts/dcsinstance.js +++ b/manager/javascripts/dcsinstance.js @@ -52,7 +52,6 @@ class DCSInstance { /* Check that the registry read was successfull */ let customSavedGamesFolder = (await getManager().getOptions()).savedGamesFolder; - console.log((await getManager().getOptions())) if (customSavedGamesFolder !== undefined || (result[shellFoldersKey] !== undefined && result[shellFoldersKey]["exists"] && result[shellFoldersKey]['values'][saveGamesKey] !== undefined && result[shellFoldersKey]['values'][saveGamesKey]['value'] !== undefined)) { try { /* Read all the folders in Saved Games */ diff --git a/manager/javascripts/manager.js b/manager/javascripts/manager.js index 8f4b701e..5f2558b1 100644 --- a/manager/javascripts/manager.js +++ b/manager/javascripts/manager.js @@ -418,7 +418,7 @@ class Manager { /* Installation type page */ } else if (this.activePage == this.cameraPage) { if (await this.checkDCSRunning()) { - showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to add Olympus to, then select Accept
`, async () => { + showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to add Olympus to, then select Accept.
You can click Accept immediately if the running DCS instance is not the one you are adding Olympus to.
`, async () => { /* Nested popup calls need to wait for animation to complete */ await sleep(300); @@ -433,7 +433,7 @@ class Manager { } else if (this.activePage == this.expertSettingsPage) { if (await this.checkPorts() && await this.checkPasswords()) { if (await this.checkDCSRunning()) { - showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to add Olympus to, then select Accept
`, async () => { + showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to add Olympus to, then select Accept.
You can click Accept immediately if the running DCS instance is not the one you are adding Olympus to.
`, async () => { /* Nested popup calls need to wait for animation to complete */ await sleep(300); @@ -644,7 +644,7 @@ class Manager { showErrorPopup("
The selected Olympus instance is currently active
Please stop DCS and Olympus Server/Client before removing it!
") } else { if (await this.checkDCSRunning()) { - showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to remove Olympus from, then select Accept
`, async () => { + showConfirmPopup(`
DCS is running!
Please stop the DCS instance you are trying to remove Olympus from, then select Accept
.
You can click Accept immediately if the running DCS instance is not the one you are removing Olympus from.`, async () => { /* Nested popup calls need to wait for animation to complete */ await sleep(300); @@ -802,7 +802,6 @@ class Manager { async checkDCSRunning() { let ps = new Promise((res, rej) => { exec('tasklist', function(err, stdout, stderr) { - console.log(stdout) if (stdout.toLowerCase().includes("dcs.exe") || stdout.includes("dcs_server.exe")) { res(true); } else {