From 0dde4bce427b6054b32596b5db61a32a1cd29517 Mon Sep 17 00:00:00 2001
From: Daniel Scalzi <d_scalzi@yahoo.com>
Date: Sat, 2 Dec 2017 22:41:47 -0500
Subject: [PATCH] Changes to prevent cyclic dependencies.

---
 app/assets/js/actionbinder.js   |  24 +++----
 app/assets/js/assetguard.js     | 122 ++++++++++++++++----------------
 app/assets/js/constants.js      |  13 ----
 app/assets/js/discordwrapper.js |   2 +-
 app/assets/js/enumerator.js     |   9 +++
 app/assets/js/modresolver.js    |  17 -----
 app/assets/js/preloader.js      |  18 ++++-
 app/assets/js/processbuilder.js |   2 +-
 app/assets/js/uicore.js         |   4 +-
 app/assets/westeroscraft.json   |   2 +-
 10 files changed, 103 insertions(+), 110 deletions(-)
 delete mode 100644 app/assets/js/constants.js
 create mode 100644 app/assets/js/enumerator.js
 delete mode 100644 app/assets/js/modresolver.js

diff --git a/app/assets/js/actionbinder.js b/app/assets/js/actionbinder.js
index 4b50a80d..0272a844 100644
--- a/app/assets/js/actionbinder.js
+++ b/app/assets/js/actionbinder.js
@@ -2,7 +2,7 @@ const mojang = require('mojang')
 const path = require('path')
 const {AssetGuard} = require(path.join(__dirname, 'assets', 'js', 'assetguard.js'))
 const ProcessBuilder = require(path.join(__dirname, 'assets', 'js', 'processbuilder.js'))
-const {GAME_DIRECTORY, DEFAULT_CONFIG} = require(path.join(__dirname, 'assets', 'js', 'constants.js'))
+const {GAME_DIRECTORY, DEFAULT_CONFIG} = require(path.join(__dirname, 'assets', 'js', 'enumerator.js')).enum
 
 document.addEventListener('readystatechange', function(){
     if (document.readyState === 'interactive'){
@@ -12,15 +12,10 @@ document.addEventListener('readystatechange', function(){
             console.log('Launching game..')
             testdownloads()
         })
-        
-        if(DEFAULT_CONFIG.getSelectedServer() == null){
-            console.log('Determining default selected server..')
-            DEFAULT_CONFIG.setSelectedServer(AssetGuard.resolveSelectedServer())
-        }
 
         // TODO convert this to dropdown menu.
         // Bind selected server
-        document.getElementById('server_selection').innerHTML = '\u2022 ' + AssetGuard.getServerById(DEFAULT_CONFIG.getSelectedServer()).name
+        document.getElementById('server_selection').innerHTML = '\u2022 ' + AssetGuard.getServerById(GAME_DIRECTORY, DEFAULT_CONFIG.getSelectedServer()).name
 
     }
 }, false)
