- Step <%= instances.length === 1? "1": "2" %> of <%= instances.length === 1? "4": "5" %>
+ Step <%= instances.length === 1? "1": "2" %> of <%= instances.length === 1? "5": "6" %>
Do you want to add Olympus for singleplayer or multiplayer?
diff --git a/manager/javascripts/dcsinstance.js b/manager/javascripts/dcsinstance.js
index 2235b50d..73ce935e 100644
--- a/manager/javascripts/dcsinstance.js
+++ b/manager/javascripts/dcsinstance.js
@@ -6,7 +6,7 @@ const { checkPort, fetchWithTimeout, getFreePort } = require('./net')
const dircompare = require('dir-compare');
const { spawn } = require('child_process');
const find = require('find-process');
-const { installHooks, installMod, installJSON, applyConfiguration, installShortCuts, deleteMod, deleteHooks, deleteJSON, deleteShortCuts } = require('./filesystem')
+const { installHooks, installMod, installJSON, applyConfiguration, installShortCuts, deleteMod, deleteHooks, deleteJSON, deleteShortCuts, installCameraPlugin, deleteCameraPlugin } = require('./filesystem')
const { showErrorPopup, showConfirmPopup, showWaitLoadingPopup, setPopupLoadingProgress } = require('./popup')
const { logger } = require("./filesystem")
const { hidePopup } = require('./popup');
@@ -129,6 +129,7 @@ class DCSInstance {
fps = 0;
installationType = 'singleplayer';
connectionsType = 'auto';
+ installCameraPlugin = 'install';
gameMasterPasswordEdited = false;
blueCommanderPasswordEdited = false;
redCommanderPasswordEdited = false;
@@ -154,6 +155,7 @@ class DCSInstance {
this.error = false;
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"))) {
@@ -518,22 +520,28 @@ class DCSInstance {
await sleep(100);
await installHooks(getManager().getActiveInstance().folder);
- setPopupLoadingProgress("Installing mod folder...", 20);
+ setPopupLoadingProgress("Installing mod folder...", 16);
await sleep(100);
await installMod(getManager().getActiveInstance().folder, getManager().getActiveInstance().name);
- setPopupLoadingProgress("Installing JSON file...", 40);
+ setPopupLoadingProgress("Installing JSON file...", 33);
await sleep(100);
await installJSON(getManager().getActiveInstance().folder);
- setPopupLoadingProgress("Applying configuration...", 60);
+ setPopupLoadingProgress("Applying configuration...", 50);
await sleep(100);
await applyConfiguration(getManager().getActiveInstance().folder, getManager().getActiveInstance());
- setPopupLoadingProgress("Creating shortcuts...", 80);
+ setPopupLoadingProgress("Creating shortcuts...", 67);
await sleep(100);
await installShortCuts(getManager().getActiveInstance().folder, getManager().getActiveInstance().name);
+ if (getManager().getActiveInstance().installCameraPlugin === 'install') {
+ setPopupLoadingProgress("Installing camera plugin...", 83);
+ await sleep(100);
+ await installCameraPlugin(getManager().getActiveInstance().folder);
+ }
+
setPopupLoadingProgress("Installation completed!", 100);
await sleep(500);
logger.log(`Installation completed successfully`);
@@ -575,18 +583,22 @@ class DCSInstance {
await sleep(100);
await deleteMod(this.folder, this.name);
- setPopupLoadingProgress("Deleting hook scripts...", 25);
+ setPopupLoadingProgress("Deleting hook scripts...", 20);
await sleep(100);
await deleteHooks(this.folder);
- setPopupLoadingProgress("Deleting JSON...", 50);
+ setPopupLoadingProgress("Deleting JSON...", 40);
await sleep(100);
await deleteJSON(this.folder);
- setPopupLoadingProgress("Deleting shortcuts...", 75);
+ setPopupLoadingProgress("Deleting shortcuts...", 60);
await sleep(100);
await deleteShortCuts(this.folder, this.name);
+ setPopupLoadingProgress("Deleting camera plugin...", 80);
+ await sleep(100);
+ await deleteCameraPlugin(this.folder);
+
await sleep(500);
setPopupLoadingProgress("Instance removed!", 100);
logger.log(`Olympus removed from ${this.folder}`)
diff --git a/manager/javascripts/filesystem.js b/manager/javascripts/filesystem.js
index 96c2fd7e..75b394e7 100644
--- a/manager/javascripts/filesystem.js
+++ b/manager/javascripts/filesystem.js
@@ -11,6 +11,8 @@ var logger = new Console(output, output);
const date = new Date();
output.write(` ======================= New log starting at ${date.toString()} =======================\n`);
+var EXPORT_STRING = "pcall(function() local olympusLFS=require('lfs');dofile(olympusLFS.writedir()..[[Mods\\Services\\Olympus\\Scripts\\OlympusCameraControl.lua]]); end,nil) ";
+
/** Conveniency function to asynchronously delete a single file, with error catching
*
* @param {String} filePath The path to the file to delete
@@ -172,6 +174,29 @@ async function applyConfiguration(folder, instance) {
}
}
+/** Asynchronously install the camera control plugin
+ *
+ * @param {String} folder The base Saved Games folder where Olympus is installed
+ */
+async function installCameraPlugin(folder) {
+ logger.log(`Installing camera support plugin to DCS in ${folder}`);
+ /* If the export file doesn't exist, create it */
+ if (!(await exists(path.join(folder, "Scripts", "export.lua")))) {
+ await fsp.writeFile(path.join(folder, "Scripts", "export.lua"), EXPORT_STRING);
+ } else {
+ let content = await fsp.readFile(path.join(folder, "Scripts", "export.lua"), { encoding: 'utf8' });
+ if (content.indexOf(EXPORT_STRING) != -1) {
+ /* Looks like the export string is already installed, nothing to do */
+ }
+ else {
+ /* Append the export string at the end of the file */
+ content += ("\n" + EXPORT_STRING);
+ }
+ /* Write the content of the file */
+ await fsp.writeFile(path.join(folder, "Scripts", "export.lua"), content)
+ }
+}
+
/** Asynchronously deletes the Hooks script
*
* @param {String} folder The base Saved Games folder where Olympus is installed
@@ -231,15 +256,40 @@ async function deleteShortCuts(folder, name) {
logger.log(`ShortCuts deleted from ${folder} and desktop`);
}
+/** Asynchronously removes the camera plugin string from the export lua file
+ *
+ * @param {String} folder The base Saved Games folder where Olympus is installed
+ */
+async function deleteCameraPlugin(folder) {
+ logger.log(`Deleting camera support plugin to DCS in ${folder}`);
+ if (!(await exists(path.join(folder, "Scripts", "export.lua")))) {
+ /* If the export file doesn't exist, nothing to do */
+ } else {
+ let content = await fsp.readFile(path.join(folder, "Scripts", "export.lua"), { encoding: 'utf8' });
+ if (content.indexOf(EXPORT_STRING) ==+ -1) {
+ /* Looks like the export string is not installed, nothing to do */
+ }
+ else {
+ /* Remove the export string from the file */
+ content = content.replace(EXPORT_STRING, "")
+
+ /* Write the content of the file */
+ await fsp.writeFile(path.join(folder, "Scripts", "export.lua"), content)
+ }
+ }
+}
+
module.exports = {
applyConfiguration: applyConfiguration,
installJSON: installJSON,
installHooks: installHooks,
installMod: installMod,
- installShortCuts, installShortCuts,
+ installShortCuts: installShortCuts,
+ installCameraPlugin: installCameraPlugin,
deleteHooks: deleteHooks,
deleteJSON: deleteJSON,
deleteMod: deleteMod,
deleteShortCuts: deleteShortCuts,
+ deleteCameraPlugin: deleteCameraPlugin,
logger: logger
}
diff --git a/manager/javascripts/manager.js b/manager/javascripts/manager.js
index 353e8a3e..91848635 100644
--- a/manager/javascripts/manager.js
+++ b/manager/javascripts/manager.js
@@ -32,6 +32,7 @@ class Manager {
connectionsTypePage = null;
connectionsPage = null;
passwordsPage = null;
+ cameraPage = null;
resultPage = null;
instancesPage = null;
expertSettingsPage = null;
@@ -103,9 +104,9 @@ class Manager {
/* Get my public IP */
this.getPublicIP().then(
(IP) => { this.setIP(IP); },
- (err) => {
+ (err) => {
logger.log(err)
- this.setIP(undefined);
+ this.setIP(undefined);
}
)
@@ -142,6 +143,7 @@ class Manager {
this.connectionsTypePage = new WizardPage(this, "./ejs/connectionsType.ejs");
this.connectionsPage = new WizardPage(this, "./ejs/connections.ejs");
this.passwordsPage = new WizardPage(this, "./ejs/passwords.ejs");
+ this.cameraPage = new WizardPage(this, "./ejs/camera.ejs");
this.resultPage = new ManagerPage(this, "./ejs/result.ejs");
this.instancesPage = new ManagerPage(this, "./ejs/instances.ejs");
this.expertSettingsPage = new WizardPage(this, "./ejs/expertsettings.ejs");
@@ -159,7 +161,7 @@ class Manager {
this.setPort('backend', this.getActiveInstance().backendPort);
}
}
-
+
/* Always force the IDLE state when reaching the menu page */
this.menuPage.options.onShow = async () => {
await this.setState('IDLE');
@@ -337,6 +339,17 @@ 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');
+ if (this.getActiveInstance())
+ this.getActiveInstance().installCameraPlugin = type;
+ else {
+ showErrorPopup(`
A critical error occurred!
Check ${this.getLogLocation()} for more info.
`);
+ }
+ }
+
/* When the next button of a wizard page is clicked */
async onNextClicked() {
/* Choose which page to show depending on the active page */
@@ -360,11 +373,11 @@ class Manager {
this.activePage.hide();
this.typePage.show();
}
- /* Installation type page */
+ /* Installation type page */
} else if (this.activePage == this.typePage) {
this.activePage.hide();
this.connectionsTypePage.show();
- /* Connection type page */
+ /* Connection type page */
} else if (this.activePage == this.connectionsTypePage) {
if (this.getActiveInstance()) {
if (this.getActiveInstance().connectionsType === 'auto') {
@@ -374,24 +387,28 @@ class Manager {
else {
this.activePage.hide();
this.connectionsPage.show();
- (this.getMode() === 'basic'? this.connectionsPage: this.expertSettingsPage).getElement().querySelector(".backend-address .checkbox").classList.toggle("checked", this.getActiveInstance().backendAddress === '*')
+ (this.getMode() === 'basic' ? this.connectionsPage : this.expertSettingsPage).getElement().querySelector(".backend-address .checkbox").classList.toggle("checked", this.getActiveInstance().backendAddress === '*')
}
} else {
showErrorPopup(`
A critical error occurred!
Check ${this.getLogLocation()} for more info.
`)
}
- /* Connection page */
+ /* Connection page */
} else if (this.activePage == this.connectionsPage) {
if (await this.checkPorts()) {
this.activePage.hide();
this.passwordsPage.show();
- }
- /* Passwords page */
+ }
+ /* Passwords page */
} else if (this.activePage == this.passwordsPage) {
if (await this.checkPasswords()) {
this.activePage.hide();
- this.getState() === 'INSTALL' ? this.getActiveInstance().install() : this.getActiveInstance().edit();
+ this.cameraPage.show()
}
- /* Expert settings page */
+ /* Installation type page */
+ } else if (this.activePage == this.cameraPage) {
+ 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();
@@ -416,7 +433,7 @@ class Manager {
async onCancelClicked() {
this.activePage.hide();
await this.setState('IDLE');
- if (this.getMode() === "basic")
+ if (this.getMode() === "basic")
this.menuPage.show(true);
else
this.instancesPage.show(true);
@@ -441,7 +458,7 @@ class Manager {
if (this.getActiveInstance())
this.getActiveInstance().setBlueCommanderPassword(value);
- else
+ else
showErrorPopup(`
A critical error occurred!
Check ${this.getLogLocation()} for more info.
`);
}
@@ -450,9 +467,9 @@ class Manager {
input.placeholder = "";
}
- if (this.getActiveInstance())
+ if (this.getActiveInstance())
this.getActiveInstance().setRedCommanderPassword(value);
- else
+ else
showErrorPopup(`
A critical error occurred!
Check ${this.getLogLocation()} for more info.
`);
}
@@ -485,6 +502,20 @@ class Manager {
}
}
+ /* When the "Enable camera control plugin" checkbox is clicked */
+ async onEnableCameraPluginClicked() {
+ if (this.getActiveInstance()) {
+ if (this.getActiveInstance().installCameraPlugin === 'install') {
+ this.getActiveInstance().installCameraPlugin = 'no-install';
+ } else {
+ this.getActiveInstance().installCameraPlugin = 'install';
+ }
+ this.expertSettingsPage.getElement().querySelector(".camera-plugin .checkbox").classList.toggle("checked", this.getActiveInstance().installCameraPlugin === 'install')
+ } else {
+ showErrorPopup(`
A critical error occurred!
Check ${this.getLogLocation()} for more info.
`)
+ }
+ }
+
/* When the "Return to manager" button is pressed */
async onReturnClicked() {
await this.reload();
@@ -562,7 +593,7 @@ class Manager {
this.setActiveInstance(instance);
await this.setState('EDIT');
this.activePage.hide();
- (this.getMode() === 'basic'? this.typePage: this.expertSettingsPage).show();
+ (this.getMode() === 'basic' ? this.typePage : this.expertSettingsPage).show();
}
}
@@ -571,7 +602,7 @@ class Manager {
this.setActiveInstance(instance);
await this.setState('INSTALL');
this.activePage.hide();
- (this.getMode() === 'basic'? this.typePage: this.expertSettingsPage).show();
+ (this.getMode() === 'basic' ? this.typePage : this.expertSettingsPage).show();
}
async onUninstallClicked(name) {
@@ -579,7 +610,7 @@ class Manager {
this.setActiveInstance(instance);
await this.setState('UNINSTALL');
if (instance.webserverOnline || instance.backendOnline)
- showErrorPopup("
The selected Olympus instance is currently active
Please stop DCS and Olympus Server/Client before removing it!
")
+ showErrorPopup("
The selected Olympus instance is currently active
Please stop DCS and Olympus Server/Client before removing it!
")
else
await instance.uninstall();
}
@@ -620,11 +651,11 @@ class Manager {
this.getActiveInstance().setBackendPort(value);
}
- var successEls = (this.getMode() === 'basic'? this.connectionsPage: this.expertSettingsPage).getElement().querySelector(`.${port}-port`).querySelectorAll(".success");
+ var successEls = (this.getMode() === 'basic' ? this.connectionsPage : this.expertSettingsPage).getElement().querySelector(`.${port}-port`).querySelectorAll(".success");
for (let i = 0; i < successEls.length; i++) {
successEls[i].classList.toggle("hide", !success);
}
- var errorEls = (this.getMode() === 'basic'? this.connectionsPage: this.expertSettingsPage).getElement().querySelector(`.${port}-port`).querySelectorAll(".error");
+ var errorEls = (this.getMode() === 'basic' ? this.connectionsPage : this.expertSettingsPage).getElement().querySelector(`.${port}-port`).querySelectorAll(".error");
for (let i = 0; i < errorEls.length; i++) {
errorEls[i].classList.toggle("hide", success);
}
@@ -693,7 +724,7 @@ class Manager {
document.getElementById("loader").style.opacity = "0%";
window.setTimeout(() => {
document.getElementById("loader").classList.add("hide");
- }, 250);
+ }, 250);
}
async setActiveInstance(newActiveInstance) {
@@ -718,12 +749,12 @@ class Manager {
async setLogLocation(newLogLocation) {
this.options.logLocation = newLogLocation;
- }
-
+ }
+
async setState(newState) {
this.options.state = newState;
await DCSInstance.reloadInstances();
- if (newState === 'IDLE')
+ if (newState === 'IDLE')
this.setActiveInstance(undefined);
}
diff --git a/scripts/lua/camera/OlympusCameraControl.lua b/scripts/lua/backend/OlympusCameraControl.lua
similarity index 100%
rename from scripts/lua/camera/OlympusCameraControl.lua
rename to scripts/lua/backend/OlympusCameraControl.lua