diff --git a/src/main.js b/src/main.js index a26f2da..e793848 100644 --- a/src/main.js +++ b/src/main.js @@ -238,7 +238,7 @@ function getPlutoniumSession(game, token) { userInfo = data; - mainWindow.loadFile(path.join(__dirname, "src", "views", "games.html")); + mainWindow.loadFile(path.join(__dirname, "views", "games.html")); } catch (error) { reject(error); } @@ -254,14 +254,14 @@ function getPlutoniumSession(game, token) { }); } -function launch(plutoniumInstallDirectory, game, gameInstallDirectory, online) { +function launch(plutoniumInstallDir, game, gameInstallDirectory, online) { return new Promise(function (resolve, reject) { getPlutoniumSession(game, userInfo.token).then(function (data) { if (!data.successful) { return reject(new Error("Authentication has failed.")); } - let bootstrapperBinary = path.join(plutoniumInstallDirectory, "bin", "plutonium-bootstrapper-win32.exe"); + let bootstrapperBinary = path.join(plutoniumInstallDir, "bin", "plutonium-bootstrapper-win32.exe"); let bootstrapperArguments = [game, gameInstallDirectory]; if (online) { @@ -273,16 +273,20 @@ function launch(plutoniumInstallDirectory, game, gameInstallDirectory, online) { bootstrapperArguments.push("-lan"); } - let gameProcess = child_process.spawn(bootstrapperBinary, bootstrapperArguments, { - "cwd": plutoniumInstallDirectory, - "detached": true, - "stdio": "ignore" - }); + fsPromises.chmod(bootstrapperBinary, 0o755).then(function () { + let gameProcess = child_process.spawn(bootstrapperBinary, bootstrapperArguments, { + "cwd": plutoniumInstallDir, + "detached": true, + "stdio": "ignore" + }); - gameProcess.on("spawn", function () { - resolve(true); - }); - gameProcess.on("error", function (error) { + gameProcess.on("spawn", function () { + resolve(true); + }); + gameProcess.on("error", function (error) { + reject(error); + }); + }).catch(function (error) { reject(error); }); }); @@ -312,7 +316,7 @@ electron.app.once("ready", function () { }); } - mainWindow.loadFile(path.join(__dirname, "src", "views", "games.html")); + mainWindow.loadFile(path.join(__dirname, "views", "games.html")); }); } }).catch(function (error) { @@ -379,7 +383,7 @@ electron.ipcMain.handle("login", function (event, username, password) { console.error(error); }); - mainWindow.loadFile(path.join(__dirname, "src", "views", "games.html")); + mainWindow.loadFile(path.join(__dirname, "views", "games.html")); } catch (error) { reject(error); } @@ -397,10 +401,32 @@ electron.ipcMain.handle("login", function (event, username, password) { electron.ipcMain.handle("launch", function (event, game, online = true) { return new Promise(function (resolve, reject) { - if (!(game in config["game-directories"])) { + let gameConfig; + switch (game) { + case "iw5mp": + case "iw5sp": + gameConfig = "iw5"; + break; + case "t4mp": + case "t4sp": + gameConfig = "t4"; + break; + case "t5mp": + case "t5sp": + gameConfig = "t5"; + break; + case "t6mp": + case "t6zm": + gameConfig = "t6"; + break; + default: + return reject(new Error("Unknown game : " + game)); + } + + if (!(gameConfig in config["game-directories"])) { return resolve(false); } - let gameInstallDirectory = config["game-directories"][game]; + let gameInstallDirectory = config["game-directories"][gameConfig]; update.checkFiles(plutoniumManifest, plutoniumInstallDirectory).then(function (fileList) { let filesToUpdate = fileList.filter(function (file) { diff --git a/src/preload.js b/src/preload.js index 23e2975..c4fe2a2 100644 --- a/src/preload.js +++ b/src/preload.js @@ -3,3 +3,7 @@ const electron = require("electron"); electron.contextBridge.exposeInMainWorld("login", function (username, password) { return electron.ipcRenderer.invoke("login", username, password); }); + +electron.contextBridge.exposeInMainWorld("launch", function (game, online) { + return electron.ipcRenderer.invoke("launch", game, online); +}); diff --git a/src/update.js b/src/update.js index f9233bc..953ad38 100644 --- a/src/update.js +++ b/src/update.js @@ -3,6 +3,9 @@ const fs = require("node:fs"); const crypto = require("node:crypto"); const https = require("node:https"); +let runningDownloads = 0; +let downloadQueue = []; + function checkFileAgainstSHA1(baseDirectory, fileEntry) { return new Promise(function (resolve, reject) { let filePath = path.join(baseDirectory, fileEntry.name); @@ -19,6 +22,11 @@ function checkFileAgainstSHA1(baseDirectory, fileEntry) { let fileInputStream = fs.createReadStream(filePath); + fileInputStream.on("error", function (error) { + fileInputStream.close(); + reject(error); + }); + hash.on("readable", function () { let data = hash.read(); if (data) { @@ -35,6 +43,12 @@ function checkFileAgainstSHA1(baseDirectory, fileEntry) { function downloadFile(url, filePath) { return new Promise(function (resolve, reject) { + let dirPath = path.dirname(filePath); + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { + "recursive": true + }); + } let fileOutputStream = fs.createWriteStream(filePath); let request = https.request(url, { @@ -42,7 +56,7 @@ function downloadFile(url, filePath) { }, function (response) { if (response.statusCode !== 200) return reject(new Error("Got a non-OK response while trying to download a file.")); - fileOutputStream.on("end", function () { + fileOutputStream.on("close", function () { resolve(true); }); @@ -59,17 +73,18 @@ function downloadFile(url, filePath) { function processDownloadQueue(baseDirectory, baseURL, fileEntries) { return new Promise(function (resolve, reject) { - let runningDownloads = 0; - let queue = [...fileEntries]; + queue = [...fileEntries]; let finishCallback = function () { runningDownloads--; if (queue.length > 0 && runningDownloads < module.exports.concurrentDownloads) { - let currentEntry = queue.shift(); + let currentEntry = queue.shift().entry; downloadFile(baseURL + currentEntry.hash, path.join(baseDirectory, currentEntry.name)).then(finishCallback).catch((errorCallback).bind(currentEntry)); - } else { + } + + if (queue.length < 1 && runningDownloads < 1) { resolve(); } }; @@ -83,13 +98,20 @@ function processDownloadQueue(baseDirectory, baseURL, fileEntries) { if (this.retries > 3) return reject(error); this.retries++; - queue.push(this); + queue.push({ + "entry": this, + "ok": false + }); }; + if (fileEntries.length < 1) { + return resolve(); + } + for (let d = 0; d < module.exports.concurrentDownloads; d++) { if (queue.length < 1) break; - let currentEntry = queue.shift(); + let currentEntry = queue.shift().entry; runningDownloads++;