@@ -40,33 +35,34 @@ testdownloads = async function(){
     details.style.display = 'flex'
     content.style.display = 'none'
 
-    tracker = new AssetGuard()
+    console.log(DEFAULT_CONFIG.getJavaExecutable())
+    tracker = new AssetGuard(GAME_DIRECTORY, DEFAULT_CONFIG.getJavaExecutable())
 
     det_text.innerHTML = 'Loading server information..'
-    const serv = await tracker.validateDistribution(DEFAULT_CONFIG.getSelectedServer(), GAME_DIRECTORY)
+    const serv = await tracker.validateDistribution(DEFAULT_CONFIG.getSelectedServer())
     progress.setAttribute('value', 20)
     progress_text.innerHTML = '20%'
     console.log('forge stuff done')
 
     det_text.innerHTML = 'Loading version information..'
-    const versionData = await tracker.loadVersionData(serv.mc_version, GAME_DIRECTORY)
+    const versionData = await tracker.loadVersionData(serv.mc_version)
     progress.setAttribute('value', 40)
     progress_text.innerHTML = '40%'
 
     det_text.innerHTML = 'Validating asset integrity..'
-    await tracker.validateAssets(versionData, GAME_DIRECTORY)
+    await tracker.validateAssets(versionData)
     progress.setAttribute('value', 60)
     progress_text.innerHTML = '60%'
     console.log('assets done')
 
     det_text.innerHTML = 'Validating library integrity..'
-    await tracker.validateLibraries(versionData, GAME_DIRECTORY)
+    await tracker.validateLibraries(versionData)
     progress.setAttribute('value', 80)
     progress_text.innerHTML = '80%'
     console.log('libs done')
 
     det_text.innerHTML = 'Validating miscellaneous file integrity..'
-    await tracker.validateMiscellaneous(versionData, GAME_DIRECTORY)
+    await tracker.validateMiscellaneous(versionData)
     progress.setAttribute('value', 100)
     progress_text.innerHTML = '100%'
     console.log('files done')
@@ -81,7 +77,7 @@ testdownloads = async function(){
     tracker.on('dlcomplete', async function(){
 
         det_text.innerHTML = 'Preparing to launch..'
-        const forgeData = await tracker.loadForgeData(serv.id, GAME_DIRECTORY)
+        const forgeData = await tracker.loadForgeData(serv.id)
         const authUser = await mojang.auth('EMAIL', 'PASS', DEFAULT_CONFIG.getClientToken(), {
             name: 'Minecraft',
             version: 1
diff --git a/app/assets/js/assetguard.js b/app/assets/js/assetguard.js
index 0d41df83..ad33b93e 100644
--- a/app/assets/js/assetguard.js
+++ b/app/assets/js/assetguard.js
@@ -26,7 +26,6 @@ const AdmZip = require('adm-zip')
 const async = require('async')
 const child_process = require('child_process')
 const crypto = require('crypto')
-const {DEFAULT_CONFIG, DISTRO_DIRECTORY} = require('./constants')
 const EventEmitter = require('events')
 const fs = require('fs')
 const mkpath = require('mkdirp');
@@ -165,11 +164,15 @@ let distributionData = null
 class AssetGuard extends EventEmitter {
 
     /**
-     * AssetGuard class should only ever have one instance which is defined in
-     * this module. On creation the object's properties are never-null default
+     * Create an instance of AssetGuard.
+     * On creation the object's properties are never-null default
      * values. Each identifier is resolved to an empty DLTracker.
+     * 
+     * @param {String} basePath - base path for asset validation (game root).
+     * @param {String} javaexec - path to a java executable which will be used
+     * to finalize installation.
      */
-    constructor(){
+    constructor(basePath, javaexec){
         super()
         this.totaldlsize = 0;
         this.progress = 0;
@@ -177,6 +180,8 @@ class AssetGuard extends EventEmitter {
         this.libraries = new DLTracker([], 0)
         this.files = new DLTracker([], 0)
         this.forge = new DLTracker([], 0)
+        this.basePath = basePath
+        this.javaexec = javaexec
     }
 
     // Static Utility Functions
@@ -277,16 +282,17 @@ class AssetGuard extends EventEmitter {
     /**
      * Statically retrieve the distribution data.
      * 
+     * @param {String} basePath - base path for asset validation (game root).
      * @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(cached = true){
+    static retrieveDistributionData(basePath, cached = true){
         return new Promise(function(fulfill, reject){
             if(!cached || distributionData == null){
                 // TODO Download file from upstream.
                 //const distroURL = 'http://mc.westeroscraft.com/WesterosCraftLauncher/westeroscraft.json'
-                // TODO Save file to DISTRO_DIRECTORY
+                // TODO Save file to path.join(basePath, 'westeroscraft.json')
                 // TODO Fulfill with JSON.parse()
 
                 // Workaround while file is not hosted.
@@ -303,11 +309,12 @@ class AssetGuard extends EventEmitter {
     /**
      * Statically retrieve the distribution data.
      * 
+     * @param {String} basePath - base path for asset validation (game root).
      * @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(cached = true){
+    static retrieveDistributionDataSync(basePath, cached = true){
         if(!cached || distributionData == null){
             distributionData = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'westeroscraft.json'), 'utf-8'))
         }
@@ -317,10 +324,11 @@ class AssetGuard extends EventEmitter {
     /**
      * Resolve the default selected server from the distribution index.
      * 
+     * @param {String} basePath - base path for asset validation (game root).
      * @returns {Object} - An object resolving to the default selected server.
      */
-    static resolveSelectedServer(){
-        const distro = AssetGuard.retrieveDistributionDataSync()
+    static resolveSelectedServer(basePath){
+        const distro = AssetGuard.retrieveDistributionDataSync(basePath)
         const servers = distro.servers
         for(let i=0; i<servers.length; i++){
             if(servers[i].default_selected){
@@ -336,12 +344,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 - base path for asset validation (game root).
      * @param {String} serverID - The id of the server to retrieve.
      * @returns {Object} - The server object whose id matches the parameter.
      */
-    static getServerById(serverID){
+    static getServerById(basePath, serverID){
         if(distributionData == null){
-            AssetGuard.retrieveDistributionDataSync(false)
+            AssetGuard.retrieveDistributionDataSync(basePath, false)
         }
         const servers = distributionData.servers
         let serv = null
@@ -424,11 +433,11 @@ class AssetGuard extends EventEmitter {
      * @param {Array.<String>} filePaths - The paths of the files to be extracted and unpacked.
      * @returns {Promise.<Void>} - An empty promise to indicate the extraction has completed.
      */
-    static _extractPackXZ(filePaths){
+    static _extractPackXZ(filePaths, javaExecutable){
         return new Promise(function(fulfill, reject){
             const libPath = path.join(__dirname, '..', 'libraries', 'java', 'PackXZExtract.jar')
             const filePath = filePaths.join(',')
-            const child = child_process.spawn(DEFAULT_CONFIG.getJavaExecutable(), ['-jar', libPath, '-packxz', filePath])
+            const child = child_process.spawn(javaExecutable, ['-jar', libPath, '-packxz', filePath])
             child.stdout.on('data', (data) => {
                 //console.log('PackXZExtract:', data.toString('utf8'))
             })
@@ -449,7 +458,7 @@ class AssetGuard extends EventEmitter {
      * in a promise.
      * 
      * @param {Asset} asset - The Asset object representing Forge.
-     * @param {String} basePath
+     * @param {String} basePath - Base path for asset validation (game root).
      * @returns {Promise.<Object>} - A promise which resolves to the contents of forge's version.json.
      */
     static _finalizeForgeAsset(asset, basePath){
@@ -557,15 +566,15 @@ class AssetGuard extends EventEmitter {
      * Loads the version data for a given minecraft version.
      * 
      * @param {String} version - the game version for which to load the index data.
-     * @param {String} basePath - the absolute file path which will be prepended to the given relative paths.
      * @param {Boolean} force - optional. If true, the version index will be downloaded even if it exists locally. Defaults to false.
      * @returns {Promise.<Object>} - Promise which resolves to the version data object.
      */
-    loadVersionData(version, basePath, force = false){
+    loadVersionData(version, force = false){
+        const self = this
         return new Promise(function(fulfill, reject){
             const name = version + '.json'
             const url = 'https://s3.amazonaws.com/Minecraft.Download/versions/' + version + '/' + name
-            const versionPath = path.join(basePath, 'versions', version)
+            const versionPath = path.join(self.basePath, 'versions', version)
             const versionFile = path.join(versionPath, name)
             if(!fs.existsSync(versionFile) || force){
                 //This download will never be tracked as it's essential and trivial.
@@ -590,14 +599,13 @@ class AssetGuard extends EventEmitter {
      * If not, it will be added to the download queue for the 'assets' identifier.
      * 
      * @param {Object} versionData - the version data for the assets.
-     * @param {String} basePath - the absolute file path which will be prepended to the given relative paths.
      * @param {Boolean} force - optional. If true, the asset index will be downloaded even if it exists locally. Defaults to false.
      * @returns {Promise.<Void>} - An empty promise to indicate the async processing has completed.
      */
-    validateAssets(versionData, basePath, force = false){
+    validateAssets(versionData, force = false){
         const self = this
         return new Promise(function(fulfill, reject){
-            self._assetChainIndexData(versionData, basePath, force).then(() => {
+            self._assetChainIndexData(versionData, force).then(() => {
                 fulfill()
             })
         })
@@ -608,17 +616,16 @@ class AssetGuard extends EventEmitter {
      * Private function used to chain the asset validation process. This function retrieves
      * the index data.
      * @param {Object} versionData
-     * @param {String} basePath
      * @param {Boolean} force
      * @returns {Promise.<Void>} - An empty promise to indicate the async processing has completed.
      */
-    _assetChainIndexData(versionData, basePath, force = false){
+    _assetChainIndexData(versionData, force = false){
         const self = this
         return new Promise(function(fulfill, reject){
             //Asset index constants.
             const assetIndex = versionData.assetIndex
             const name = assetIndex.id + '.json'
-            const indexPath = path.join(basePath, 'assets', 'indexes')
+            const indexPath = path.join(self.basePath, 'assets', 'indexes')
             const assetIndexLoc = path.join(indexPath, name)
 
             let data = null
@@ -628,13 +635,13 @@ class AssetGuard extends EventEmitter {
                 const stream = request(assetIndex.url).pipe(fs.createWriteStream(assetIndexLoc))
                 stream.on('finish', function() {
                     data = JSON.parse(fs.readFileSync(assetIndexLoc, 'utf-8'))
-                    self._assetChainValidateAssets(versionData, basePath, data).then(() => {
+                    self._assetChainValidateAssets(versionData, data).then(() => {
                         fulfill()
                     })
                 })
             } else {
                 data = JSON.parse(fs.readFileSync(assetIndexLoc, 'utf-8'))
-                self._assetChainValidateAssets(versionData, basePath, data).then(() => {
+                self._assetChainValidateAssets(versionData, data).then(() => {
                     fulfill()
                 })
             }
@@ -645,17 +652,16 @@ class AssetGuard extends EventEmitter {
      * Private function used to chain the asset validation process. This function processes
      * the assets and enqueues missing or invalid files.
      * @param {Object} versionData
-     * @param {String} basePath
      * @param {Boolean} force
      * @returns {Promise.<Void>} - An empty promise to indicate the async processing has completed.
      */
-    _assetChainValidateAssets(versionData, basePath, indexData){
+    _assetChainValidateAssets(versionData, indexData){
         const self = this
         return new Promise(function(fulfill, reject){
 
             //Asset constants
             const resourceURL = 'http://resources.download.minecraft.net/'
-            const localPath = path.join(basePath, 'assets')
+            const localPath = path.join(self.basePath, 'assets')
             const indexPath = path.join(localPath, 'indexes')
             const objectPath = path.join(localPath, 'objects')
 
@@ -686,15 +692,14 @@ class AssetGuard extends EventEmitter {
      * queue for the 'libraries' identifier.
      * 
      * @param {Object} versionData - the version data for the assets.
-     * @param {String} basePath - the absolute file path which will be prepended to the given relative paths.
      * @returns {Promise.<Void>} - An empty promise to indicate the async processing has completed.
      */
-    validateLibraries(versionData, basePath){
+    validateLibraries(versionData){
         const self = this
         return new Promise(function(fulfill, reject){
 
             const libArr = versionData.libraries
-            const libPath = path.join(basePath, 'libraries')
+            const libPath = path.join(self.basePath, 'libraries')
 
             const libDlQueue = []
             let dlSize = 0
@@ -722,14 +727,13 @@ class AssetGuard extends EventEmitter {
      * the 'files' identifier.
      * 
      * @param {Object} versionData - the version data for the assets.
-     * @param {String} basePath - the absolute file path which will be prepended to the given relative paths.
      * @returns {Promise.<Void>} - An empty promise to indicate the async processing has completed.
      */
-    validateMiscellaneous(versionData, basePath){
+    validateMiscellaneous(versionData){
         const self = this
         return new Promise(async function(fulfill, reject){
-            await self.validateClient(versionData, basePath)
-            await self.validateLogConfig(versionData, basePath)
+            await self.validateClient(versionData)
+            await self.validateLogConfig(versionData)
             fulfill()
         })
     }
@@ -738,16 +742,15 @@ class AssetGuard extends EventEmitter {
      * Validate client file - artifact renamed from client.jar to '{version}'.jar.
      * 
      * @param {Object} versionData - the version data for the assets.
-     * @param {String} basePath - the absolute file path which will be prepended to the given relative paths.
      * @param {Boolean} force - optional. If true, the asset index will be downloaded even if it exists locally. Defaults to false.
      * @returns {Promise.<Void>} - An empty promise to indicate the async processing has completed.
      */
-    validateClient(versionData, basePath, force = false){
+    validateClient(versionData, force = false){
         const self = this
         return new Promise(function(fulfill, reject){
             const clientData = versionData.downloads.client
             const version = versionData.id
-            const targetPath = path.join(basePath, 'versions', version)
+            const targetPath = path.join(self.basePath, 'versions', version)
             const targetFile = version + '.jar'
 
             let client = new Asset(version + ' client', clientData.sha1, clientData.size, clientData.url, path.join(targetPath, targetFile))
@@ -766,16 +769,15 @@ class AssetGuard extends EventEmitter {
      * Validate log config.
      * 
      * @param {Object} versionData - the version data for the assets.
-     * @param {String} basePath - the absolute file path which will be prepended to the given relative paths.
      * @param {Boolean} force - optional. If true, the asset index will be downloaded even if it exists locally. Defaults to false.
      * @returns {Promise.<Void>} - An empty promise to indicate the async processing has completed.
      */
-    validateLogConfig(versionData, basePath){
+    validateLogConfig(versionData){
         const self = this
         return new Promise(function(fulfill, reject){
             const client = versionData.logging.client
             const file = client.file
-            const targetPath = path.join(basePath, 'assets', 'log_configs')
+            const targetPath = path.join(self.basePath, 'assets', 'log_configs')
 
             let logConfig = new Asset(file.id, file.sha1, file.size, file.url, path.join(targetPath, file.id))
 
@@ -793,13 +795,12 @@ class AssetGuard extends EventEmitter {
      * Validate the distribution.
      * 
      * @param {String} serverpackid - The id of the server to validate.
-     * @param {String} basePath - the absolute file path which will be prepended to the given relative paths.
      * @returns {Promise.<Object>} - A promise which resolves to the server distribution object.
      */
-    validateDistribution(serverpackid, basePath){
+    validateDistribution(serverpackid){
         const self = this
         return new Promise(function(fulfill, reject){
-            AssetGuard.retrieveDistributionData(false).then((value) => {
+            AssetGuard.retrieveDistributionData(self.basePath, false).then((value) => {
                 /*const servers = value.servers
                 let serv = null
                 for(let i=0; i<servers.length; i++){
@@ -808,17 +809,17 @@ class AssetGuard extends EventEmitter {
                         break
                     }
                 }*/
-                const serv = AssetGuard.getServerById(serverpackid)
+                const serv = AssetGuard.getServerById(self.basePath, serverpackid)
 
-                self.forge = self._parseDistroModules(serv.modules, basePath, serv.mc_version)
+                self.forge = self._parseDistroModules(serv.modules, serv.mc_version)
                 //Correct our workaround here.
                 let decompressqueue = self.forge.callback
                 self.forge.callback = function(asset){
                     if(asset.to.toLowerCase().endsWith('.pack.xz')){
-                        AssetGuard._extractPackXZ([asset.to])
+                        AssetGuard._extractPackXZ([asset.to], self.javaexec)
                     }
                     if(asset.type === 'forge-hosted' || asset.type === 'forge'){
-                        AssetGuard._finalizeForgeAsset(asset, basePath)
+                        AssetGuard._finalizeForgeAsset(asset, self.basePath)
                     }
                 }
                 fulfill(serv)
@@ -839,7 +840,7 @@ class AssetGuard extends EventEmitter {
         })
     }*/
 
-    _parseDistroModules(modules, basePath, version){
+    _parseDistroModules(modules, version){
         let alist = []
         let asize = 0;
         //This may be removed soon, considering the most efficient way to extract.
@@ -853,19 +854,19 @@ class AssetGuard extends EventEmitter {
                 case 'forge-hosted':
                 case 'forge':
                 case 'library':
-                    obPath = path.join(basePath, 'libraries', obPath)
+                    obPath = path.join(this.basePath, 'libraries', obPath)
                     break
                 case 'forgemod':
-                    //obPath = path.join(basePath, 'mods', obPath)
-                    obPath = path.join(basePath, 'modstore', obPath)
+                    //obPath = path.join(this.basePath, 'mods', obPath)
+                    obPath = path.join(this.basePath, 'modstore', obPath)
                     break
                 case 'litemod':
-                    //obPath = path.join(basePath, 'mods', version, obPath)
-                    obPath = path.join(basePath, 'modstore', obPath)
+                    //obPath = path.join(this.basePath, 'mods', version, obPath)
+                    obPath = path.join(this.basePath, 'modstore', obPath)
                     break
                 case 'file':
                 default: 
-                    obPath = path.join(basePath, obPath)
+                    obPath = path.join(this.basePath, obPath)
             }
             let artifact = new DistroModule(ob.id, obArtifact.MD5, obArtifact.size, obArtifact.url, obPath, obType)
             const validationPath = obPath.toLowerCase().endsWith('.pack.xz') ? obPath.substring(0, obPath.toLowerCase().lastIndexOf('.pack.xz')) : obPath
@@ -876,7 +877,7 @@ class AssetGuard extends EventEmitter {
             }
             //Recursively process the submodules then combine the results.
             if(ob.sub_modules != null){
-                let dltrack = this._parseDistroModules(ob.sub_modules, basePath, version)
+                let dltrack = this._parseDistroModules(ob.sub_modules, version)
                 asize += dltrack.dlsize*1
                 alist = alist.concat(dltrack.dlqueue)
                 decompressqueue = decompressqueue.concat(dltrack.callback)
@@ -891,13 +892,12 @@ class AssetGuard extends EventEmitter {
      * Loads Forge's version.json data into memory for the specified server id.
      * 
      * @param {String} serverpack - The id of the server to load Forge data for.
-     * @param {String} basePath
      * @returns {Promise.<Object>} - A promise which resolves to Forge's version.json data.
      */
-    loadForgeData(serverpack, basePath){
+    loadForgeData(serverpack){
         const self = this
         return new Promise(async function(fulfill, reject){
-            let distro = AssetGuard.retrieveDistributionDataSync()
+            let distro = AssetGuard.retrieveDistributionDataSync(self.basePath)
             
             const servers = distro.servers
             let serv = null
@@ -913,9 +913,9 @@ class AssetGuard extends EventEmitter {
                 const ob = modules[i]
                 if(ob.type === 'forge-hosted' || ob.type === 'forge'){
                     let obArtifact = ob.artifact
-                    let obPath = obArtifact.path == null ? path.join(basePath, 'libraries', AssetGuard._resolvePath(ob.id, obArtifact.extension)) : obArtifact.path
+                    let obPath = obArtifact.path == null ? path.join(self.basePath, 'libraries', AssetGuard._resolvePath(ob.id, obArtifact.extension)) : obArtifact.path
                     let asset = new DistroModule(ob.id, obArtifact.MD5, obArtifact.size, obArtifact.url, obPath, ob.type)
-                    let forgeData = await AssetGuard._finalizeForgeAsset(asset, basePath)
+                    let forgeData = await AssetGuard._finalizeForgeAsset(asset, self.basePath)
                     fulfill(forgeData)
                     return
                 }
diff --git a/app/assets/js/constants.js b/app/assets/js/constants.js
deleted file mode 100644
index 9b4d33d5..00000000
--- a/app/assets/js/constants.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const path = require('path')
-const ConfigManager = require('./configmanager')
-
-//TODO: Resolve game directory based on windows, linux, or mac..
-const GAME_DIRECTORY = path.join(__dirname, '..', '..', '..', 'target', 'test', 'mcfiles')
-const DISTRO_DIRECTORY = path.join(GAME_DIRECTORY, 'westeroscraft.json')
-const DEFAULT_CONFIG = new ConfigManager(path.join(GAME_DIRECTORY, 'config.json'))
-
-module.exports = {
-    GAME_DIRECTORY,
-    DISTRO_DIRECTORY,
-    DEFAULT_CONFIG
-}
\ No newline at end of file
diff --git a/app/assets/js/discordwrapper.js b/app/assets/js/discordwrapper.js
index 960d6d45..579e05c2 100644
--- a/app/assets/js/discordwrapper.js
+++ b/app/assets/js/discordwrapper.js
@@ -1,6 +1,6 @@
 // Work in progress
 const Client = require('discord-rpc')
-const {DEFAULT_CONFIG} = require('./constants')
+const {DEFAULT_CONFIG} = require('./enumerator.js').enum
 
 let rpc
 
diff --git a/app/assets/js/enumerator.js b/app/assets/js/enumerator.js
new file mode 100644
index 00000000..64b9d8f7
--- /dev/null
+++ b/app/assets/js/enumerator.js
@@ -0,0 +1,9 @@
+/**
+ * Module which stores constant values. These constants are mutable, however
+ * generally should not be changed unless a value is being added. Values are
+ * typically initialized during the app's preloader.
+ * @module enumerator
+ */
+exports.enum = {
+
+}
\ No newline at end of file
diff --git a/app/assets/js/modresolver.js b/app/assets/js/modresolver.js
deleted file mode 100644
index 22426cf6..00000000
--- a/app/assets/js/modresolver.js
+++ /dev/null
@@ -1,17 +0,0 @@
-function _shouldInclude(mdle){
-    return mdle.required == null || mdle.required.value == null || mdle.required.value === true || (mdle.required.value === false && mdle.required.def === true)
-}
-
-function resolveForgeFromDistro(moduleArr){
-    const mods = []
-
-    for(let i=0; i<moduleArr.length; ++i){
-        if(moduleArr[i].type != null && moduleArr[i].type === 'forgemod'){
-            if(_shouldInclude(moduleArr[i])){
-                mods.push(moduleArr[i])
-            }
-        }
-    }
-
-    return mods
-}
\ No newline at end of file
diff --git a/app/assets/js/preloader.js b/app/assets/js/preloader.js
index e7cc7272..77557f2e 100644
--- a/app/assets/js/preloader.js
+++ b/app/assets/js/preloader.js
@@ -1,6 +1,22 @@
+// Note: The following modules CANNOT require enumerator.js
 const {AssetGuard} = require('./assetguard.js')
+const ConfigManager = require('./configmanager.js')
+const constants = require('./enumerator.js').enum
+const path = require('path')
 
 console.log('Preloading')
 
 // Ensure Distribution is downloaded and cached.
-AssetGuard.retrieveDistributionDataSync(false)
\ No newline at end of file
+AssetGuard.retrieveDistributionDataSync(false)
+
+// TODO: Resolve game directory based on windows, linux, or mac..
+constants.GAME_DIRECTORY = path.join(__dirname, '..', '..', '..', 'target', 'test', 'mcfiles')
+constants.DISTRO_DIRECTORY = path.join(constants.GAME_DIRECTORY, 'westeroscraft.json')
+
+// Complete config setup
+const conf = new ConfigManager(path.join(constants.GAME_DIRECTORY, 'config.json'))
+if(conf.getSelectedServer() == null){
+    console.log('Determining default selected server..')
+    conf.setSelectedServer(AssetGuard.resolveSelectedServer(constants.GAME_DIRECTORY))
+}
+constants.DEFAULT_CONFIG = conf
\ No newline at end of file
diff --git a/app/assets/js/processbuilder.js b/app/assets/js/processbuilder.js
index 9d0ccfb6..6ea4f2a2 100644
--- a/app/assets/js/processbuilder.js
+++ b/app/assets/js/processbuilder.js
@@ -8,7 +8,7 @@
 const AdmZip = require('adm-zip')
 const {AssetGuard, Library} = require('./assetguard.js')
 const child_process = require('child_process')
-const {DEFAULT_CONFIG} = require('./constants')
+const {DEFAULT_CONFIG} = require('./enumerator.js').enum
 const fs = require('fs')
 const mkpath = require('mkdirp')
 const path = require('path')
diff --git a/app/assets/js/uicore.js b/app/assets/js/uicore.js
index 140b50fc..ed2cb240 100644
--- a/app/assets/js/uicore.js
+++ b/app/assets/js/uicore.js
@@ -1,6 +1,8 @@
 /**
  * Core UI functions are initialized in this file. This prevents
- * unexpected errors from breaking the core features.
+ * unexpected errors from breaking the core features. Specifically,
+ * actions in this file should not require the usage of any internal
+ * modules, excluding dependencies.
  */
 const $ = require('jquery');
 const {remote, shell} = require('electron')
diff --git a/app/assets/westeroscraft.json b/app/assets/westeroscraft.json
index 140f6611..8fd950e8 100644
--- a/app/assets/westeroscraft.json
+++ b/app/assets/westeroscraft.json
@@ -3,7 +3,7 @@
     "servers": [
         {
             "id": "WesterosCraft-1.11.2",
-            "name": "WesterosCraft Production Client",
+            "name": "WesterosCraft Production Server",
             "news_feed": "http://www.westeroscraft.com/api/rss.php?preset_id=12700544",
             "icon_url": "http://mc.westeroscraft.com/WesterosCraftLauncher/files/server-prod.png",
             "revision": "0.0.1",