diff --git a/app/assets/js/assetexec.js b/app/assets/js/assetexec.js index d0ac3e8..1660b30 100644 --- a/app/assets/js/assetexec.js +++ b/app/assets/js/assetexec.js @@ -1,6 +1,6 @@ const {AssetGuard} = require('./assetguard.js') -const tracker = new AssetGuard(process.argv[2], process.argv[3]) +const tracker = new AssetGuard(process.argv[2], process.argv[3], process.argv[4]) console.log('AssetExec Started') // Temporary for debug purposes. diff --git a/app/assets/js/assetguard.js b/app/assets/js/assetguard.js index c1165cf..cbe9cb7 100644 --- a/app/assets/js/assetguard.js +++ b/app/assets/js/assetguard.js @@ -179,10 +179,11 @@ class AssetGuard extends EventEmitter { * values. Each identifier is resolved to an empty DLTracker. * * @param {string} basePath The base path for asset validation (game root). + * @param {string} launcherPath The root launcher directory. * @param {string} javaexec The path to a java executable which will be used * to finalize installation. */ - constructor(basePath, javaexec){ + constructor(basePath, launcherPath, javaexec){ super() this.totaldlsize = 0 this.progress = 0 @@ -193,6 +194,7 @@ class AssetGuard extends EventEmitter { this.java = new DLTracker([], 0) this.extractQueue = [] this.basePath = basePath + this.launcherPath = launcherPath this.javaexec = javaexec } @@ -373,41 +375,51 @@ class AssetGuard extends EventEmitter { /** * Statically retrieve the distribution data. * - * @param {string} basePath The base path for asset validation (game root). + * @param {string} launcherPath The root launcher directory. * @param {boolean} cached Optional. False if the distro should be freshly downloaded, else * a cached copy will be returned. * @returns {Promise.} A promise which resolves to the distribution data object. */ - static retrieveDistributionData(basePath, cached = true){ - return new Promise(function(fulfill, reject){ + static retrieveDistributionData(launcherPath, cached = true){ + return new Promise(function(resolve, reject){ if(!cached || distributionData == null){ // TODO Download file from upstream. - //const distroURL = 'http://mc.westeroscraft.com/WesterosCraftLauncher/westeroscraft.json' - // TODO Save file to path.join(basePath, 'westeroscraft.json') + const distroURL = 'http://mc.westeroscraft.com/WesterosCraftLauncher/westeroscraft.json' + const distroDest = path.join(launcherPath, 'westeroscraft.json') // TODO Fulfill with JSON.parse() + request(distroURL, (error, resp, body) => { + distributionData = JSON.parse(body) + fs.writeFile(distroDest, body, 'utf-8', (err) => { + if(!err){ + resolve(distributionData) + } else { + reject(err) + } + }) + }) // Workaround while file is not hosted. - fs.readFile(path.join(__dirname, '..', 'westeroscraft.json'), 'utf-8', (err, data) => { + /*fs.readFile(path.join(__dirname, '..', 'westeroscraft.json'), 'utf-8', (err, data) => { distributionData = JSON.parse(data) fulfill(distributionData) - }) + })*/ } else { - fulfill(distributionData) + resolve(distributionData) } }) } /** - * Statically retrieve the distribution data. + * Recieved a cached version of the distribution index. * - * @param {string} basePath The base path for asset validation (game root). + * @param {string} launcherPath The root launcher directory. * @param {boolean} cached Optional. False if the distro should be freshly downloaded, else * a cached copy will be returned. * @returns {Object} The distribution data object. */ - static retrieveDistributionDataSync(basePath, cached = true){ + static retrieveDistributionDataSync(launcherPath, cached = true){ if(!cached || distributionData == null){ - distributionData = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'westeroscraft.json'), 'utf-8')) + distributionData = JSON.parse(fs.readFileSync(path.join(launcherPath, 'westeroscraft.json'), 'utf-8')) } return distributionData } @@ -415,11 +427,11 @@ class AssetGuard extends EventEmitter { /** * Resolve the default selected server from the distribution index. * - * @param {string} basePath The base path for asset validation (game root). + * @param {string} launcherPath The root launcher directory. * @returns {Object} An object resolving to the default selected server. */ - static resolveSelectedServer(basePath){ - const distro = AssetGuard.retrieveDistributionDataSync(basePath) + static resolveSelectedServer(launcherPath){ + const distro = AssetGuard.retrieveDistributionDataSync(launcherPath) const servers = distro.servers for(let i=0; i} An empty promise to indicate the extraction has completed. */ static _extractPackXZ(filePaths, javaExecutable){ - return new Promise(function(fulfill, reject){ + return new Promise(function(resolve, reject){ let libPath if(isDev){ libPath = path.join(process.cwd(), 'libraries', 'java', 'PackXZExtract.jar') @@ -480,14 +492,14 @@ class AssetGuard extends EventEmitter { const filePath = filePaths.join(',') const child = child_process.spawn(javaExecutable, ['-jar', libPath, '-packxz', filePath]) child.stdout.on('data', (data) => { - //console.log('PackXZExtract:', data.toString('utf8')) + console.log('PackXZExtract:', data.toString('utf8')) }) child.stderr.on('data', (data) => { - //console.log('PackXZExtract:', data.toString('utf8')) + console.log('PackXZExtract:', data.toString('utf8')) }) child.on('close', (code, signal) => { - //console.log('PackXZExtract: Exited with code', code) - fulfill() + console.log('PackXZExtract: Exited with code', code) + resolve() }) }) } @@ -503,7 +515,7 @@ class AssetGuard extends EventEmitter { * @returns {Promise.} A promise which resolves to the contents of forge's version.json. */ static _finalizeForgeAsset(asset, basePath){ - return new Promise(function(fulfill, reject){ + return new Promise(function(resolve, reject){ fs.readFile(asset.to, (err, data) => { const zip = new AdmZip(data) const zipEntries = zip.getEntries() @@ -516,10 +528,10 @@ class AssetGuard extends EventEmitter { if(!fs.existsSync(versionFile)){ mkpath.sync(versionPath) fs.writeFileSync(path.join(versionPath, forgeVersion.id + '.json'), zipEntries[i].getData()) - fulfill(forgeVersion) + resolve(forgeVersion) } else { //Read the saved file to allow for user modifications. - fulfill(JSON.parse(fs.readFileSync(versionFile, 'utf-8'))) + resolve(JSON.parse(fs.readFileSync(versionFile, 'utf-8'))) } return } @@ -1269,7 +1281,7 @@ class AssetGuard extends EventEmitter { validateDistribution(serverpackid){ const self = this return new Promise(function(fulfill, reject){ - AssetGuard.retrieveDistributionData(self.basePath, false).then((value) => { + AssetGuard.retrieveDistributionData(self.launcherPath, false).then((value) => { /*const servers = value.servers let serv = null for(let i=0; i { + console.log('%c[Preloader]', 'color: #a02d2a; font-weight: bold', 'Loaded distribution index.') -// Resolve the selected server if its value has yet to be set. -if(ConfigManager.getSelectedServer() == null){ - console.log('Determining default selected server..') - ConfigManager.setSelectedServer(AssetGuard.resolveSelectedServer(ConfigManager.getGameDirectory()).id) - ConfigManager.save() -} + // Resolve the selected server if its value has yet to be set. + if(ConfigManager.getSelectedServer() == null){ + console.log('Determining default selected server..') + ConfigManager.setSelectedServer(AssetGuard.resolveSelectedServer(ConfigManager.getLauncherDirectory()).id) + ConfigManager.save() + } + + ipcRenderer.send('distributionIndexDone', data) + +}).catch(err => { + console.log('%c[Preloader]', 'color: #a02d2a; font-weight: bold', 'Failed to load distribution index.') + console.err(err) +}) // Clean up temp dir incase previous launches ended unexpectedly. rimraf(path.join(os.tmpdir(), ConfigManager.getTempNativeFolder()), (err) => { diff --git a/app/assets/js/scripts/landing.js b/app/assets/js/scripts/landing.js index e1d729f..00a3103 100644 --- a/app/assets/js/scripts/landing.js +++ b/app/assets/js/scripts/landing.js @@ -132,7 +132,8 @@ function updateSelectedServer(serverName){ } server_selection_button.innerHTML = '\u2022 ' + serverName } -updateSelectedServer(AssetGuard.getServerById(ConfigManager.getGameDirectory(), ConfigManager.getSelectedServer()).name) +// Real text is set in uibinder.js on distributionIndexDone. +updateSelectedServer('Loading..') server_selection_button.addEventListener('click', (e) => { e.target.blur() toggleServerSelection(true) @@ -198,7 +199,7 @@ const refreshServerStatus = async function(fade = false){ } refreshMojangStatuses() -refreshServerStatus() +// Server Status is refreshed in uibinder.js on distributionIndexDone. // Set refresh rate to once every 5 minutes. let mojangStatusListener = setInterval(() => refreshMojangStatuses(true), 300000) @@ -220,6 +221,7 @@ function asyncSystemScan(launchAfter = true){ // Fork a process to run validations. sysAEx = cp.fork(path.join(__dirname, 'assets', 'js', 'assetexec.js'), [ ConfigManager.getGameDirectory(), + ConfigManager.getLauncherDirectory(), ConfigManager.getJavaExecutable() ]) @@ -388,6 +390,7 @@ function dlAsync(login = true){ // Start AssetExec to run validations and downloads in a forked process. aEx = cp.fork(path.join(__dirname, 'assets', 'js', 'assetexec.js'), [ ConfigManager.getGameDirectory(), + ConfigManager.getLauncherDirectory(), ConfigManager.getJavaExecutable() ]) @@ -542,7 +545,7 @@ function dlAsync(login = true){ proc.stdout.on('data', gameStateChange) // Init Discord Hook - const distro = AssetGuard.retrieveDistributionDataSync(ConfigManager.getGameDirectory) + const distro = AssetGuard.retrieveDistributionDataSync(ConfigManager.getLauncherDirectory()) if(distro.discord != null && serv.discord != null){ DiscordWrapper.initRPC(distro.discord, serv.discord) hasRPC = true diff --git a/app/assets/js/scripts/overlay.js b/app/assets/js/scripts/overlay.js index 91c082f..a24c85c 100644 --- a/app/assets/js/scripts/overlay.js +++ b/app/assets/js/scripts/overlay.js @@ -160,7 +160,7 @@ function setServerListingHandlers(){ } function populateServerListings(){ - const distro = AssetGuard.retrieveDistributionDataSync(ConfigManager.getGameDirectory()) + const distro = AssetGuard.retrieveDistributionDataSync(ConfigManager.getLauncherDirectory()) const giaSel = ConfigManager.getSelectedServer() const servers = distro.servers let htmlString = `` diff --git a/app/assets/js/scripts/uibinder.js b/app/assets/js/scripts/uibinder.js index 3f620a5..9c5ee4c 100644 --- a/app/assets/js/scripts/uibinder.js +++ b/app/assets/js/scripts/uibinder.js @@ -6,14 +6,18 @@ const path = require('path') const ConfigManager = require(path.join(__dirname, 'assets', 'js', 'configmanager.js')) +let rscShouldLoad = false + // Synchronous Listener document.addEventListener('readystatechange', function(){ if (document.readyState === 'complete'){ - if(ConfigManager.isFirstLaunch()){ - $('#welcomeContainer').fadeIn(500) - } else { - $('#landingContainer').fadeIn(500) + if(rscShouldLoad){ + if(ConfigManager.isFirstLaunch()){ + $('#welcomeContainer').fadeIn(500) + } else { + $('#landingContainer').fadeIn(500) + } } } @@ -21,3 +25,18 @@ document.addEventListener('readystatechange', function(){ }*/ }, false) + +// Actions that must be performed after the distribution index is downloaded. +ipcRenderer.on('distributionIndexDone', (data) => { + updateSelectedServer(AssetGuard.getServerById(ConfigManager.getLauncherDirectory(), ConfigManager.getSelectedServer()).name) + refreshServerStatus() + if(document.readyState === 'complete'){ + if(ConfigManager.isFirstLaunch()){ + $('#welcomeContainer').fadeIn(500) + } else { + $('#landingContainer').fadeIn(500) + } + } else { + rscShouldLoad = true + } +}) diff --git a/index.js b/index.js index 5de007b..72c9649 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ const {app, BrowserWindow, ipcMain} = require('electron') -const autoUpdater = require("electron-updater").autoUpdater +const autoUpdater = require('electron-updater').autoUpdater const isDev = require('electron-is-dev') const path = require('path') const url = require('url') @@ -50,6 +50,10 @@ ipcMain.on('autoUpdateAction', (event, arg) => { break } }) +// Redirect distribution index event from preloader to renderer. +ipcMain.on('distributionIndexDone', (event, arg) => { + event.sender.send('distributionIndexDone', arg) +}) // Disable hardware acceleration. // https://electronjs.org/docs/tutorial/offscreen-rendering diff --git a/package-lock.json b/package-lock.json index 326c464..3a5bde6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -414,6 +414,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-4.2.0.tgz", "integrity": "sha512-cROCExnJOJvRD58HHcnrrgyRAoDHGZT0hKox0op7vTuuuRC/1JKMXvSR+Hxy7KWy/aEmKu0HfSqMd4znDEqQsA==", + "dev": true, "requires": { "bluebird-lst": "^1.0.5", "debug": "^3.1.0", @@ -425,6 +426,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -897,9 +899,9 @@ } }, "ejs": { - "version": "2.5.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", - "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" }, "ejs-electron": { "version": "2.0.1", @@ -1152,19 +1154,67 @@ } }, "electron-updater": { - "version": "2.21.8", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-2.21.8.tgz", - "integrity": "sha512-mYZu3m0i5okXtxh6uz1WbEiz3c1vVsITFPfrhctqaGFSaQbI/7YqzoY12QJX6KVO4Iu1hUMijr+wJlmVTlLhZw==", + "version": "2.21.10", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-2.21.10.tgz", + "integrity": "sha512-9QNUGHqwddLFIsFiAoFSxu0NdmvB1VGKrH2dGCn/b8nDwfWwHUyCnetMsnwcVSMjHA2Lz4tGfRSDSN3PtlVDKA==", "requires": { "bluebird-lst": "^1.0.5", - "builder-util-runtime": "~4.2.0", + "builder-util-runtime": "~4.2.1", "electron-is-dev": "^0.3.0", - "fs-extra-p": "^4.5.2", + "fs-extra-p": "^4.6.0", "js-yaml": "^3.11.0", "lazy-val": "^1.0.3", "lodash.isequal": "^4.5.0", "semver": "^5.5.0", - "source-map-support": "^0.5.4" + "source-map-support": "^0.5.5" + }, + "dependencies": { + "builder-util-runtime": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-4.2.1.tgz", + "integrity": "sha512-6Ufp6ExT40RDYNXQgD4xG0fgtpUHyc8XIld6lptKr0re1DNnUrQP4sSV/lJOajpzyercMP/YIzO60/mNuAFiWg==", + "requires": { + "bluebird-lst": "^1.0.5", + "debug": "^3.1.0", + "fs-extra-p": "^4.6.0", + "sax": "^1.2.4" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "fs-extra": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.0.tgz", + "integrity": "sha512-lk2cUCo8QzbiEWEbt7Cw3m27WMiRG321xsssbcIpfMhpRjrlC08WBOVQqj1/nQYYNnPtyIhP1oqLO3QwT2tPCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-extra-p": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-4.6.0.tgz", + "integrity": "sha512-nSVqB5UfWZQdU6pzBwcFh+7lJpBynnTsVtNJTBhAnAppUQRut0W7WeM271iS0TqQ9FoCqDXqyL0+h+h8DQUCpg==", + "requires": { + "bluebird-lst": "^1.0.5", + "fs-extra": "^6.0.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + } } }, "end-of-stream": { @@ -1327,6 +1377,7 @@ "version": "4.5.2", "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-4.5.2.tgz", "integrity": "sha512-ZYqFpBdy9w7PsK+vB30j+TnHOyWHm/CJbUq1qqoE8tb71m6qgk5Wa7gp3MYQdlGFxb9vfznF+yD4jcl8l+y91A==", + "dev": true, "requires": { "bluebird-lst": "^1.0.5", "fs-extra": "^5.0.0" @@ -1336,6 +1387,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -1346,6 +1398,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, "requires": { "graceful-fs": "^4.1.6" } diff --git a/package.json b/package.json index 1e09eec..d66b3a0 100644 --- a/package.json +++ b/package.json @@ -31,10 +31,10 @@ "adm-zip": "^0.4.9", "async": "^2.6.0", "discord-rpc": "^3.0.0-beta.10", - "ejs": "^2.5.9", + "ejs": "^2.6.1", "ejs-electron": "^2.0.1", "electron-is-dev": "^0.3.0", - "electron-updater": "^2.21.8", + "electron-updater": "^2.21.10", "jquery": "^3.3.1", "mkdirp": "^0.5.1", "request": "^2.85.0", @@ -45,7 +45,7 @@ }, "devDependencies": { "electron": "^2.0.0", - "electron-builder": "^20.11.0" + "electron-builder": "^20.11.1" }, "build": { "appId": "westeroscraftlauncher",