Эх сурвалжийг харах

Distribution data is now pulled from our servers.

Daniel Scalzi 7 жил өмнө
parent
commit
0c1ebd0ce0

+ 1 - 1
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.

+ 42 - 30
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.<Object>} 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<servers.length; i++){
             if(servers[i].default_selected){
@@ -435,13 +447,13 @@ class AssetGuard extends EventEmitter {
      * Returns null if the ID could not be found or the distro index has
      * not yet been loaded.
      * 
-     * @param {string} basePath The base path for asset validation (game root).
+     * @param {string} launcherPath The root launcher directory.
      * @param {string} serverID The id of the server to retrieve.
      * @returns {Object} The server object whose id matches the parameter.
      */
-    static getServerById(basePath, serverID){
+    static getServerById(launcherPath, serverID){
         if(distributionData == null){
-            AssetGuard.retrieveDistributionDataSync(basePath, false)
+            AssetGuard.retrieveDistributionDataSync(launcherPath, false)
         }
         const servers = distributionData.servers
         let serv = null
@@ -465,7 +477,7 @@ class AssetGuard extends EventEmitter {
      * @returns {Promise.<void>} 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.<Object>} 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<servers.length; i++){
@@ -1278,7 +1290,7 @@ class AssetGuard extends EventEmitter {
                         break
                     }
                 }*/
-                const serv = AssetGuard.getServerById(self.basePath, serverpackid)
+                const serv = AssetGuard.getServerById(self.launcherPath, serverpackid)
 
                 if(serv == null) {
                     console.error('Invalid server pack id:', serverpackid)
@@ -1367,7 +1379,7 @@ class AssetGuard extends EventEmitter {
     loadForgeData(serverpack){
         const self = this
         return new Promise(async function(fulfill, reject){
-            let distro = AssetGuard.retrieveDistributionDataSync(self.basePath)
+            let distro = AssetGuard.retrieveDistributionDataSync(self.launcherPath)
             
             const servers = distro.servers
             let serv = null

+ 16 - 7
app/assets/js/preloader.js

@@ -1,5 +1,6 @@
 const {AssetGuard} = require('./assetguard.js')
 const ConfigManager = require('./configmanager.js')
+const {ipcRenderer} = require('electron')
 const os = require('os')
 const path = require('path')
 const rimraf = require('rimraf')
@@ -10,14 +11,22 @@ console.log('%c[Preloader]', 'color: #a02d2a; font-weight: bold', 'Loading..')
 ConfigManager.load()
 
 // Ensure Distribution is downloaded and cached.
-AssetGuard.retrieveDistributionDataSync(ConfigManager.getGameDirectory(), false)
+AssetGuard.retrieveDistributionData(ConfigManager.getLauncherDirectory(), false).then((data) => {
+    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) => {

+ 6 - 3
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

+ 1 - 1
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 = ``

+ 23 - 4
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
+    }
+})

+ 5 - 1
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

+ 62 - 9
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"
           }

+ 3 - 3
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",