Updated manager to allow updating

This commit is contained in:
Pax1601 2023-12-20 15:34:55 +01:00
parent 0a07f85fcf
commit 278d0bdd3c
5 changed files with 196 additions and 133 deletions

View File

@ -3,6 +3,10 @@
<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>
@ -58,6 +62,7 @@
<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>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#F2F2F2" d="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

View File

@ -6,7 +6,8 @@ const portfinder = require('portfinder')
const sha256 = require('sha256')
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
const createDesktopShortcut = require('create-desktop-shortcuts');
const 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}'
@ -37,29 +38,29 @@ const ipc = {
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);
}
// 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) {
@ -69,7 +70,7 @@ function showPopup(message, otherButton, otherButtonCallback) {
};
var popups = document.querySelectorAll(".popup");
for (let i = 0; i < popups.length; i++) {
document.body.removeChild(popups[i])
}
@ -78,8 +79,8 @@ function showPopup(message, otherButton, otherButtonCallback) {
var div = document.createElement("div");
div.classList.add("popup");
div.innerHTML = str;
document.body.appendChild(div);
document.body.appendChild(div);
div.querySelector(".apply").addEventListener("click", () => {
document.body.removeChild(div);
})
@ -91,7 +92,7 @@ function showPopup(message, otherButton, otherButtonCallback) {
}
function checkPort(port, callback) {
portfinder.getPort({port: port, stopPort: port}, (err, res) => {
portfinder.getPort({ port: port, stopPort: port }, (err, res) => {
if (err !== null) {
console.error(`Port ${port} already in use`);
callback(false);
@ -101,66 +102,116 @@ function checkPort(port, callback) {
});
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function installOlympus(folder) {
function installOlympus(folder) {
console.log(`Installing Olympus in ${folder}`);
fs.cpSync(path.join("..", "mod"), path.join(folder, "Mods", "Services", "Olympus"), {recursive: true});
fs.cpSync(path.join("..", "scripts", "OlympusHook.lua"), path.join(folder, "Scripts", "Hook", "OlympusHook.lua"));
fs.cpSync(path.join("..", "olympus.json"), path.join(folder, "Config", "olympus.json"));
if (createDesktopShortcut({
windows: {
filePath: path.resolve(__dirname, '..', '..', 'client', 'client.vbs'),
outputPath: folder,
name: "DCS Olympus Client",
arguments: `"${path.join(folder, "Config", "olympus.json")}"`,
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus.ico'),
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
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;
}
}) &&
createDesktopShortcut({
windows: {
filePath: path.resolve(__dirname, '..', '..', 'client', 'server.vbs'),
outputPath: folder,
name: "DCS Olympus Server",
arguments: `"${path.join(folder, "Config", "olympus.json")}"`,
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus_server.ico'),
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
}
})) {
console.log("Shorcuts created succesfully")
} else {
throw new Error("Error creating shortcuts");
} catch (e) {
console.error(e);
return false;
}
loadDivs();
return true;
}
async function uninstallOlympus(folder) {
function uninstallOlympus(folder) {
console.log(`Uninstalling Olympus from ${folder}`);
fs.rmSync(path.join(folder, "Mods", "Services", "Olympus"), {recursive: true});
fs.rmSync(path.join(folder, "Config", "olympus.json"));
loadDivs();
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;
}
async function applyConfiguration(folder, data) {
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"]);
fs.writeFileSync(path.join(folder, "Config", "olympus.json"), JSON.stringify(config, null, 4));
return true;
}
return false;
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 {
@ -180,10 +231,13 @@ class InstanceDiv {
var data = {
folder: this.folder,
installed: false,
index: instanceDivs.length * 9
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 = {
@ -191,6 +245,12 @@ class InstanceDiv {
...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) => {
@ -198,52 +258,28 @@ class InstanceDiv {
this.element.querySelector(".add").addEventListener("click", (e) => {
if (!e.srcElement.classList.contains("disabled")) {
showPopup("Please wait while Olympus is being installed");
delay(100)
.then(() => {
installOlympus(this.folder)
})
.then(() => {
showPopup("Olympus installed successfully. Use the provided form to set Olympus properties. All fields are mandatory. Click on \"Create desktop shortcuts\" to generate Olympus shortcuts on your desktop.", "Create desktop shortcuts", () => {
if (createDesktopShortcut({
windows: {
filePath: path.resolve(__dirname, '..', '..', 'client', 'client.vbs'),
name: "DCS Olympus Client",
arguments: `"${path.join(this.folder, "Config", "olympus.json")}"`,
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus.ico'),
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
}
}) && createDesktopShortcut({
windows: {
filePath: path.resolve(__dirname, '..', '..', 'client', 'server.vbs'),
name: "DCS Olympus Server",
arguments: `"${path.join(this.folder, "Config", "olympus.json")}"`,
icon: path.resolve(__dirname, '..', '..', 'img', 'olympus_server.ico'),
workingDirectory: path.resolve(__dirname, '..', '..', 'client')
}
})) {
showPopup("Shortcuts created successfully!")
} else {
showPopup("And error occurred while creating the shortcuts.")
}
});
}).catch(() => {
showPopup("An error has occurred during installation");
})
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")){
if (!e.srcElement.classList.contains("disabled")) {
showPopup("Please wait while Olympus is being uninstalled from DCS instance");
delay(100)
.then(() => {
uninstallOlympus(this.folder)
})
.then(() => {
showPopup("Olympus uninstalled successfully from DCS instance!");
}).catch(() => {
showPopup("An error has occurred during uninstallation");
})
window.setTimeout(() => {
if (uninstallOlympus(this.folder)) {
showPopup("Olympus uninstalled successfully from DCS instance!");
} else {
showPopup("An error has occurred during uninstallation");
}
}, 100);
}
});
@ -251,15 +287,26 @@ class InstanceDiv {
e.srcElement.classList.remove("blink");
if (!e.srcElement.classList.contains("disabled")) {
showPopup("Please wait while the configuration is being applied");
delay(100)
.then(() => {
applyConfiguration(this.folder, this.getFields())
})
.then(() => {
showPopup("Olympus configuration applied successfully!");
}).catch(() => {
showPopup("An error has occurred while applying the configuration");
})
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);
}
});
@ -276,7 +323,7 @@ class InstanceDiv {
getDiv() {
return this.element;
}
getFields() {
return {
clientPort: Number(this.element.querySelector("#client-port").value),
@ -291,7 +338,7 @@ class InstanceDiv {
checkFields() {
var data = this.getFields();
/* Clear existing errors */
/* Clear existing errors */
var inputs = this.element.querySelectorAll("input");
for (let i = 0; i < inputs.length; i++) {
inputs[i].classList.remove("error");
@ -300,10 +347,10 @@ class InstanceDiv {
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");
@ -380,20 +427,20 @@ class InstanceDiv {
}
function loadDivs() {
regedit.list(shellFoldersKey, function(err, result) {
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)
{
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, "Logs", "dcs.log"))) {
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)));
}
});

View File

@ -15,6 +15,7 @@
"electron": "^28.0.0",
"portfinder": "^1.0.32",
"regedit": "^5.1.2",
"sha256": "^0.2.0"
"sha256": "^0.2.0",
"win-version-info": "^6.0.1"
}
}

View File

@ -69,8 +69,8 @@ body {
column-gap: 10px;
}
#header>div:first-child>div:last-child {
width: 100px;
#header>div:first-of-type{
width: 300px;
}
#header>div:last-child {
@ -165,6 +165,11 @@ body {
margin-right: 15px;
}
.version {
font-size: 13px;
color: #F2F2F2;
}
.input-table {
padding: 0px;
margin: 0px;
@ -235,7 +240,7 @@ body {
}
.update {
padding: 5px 15px 5px 15px;
background-image: url("../icons/rotate-right-solid.svg");
}
.other {
@ -281,6 +286,10 @@ input.error {
color: #FF5858;
}
.accent-red {
color: #FF5858;
}
.accent-green {
color: #8bff63;
}
@ -293,12 +302,12 @@ input.error {
}
.blink {
animation: blinker 1s linear 3;
animation: blinker 1s linear infinite;
}
@keyframes blinker {
50% {
background-color: transparent;
color: transparent;
}
}