diff options
-rw-r--r-- | src/utils.js | 105 |
1 files changed, 96 insertions, 9 deletions
diff --git a/src/utils.js b/src/utils.js index e6fa5b0..797afe5 100644 --- a/src/utils.js +++ b/src/utils.js @@ -17,17 +17,22 @@ const { https } = require("follow-redirects"); process.chdir(app.getPath("appData")); +// Base settings var settings = { gamepath: "", lang: "en-US", autoupdate: true, zip: "/northstar.zip", + + // These files won't be overwritten when installing/updating + // Northstar, useful for config file. excludes: [ "ns_startup_args.txt", "ns_startup_args_dedi.txt" ] } +// Creates the settings file with the base settings if it doesn't exist. if (fs.existsSync("viper.json")) { settings = {...settings, ...JSON.parse(fs.readFileSync("viper.json", "utf8"))}; settings.zip = path.join(settings.gamepath + "/northstar.zip"); @@ -35,10 +40,14 @@ if (fs.existsSync("viper.json")) { console.log(lang("general.missingpath")); } - +// A simple function that checks if the game is running, which we use to +// not update Northstar when it is running. async function isGameRunning() { return new Promise(resolve => { let procs = ["Titanfall2.exe", "Titanfall2-unpacked.exe", "NorthstarLauncher.exe"]; + // While we could use a Node module to do this instead, I + // decided not to do so. As this achieves exactly the same + // thing. And it's not much more clunky. let cmd = (() => { switch (process.platform) { case "linux": return "ps -A"; @@ -59,6 +68,10 @@ async function isGameRunning() { }); } +// Handles auto updating Northstar. +// +// It uses isGameRunning() to ensure it doesn't run while the game is +// running, as that may have all kinds of issues. northstar_auto_updates: { if (!settings.autoupdate || !fs.existsSync("viper.json") || settings.gamepath.length === 0) { break northstar_auto_updates; @@ -69,6 +82,7 @@ northstar_auto_updates: { let distantVersion = await requests.getLatestNsVersion(); console.log(lang("cli.autoupdates.checking")); + // Checks if NS is outdated if (localVersion !== distantVersion) { console.log(lang("cli.autoupdates.available")); if (await isGameRunning()) { @@ -87,7 +101,9 @@ northstar_auto_updates: { setTimeout( _checkForUpdates, - 15 * 60 * 1000 // update checking interval must be bigger than cache validity duration + 15 * 60 * 1000 + // interval in between each update check + // by default 15 minutes. ); } @@ -95,10 +111,14 @@ northstar_auto_updates: { } +// Requests to set the game path +// +// If running with CLI it takes in the --setpath argument otherwise it +// open the systems file browser for the user to select a path. function setpath(win) { - if (! win) { + if (! win) { // CLI settings.gamepath = cli.param("setpath"); - } else { + } else { // GUI dialog.showOpenDialog({properties: ["openDirectory"]}).then(res => { if (res.canceled) { ipcMain.emit("newpath", null, false); @@ -121,10 +141,15 @@ function setpath(win) { cli.exit(); } +// As to not have to do the same one liner a million times, this +// function exists, as the name suggests, it simply writes the current +// settings to the disk. function saveSettings() { fs.writeFileSync(app.getPath("appData") + "/viper.json", JSON.stringify(settings)); } +// Returns the current Northstar version +// If not installed it'll return "unknown" function getNSVersion() { var versionFilePath = path.join(settings.gamepath, "ns_version.txt"); @@ -137,11 +162,11 @@ function getNSVersion() { } -/** - * Loads up Titanfall|2 version from gameversion.txt file. - * TODO This file is present on Origin install, should check if it's present with - * Steam install as well. - */ +// Returns the Titanfall 2 version from gameversion.txt file. +// If it fails it simply returns "unknown" +// +// TODO: This file is present on Origin install, should check if it's +// present with Steam install as well. function getTF2Version() { var versionFilePath = path.join(settings.gamepath, "gameversion.txt"); if (fs.existsSync(versionFilePath)) { @@ -151,7 +176,17 @@ function getTF2Version() { } } +// Installs/Updates Northstar +// +// If Northstar is already installed it'll be an update, otherwise it'll +// install it. It simply downloads the Northstar archive from GitHub, if +// it's outdated, then extracts it into the game path. +// +// As to handle not overwriting files we rename certain files to +// <file>.excluded, then rename them back after the extraction. The +// unzip module does not support excluding files directly. async function update() { + // Renames excluded files to <file>.excluded for (let i = 0; i < settings.excludes.length; i++) { let exclude = path.join(settings.gamepath + "/" + settings.excludes[i]); if (fs.existsSync(exclude)) { @@ -165,6 +200,7 @@ async function update() { const latestAvailableVersion = await requests.getLatestNsVersion(); + // Makes sure it is not already the latest version if (version === latestAvailableVersion) { ipcMain.emit("ns-update-event", "cli.update.uptodate.short"); console.log(lang("cli.update.uptodate"), version); @@ -179,11 +215,14 @@ async function update() { ipcMain.emit("ns-update-event", "cli.update.downloading"); } + // Start the download of the zip https.get(requests.getLatestNsVersionLink(), (res) => { let stream = fs.createWriteStream(settings.zip); res.pipe(stream); let received = 0; + // Progress messages, we should probably switch this to + // percentage instead of how much is downloaded. res.on("data", (chunk) => { received += chunk.length; ipcMain.emit("ns-update-event", lang("gui.update.downloading") + " " + (received / 1024 / 1024).toFixed(1) + "mb"); @@ -194,11 +233,14 @@ async function update() { winLog(lang("gui.update.extracting")); ipcMain.emit("ns-update-event", "gui.update.extracting"); console.log(lang("cli.update.downloaddone")); + // Extracts the zip, this is the part where we're actually + // installing Northstar. fs.createReadStream(settings.zip).pipe(unzip.Extract({path: settings.gamepath})) .on("finish", () => { fs.writeFileSync(path.join(settings.gamepath, "ns_version.txt"), latestAvailableVersion); ipcMain.emit("getversion"); + // Renames excluded files to their original name for (let i = 0; i < settings.excludes.length; i++) { let exclude = path.join(settings.gamepath + "/" + settings.excludes[i]); if (fs.existsSync(exclude + ".excluded")) { @@ -216,6 +258,11 @@ async function update() { }) } +// Updates Viper itself +// +// This uses electron updater to easily update and publish releases, it +// simply fetches it from GitHub and updates if it's outdated, very +// useful. Not much we have to do on our side. function updatevp(autoinstall) { const { autoUpdater } = require("electron-updater"); @@ -231,6 +278,10 @@ function updatevp(autoinstall) { autoUpdater.checkForUpdatesAndNotify(); } +// Launches the game +// +// Either Northstar or Vanilla. Linux support is not currently a thing, +// however it'll be added at some point. function launch(version) { if (process.platform == "linux") { console.error("error:", lang("cli.launch.linuxerror")) @@ -250,16 +301,27 @@ function launch(version) { } } +// Logs into the dev tools of the renderer function winLog(msg) { ipcMain.emit("winLog", msg, msg); } +// Sends an alert to the renderer function winAlert(msg) { ipcMain.emit("winAlert", msg, msg); } +// Used to manage mods. +// +// We can both get list of disabled mods, remove/install/toggle mods and +// other things akin to that, all kinds of mod related stuff let modpath = path.join(settings.gamepath, "R2Northstar/mods"); const mods = { + // Returns a list of mods + // + // It'll return 3 arrays, all, enabled, disabled. all being a + // combination of the other two, enabled being enabled mods, and you + // guessed it, disabled being disabled mods. list: () => { if (getNSVersion() == "unknown") { winLog(lang("general.notinstalled")) @@ -319,6 +381,13 @@ const mods = { all: [...mods, ...disabled] }; }, + + // Gets information about a mod + // + // Folder name, version, name and whatever else is in the mod.json, + // keep in mind if the mod developer didn't format their JSON file + // the absolute basics will be provided and we can't know the + // version or similar. get: (mod) => { if (getNSVersion() == "unknown") { winLog(lang("general.notinstalled")) @@ -337,6 +406,12 @@ const mods = { return false; }, + + // Installs mods from a file path + // + // Either a zip or folder is supported, we'll also try to search + // inside the zip or folder to see if buried in another folder or + // not, as sometimes that's the case. install: (mod) => { if (getNSVersion() == "unknown") { winLog(lang("general.notinstalled")) @@ -411,6 +486,11 @@ const mods = { }catch(err) {return notamod()} } }, + as well + // Removes mods + // + // Takes in the names of the mod then removes it, no confirmation, + // that'd be up to the GUI. remove: (mod) => { if (getNSVersion() == "unknown") { winLog(lang("general.notinstalled")) @@ -454,6 +534,13 @@ const mods = { cli.exit(1); } }, + + // Toggles mods + // + // If a mod is enabled it'll disable it, vice versa it'll enable it + // if it's disabled. You could have a direct .disable() function if + // you checked for if a mod is already disable and if not run the + // function. However we currently have no need for that. toggle: (mod, fork) => { if (getNSVersion() == "unknown") { winLog(lang("general.notinstalled")) |