diff --git a/.eslintrc.json b/.eslintrc.json index 006dfc0..e0521a6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -52,7 +52,7 @@ }, "overrides": [ { - "files": [ "app/assets/js/scripts/*.js" ], + "files": [ "src/scripts/*.js" ], "rules": { "no-unused-vars": [ 0 diff --git a/.gitignore b/.gitignore index 30ce193..27289ff 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ /.vscode/ /target/ /logs/ -/dist/ \ No newline at end of file +/dist/ +/out/ \ No newline at end of file diff --git a/app/assets/js/configmanager.js b/app/assets/js/configmanager.js deleted file mode 100644 index f34cc25..0000000 --- a/app/assets/js/configmanager.js +++ /dev/null @@ -1,688 +0,0 @@ -const fs = require('fs-extra') -const os = require('os') -const path = require('path') - -const logger = require('./loggerutil')('%c[ConfigManager]', 'color: #a02d2a; font-weight: bold') - -const sysRoot = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME) -// TODO change -const dataPath = path.join(sysRoot, '.westeroscraft') - -// Forked processes do not have access to electron, so we have this workaround. -const launcherDir = process.env.CONFIG_DIRECT_PATH || require('electron').remote.app.getPath('userData') - -/** - * Retrieve the absolute path of the launcher directory. - * - * @returns {string} The absolute path of the launcher directory. - */ -exports.getLauncherDirectory = function(){ - return launcherDir -} - -/** - * Get the launcher's data directory. This is where all files related - * to game launch are installed (common, instances, java, etc). - * - * @returns {string} The absolute path of the launcher's data directory. - */ -exports.getDataDirectory = function(def = false){ - return !def ? config.settings.launcher.dataDirectory : DEFAULT_CONFIG.settings.launcher.dataDirectory -} - -/** - * Set the new data directory. - * - * @param {string} dataDirectory The new data directory. - */ -exports.setDataDirectory = function(dataDirectory){ - config.settings.launcher.dataDirectory = dataDirectory -} - -const configPath = path.join(exports.getLauncherDirectory(), 'config.json') -const configPathLEGACY = path.join(dataPath, 'config.json') -const firstLaunch = !fs.existsSync(configPath) && !fs.existsSync(configPathLEGACY) - -exports.getAbsoluteMinRAM = function(){ - const mem = os.totalmem() - return mem >= 6000000000 ? 3 : 2 -} - -exports.getAbsoluteMaxRAM = function(){ - const mem = os.totalmem() - const gT16 = mem-16000000000 - return Math.floor((mem-1000000000-(gT16 > 0 ? (Number.parseInt(gT16/8) + 16000000000/4) : mem/4))/1000000000) -} - -function resolveMaxRAM(){ - const mem = os.totalmem() - return mem >= 8000000000 ? '4G' : (mem >= 6000000000 ? '3G' : '2G') -} - -function resolveMinRAM(){ - return resolveMaxRAM() -} - -/** - * Three types of values: - * Static = Explicitly declared. - * Dynamic = Calculated by a private function. - * Resolved = Resolved externally, defaults to null. - */ -const DEFAULT_CONFIG = { - settings: { - java: { - minRAM: resolveMinRAM(), - maxRAM: resolveMaxRAM(), // Dynamic - executable: null, - jvmOptions: [ - '-XX:+UseConcMarkSweepGC', - '-XX:+CMSIncrementalMode', - '-XX:-UseAdaptiveSizePolicy', - '-Xmn128M' - ], - }, - game: { - resWidth: 1280, - resHeight: 720, - fullscreen: false, - autoConnect: true, - launchDetached: true - }, - launcher: { - allowPrerelease: false, - dataDirectory: dataPath - } - }, - newsCache: { - date: null, - content: null, - dismissed: false - }, - clientToken: null, - selectedServer: null, // Resolved - selectedAccount: null, - authenticationDatabase: {}, - modConfigurations: [] -} - -let config = null - -// Persistance Utility Functions - -/** - * Save the current configuration to a file. - */ -exports.save = function(){ - fs.writeFileSync(configPath, JSON.stringify(config, null, 4), 'UTF-8') -} - -/** - * Load the configuration into memory. If a configuration file exists, - * that will be read and saved. Otherwise, a default configuration will - * be generated. Note that "resolved" values default to null and will - * need to be externally assigned. - */ -exports.load = function(){ - let doLoad = true - - if(!fs.existsSync(configPath)){ - // Create all parent directories. - fs.ensureDirSync(path.join(configPath, '..')) - if(fs.existsSync(configPathLEGACY)){ - fs.moveSync(configPathLEGACY, configPath) - } else { - doLoad = false - config = DEFAULT_CONFIG - exports.save() - } - } - if(doLoad){ - let doValidate = false - try { - config = JSON.parse(fs.readFileSync(configPath, 'UTF-8')) - doValidate = true - } catch (err){ - logger.error(err) - logger.log('Configuration file contains malformed JSON or is corrupt.') - logger.log('Generating a new configuration file.') - fs.ensureDirSync(path.join(configPath, '..')) - config = DEFAULT_CONFIG - exports.save() - } - if(doValidate){ - config = validateKeySet(DEFAULT_CONFIG, config) - exports.save() - } - } - logger.log('Successfully Loaded') -} - -/** - * @returns {boolean} Whether or not the manager has been loaded. - */ -exports.isLoaded = function(){ - return config != null -} - -/** - * Validate that the destination object has at least every field - * present in the source object. Assign a default value otherwise. - * - * @param {Object} srcObj The source object to reference against. - * @param {Object} destObj The destination object. - * @returns {Object} A validated destination object. - */ -function validateKeySet(srcObj, destObj){ - if(srcObj == null){ - srcObj = {} - } - const validationBlacklist = ['authenticationDatabase'] - const keys = Object.keys(srcObj) - for(let i=0; i} An array of each stored authenticated account. - */ -exports.getAuthAccounts = function(){ - return config.authenticationDatabase -} - -/** - * Returns the authenticated account with the given uuid. Value may - * be null. - * - * @param {string} uuid The uuid of the authenticated account. - * @returns {Object} The authenticated account with the given uuid. - */ -exports.getAuthAccount = function(uuid){ - return config.authenticationDatabase[uuid] -} - -/** - * Update the access token of an authenticated account. - * - * @param {string} uuid The uuid of the authenticated account. - * @param {string} accessToken The new Access Token. - * - * @returns {Object} The authenticated account object created by this action. - */ -exports.updateAuthAccount = function(uuid, accessToken){ - config.authenticationDatabase[uuid].accessToken = accessToken - return config.authenticationDatabase[uuid] -} - -/** - * Adds an authenticated account to the database to be stored. - * - * @param {string} uuid The uuid of the authenticated account. - * @param {string} accessToken The accessToken of the authenticated account. - * @param {string} username The username (usually email) of the authenticated account. - * @param {string} displayName The in game name of the authenticated account. - * - * @returns {Object} The authenticated account object created by this action. - */ -exports.addAuthAccount = function(uuid, accessToken, username, displayName){ - config.selectedAccount = uuid - config.authenticationDatabase[uuid] = { - accessToken, - username: username.trim(), - uuid: uuid.trim(), - displayName: displayName.trim() - } - return config.authenticationDatabase[uuid] -} - -/** - * Remove an authenticated account from the database. If the account - * was also the selected account, a new one will be selected. If there - * are no accounts, the selected account will be null. - * - * @param {string} uuid The uuid of the authenticated account. - * - * @returns {boolean} True if the account was removed, false if it never existed. - */ -exports.removeAuthAccount = function(uuid){ - if(config.authenticationDatabase[uuid] != null){ - delete config.authenticationDatabase[uuid] - if(config.selectedAccount === uuid){ - const keys = Object.keys(config.authenticationDatabase) - if(keys.length > 0){ - config.selectedAccount = keys[0] - } else { - config.selectedAccount = null - config.clientToken = null - } - } - return true - } - return false -} - -/** - * Get the currently selected authenticated account. - * - * @returns {Object} The selected authenticated account. - */ -exports.getSelectedAccount = function(){ - return config.authenticationDatabase[config.selectedAccount] -} - -/** - * Set the selected authenticated account. - * - * @param {string} uuid The UUID of the account which is to be set - * as the selected account. - * - * @returns {Object} The selected authenticated account. - */ -exports.setSelectedAccount = function(uuid){ - const authAcc = config.authenticationDatabase[uuid] - if(authAcc != null) { - config.selectedAccount = uuid - } - return authAcc -} - -/** - * Get an array of each mod configuration currently stored. - * - * @returns {Array.} An array of each stored mod configuration. - */ -exports.getModConfigurations = function(){ - return config.modConfigurations -} - -/** - * Set the array of stored mod configurations. - * - * @param {Array.} configurations An array of mod configurations. - */ -exports.setModConfigurations = function(configurations){ - config.modConfigurations = configurations -} - -/** - * Get the mod configuration for a specific server. - * - * @param {string} serverid The id of the server. - * @returns {Object} The mod configuration for the given server. - */ -exports.getModConfiguration = function(serverid){ - const cfgs = config.modConfigurations - for(let i=0; i} An array of the additional arguments for JVM initialization. - */ -exports.getJVMOptions = function(def = false){ - return !def ? config.settings.java.jvmOptions : DEFAULT_CONFIG.settings.java.jvmOptions -} - -/** - * Set the additional arguments for JVM initialization. Required arguments, - * such as memory allocation, will be dynamically resolved and should not be - * included in this value. - * - * @param {Array.} jvmOptions An array of the new additional arguments for JVM - * initialization. - */ -exports.setJVMOptions = function(jvmOptions){ - config.settings.java.jvmOptions = jvmOptions -} - -// Game Settings - -/** - * Retrieve the width of the game window. - * - * @param {boolean} def Optional. If true, the default value will be returned. - * @returns {number} The width of the game window. - */ -exports.getGameWidth = function(def = false){ - return !def ? config.settings.game.resWidth : DEFAULT_CONFIG.settings.game.resWidth -} - -/** - * Set the width of the game window. - * - * @param {number} resWidth The new width of the game window. - */ -exports.setGameWidth = function(resWidth){ - config.settings.game.resWidth = Number.parseInt(resWidth) -} - -/** - * Validate a potential new width value. - * - * @param {number} resWidth The width value to validate. - * @returns {boolean} Whether or not the value is valid. - */ -exports.validateGameWidth = function(resWidth){ - const nVal = Number.parseInt(resWidth) - return Number.isInteger(nVal) && nVal >= 0 -} - -/** - * Retrieve the height of the game window. - * - * @param {boolean} def Optional. If true, the default value will be returned. - * @returns {number} The height of the game window. - */ -exports.getGameHeight = function(def = false){ - return !def ? config.settings.game.resHeight : DEFAULT_CONFIG.settings.game.resHeight -} - -/** - * Set the height of the game window. - * - * @param {number} resHeight The new height of the game window. - */ -exports.setGameHeight = function(resHeight){ - config.settings.game.resHeight = Number.parseInt(resHeight) -} - -/** - * Validate a potential new height value. - * - * @param {number} resHeight The height value to validate. - * @returns {boolean} Whether or not the value is valid. - */ -exports.validateGameHeight = function(resHeight){ - const nVal = Number.parseInt(resHeight) - return Number.isInteger(nVal) && nVal >= 0 -} - -/** - * Check if the game should be launched in fullscreen mode. - * - * @param {boolean} def Optional. If true, the default value will be returned. - * @returns {boolean} Whether or not the game is set to launch in fullscreen mode. - */ -exports.getFullscreen = function(def = false){ - return !def ? config.settings.game.fullscreen : DEFAULT_CONFIG.settings.game.fullscreen -} - -/** - * Change the status of if the game should be launched in fullscreen mode. - * - * @param {boolean} fullscreen Whether or not the game should launch in fullscreen mode. - */ -exports.setFullscreen = function(fullscreen){ - config.settings.game.fullscreen = fullscreen -} - -/** - * Check if the game should auto connect to servers. - * - * @param {boolean} def Optional. If true, the default value will be returned. - * @returns {boolean} Whether or not the game should auto connect to servers. - */ -exports.getAutoConnect = function(def = false){ - return !def ? config.settings.game.autoConnect : DEFAULT_CONFIG.settings.game.autoConnect -} - -/** - * Change the status of whether or not the game should auto connect to servers. - * - * @param {boolean} autoConnect Whether or not the game should auto connect to servers. - */ -exports.setAutoConnect = function(autoConnect){ - config.settings.game.autoConnect = autoConnect -} - -/** - * Check if the game should launch as a detached process. - * - * @param {boolean} def Optional. If true, the default value will be returned. - * @returns {boolean} Whether or not the game will launch as a detached process. - */ -exports.getLaunchDetached = function(def = false){ - return !def ? config.settings.game.launchDetached : DEFAULT_CONFIG.settings.game.launchDetached -} - -/** - * Change the status of whether or not the game should launch as a detached process. - * - * @param {boolean} launchDetached Whether or not the game should launch as a detached process. - */ -exports.setLaunchDetached = function(launchDetached){ - config.settings.game.launchDetached = launchDetached -} - -// Launcher Settings - -/** - * Check if the launcher should download prerelease versions. - * - * @param {boolean} def Optional. If true, the default value will be returned. - * @returns {boolean} Whether or not the launcher should download prerelease versions. - */ -exports.getAllowPrerelease = function(def = false){ - return !def ? config.settings.launcher.allowPrerelease : DEFAULT_CONFIG.settings.launcher.allowPrerelease -} - -/** - * Change the status of Whether or not the launcher should download prerelease versions. - * - * @param {boolean} launchDetached Whether or not the launcher should download prerelease versions. - */ -exports.setAllowPrerelease = function(allowPrerelease){ - config.settings.launcher.allowPrerelease = allowPrerelease -} \ No newline at end of file diff --git a/app/assets/js/distromanager.js b/app/assets/js/distromanager.js deleted file mode 100644 index a4cafff..0000000 --- a/app/assets/js/distromanager.js +++ /dev/null @@ -1,605 +0,0 @@ -const fs = require('fs') -const path = require('path') -const request = require('request') - -const ConfigManager = require('./configmanager') -const logger = require('./loggerutil')('%c[DistroManager]', 'color: #a02d2a; font-weight: bold') - -/** - * Represents the download information - * for a specific module. - */ -class Artifact { - - /** - * Parse a JSON object into an Artifact. - * - * @param {Object} json A JSON object representing an Artifact. - * - * @returns {Artifact} The parsed Artifact. - */ - static fromJSON(json){ - return Object.assign(new Artifact(), json) - } - - /** - * Get the MD5 hash of the artifact. This value may - * be undefined for artifacts which are not to be - * validated and updated. - * - * @returns {string} The MD5 hash of the Artifact or undefined. - */ - getHash(){ - return this.MD5 - } - - /** - * @returns {number} The download size of the artifact. - */ - getSize(){ - return this.size - } - - /** - * @returns {string} The download url of the artifact. - */ - getURL(){ - return this.url - } - - /** - * @returns {string} The artifact's destination path. - */ - getPath(){ - return this.path - } - -} -exports.Artifact - -/** - * Represents a the requirement status - * of a module. - */ -class Required { - - /** - * Parse a JSON object into a Required object. - * - * @param {Object} json A JSON object representing a Required object. - * - * @returns {Required} The parsed Required object. - */ - static fromJSON(json){ - if(json == null){ - return new Required(true, true) - } else { - return new Required(json.value == null ? true : json.value, json.def == null ? true : json.def) - } - } - - constructor(value, def){ - this.value = value - this.default = def - } - - /** - * Get the default value for a required object. If a module - * is not required, this value determines whether or not - * it is enabled by default. - * - * @returns {boolean} The default enabled value. - */ - isDefault(){ - return this.default - } - - /** - * @returns {boolean} Whether or not the module is required. - */ - isRequired(){ - return this.value - } - -} -exports.Required - -/** - * Represents a module. - */ -class Module { - - /** - * Parse a JSON object into a Module. - * - * @param {Object} json A JSON object representing a Module. - * @param {string} serverid The ID of the server to which this module belongs. - * - * @returns {Module} The parsed Module. - */ - static fromJSON(json, serverid){ - return new Module(json.id, json.name, json.type, json.required, json.artifact, json.subModules, serverid) - } - - /** - * Resolve the default extension for a specific module type. - * - * @param {string} type The type of the module. - * - * @return {string} The default extension for the given type. - */ - static _resolveDefaultExtension(type){ - switch (type) { - case exports.Types.Library: - case exports.Types.ForgeHosted: - case exports.Types.LiteLoader: - case exports.Types.ForgeMod: - return 'jar' - case exports.Types.LiteMod: - return 'litemod' - case exports.Types.File: - default: - return 'jar' // There is no default extension really. - } - } - - constructor(id, name, type, required, artifact, subModules, serverid) { - this.identifier = id - this.type = type - this._resolveMetaData() - this.name = name - this.required = Required.fromJSON(required) - this.artifact = Artifact.fromJSON(artifact) - this._resolveArtifactPath(artifact.path, serverid) - this._resolveSubModules(subModules, serverid) - } - - _resolveMetaData(){ - try { - - const m0 = this.identifier.split('@') - - this.artifactExt = m0[1] || Module._resolveDefaultExtension(this.type) - - const m1 = m0[0].split(':') - - this.artifactClassifier = m1[3] || undefined - this.artifactVersion = m1[2] || '???' - this.artifactID = m1[1] || '???' - this.artifactGroup = m1[0] || '???' - - } catch (err) { - // Improper identifier - logger.error('Improper ID for module', this.identifier, err) - } - } - - _resolveArtifactPath(artifactPath, serverid){ - const pth = artifactPath == null ? path.join(...this.getGroup().split('.'), this.getID(), this.getVersion(), `${this.getID()}-${this.getVersion()}${this.artifactClassifier != undefined ? `-${this.artifactClassifier}` : ''}.${this.getExtension()}`) : artifactPath - - switch (this.type){ - case exports.Types.Library: - case exports.Types.ForgeHosted: - case exports.Types.LiteLoader: - this.artifact.path = path.join(ConfigManager.getCommonDirectory(), 'libraries', pth) - break - case exports.Types.ForgeMod: - case exports.Types.LiteMod: - this.artifact.path = path.join(ConfigManager.getCommonDirectory(), 'modstore', pth) - break - case exports.Types.VersionManifest: - this.artifact.path = path.join(ConfigManager.getCommonDirectory(), 'versions', this.getIdentifier(), `${this.getIdentifier()}.json`) - break - case exports.Types.File: - default: - this.artifact.path = path.join(ConfigManager.getInstanceDirectory(), serverid, pth) - break - } - - } - - _resolveSubModules(json, serverid){ - const arr = [] - if(json != null){ - for(let sm of json){ - arr.push(Module.fromJSON(sm, serverid)) - } - } - this.subModules = arr.length > 0 ? arr : null - } - - /** - * @returns {string} The full, unparsed module identifier. - */ - getIdentifier(){ - return this.identifier - } - - /** - * @returns {string} The name of the module. - */ - getName(){ - return this.name - } - - /** - * @returns {Required} The required object declared by this module. - */ - getRequired(){ - return this.required - } - - /** - * @returns {Artifact} The artifact declared by this module. - */ - getArtifact(){ - return this.artifact - } - - /** - * @returns {string} The maven identifier of this module's artifact. - */ - getID(){ - return this.artifactID - } - - /** - * @returns {string} The maven group of this module's artifact. - */ - getGroup(){ - return this.artifactGroup - } - - /** - * @returns {string} The identifier without he version or extension. - */ - getVersionlessID(){ - return this.getGroup() + ':' + this.getID() - } - - /** - * @returns {string} The identifier without the extension. - */ - getExtensionlessID(){ - return this.getIdentifier().split('@')[0] - } - - /** - * @returns {string} The version of this module's artifact. - */ - getVersion(){ - return this.artifactVersion - } - - /** - * @returns {string} The classifier of this module's artifact - */ - getClassifier(){ - return this.artifactClassifier - } - - /** - * @returns {string} The extension of this module's artifact. - */ - getExtension(){ - return this.artifactExt - } - - /** - * @returns {boolean} Whether or not this module has sub modules. - */ - hasSubModules(){ - return this.subModules != null - } - - /** - * @returns {Array.} An array of sub modules. - */ - getSubModules(){ - return this.subModules - } - - /** - * @returns {string} The type of the module. - */ - getType(){ - return this.type - } - -} -exports.Module - -/** - * Represents a server configuration. - */ -class Server { - - /** - * Parse a JSON object into a Server. - * - * @param {Object} json A JSON object representing a Server. - * - * @returns {Server} The parsed Server object. - */ - static fromJSON(json){ - - const mdls = json.modules - json.modules = [] - - const serv = Object.assign(new Server(), json) - serv._resolveModules(mdls) - - return serv - } - - _resolveModules(json){ - const arr = [] - for(let m of json){ - arr.push(Module.fromJSON(m, this.getID())) - } - this.modules = arr - } - - /** - * @returns {string} The ID of the server. - */ - getID(){ - return this.id - } - - /** - * @returns {string} The name of the server. - */ - getName(){ - return this.name - } - - /** - * @returns {string} The description of the server. - */ - getDescription(){ - return this.description - } - - /** - * @returns {string} The URL of the server's icon. - */ - getIcon(){ - return this.icon - } - - /** - * @returns {string} The version of the server configuration. - */ - getVersion(){ - return this.version - } - - /** - * @returns {string} The IP address of the server. - */ - getAddress(){ - return this.address - } - - /** - * @returns {string} The minecraft version of the server. - */ - getMinecraftVersion(){ - return this.minecraftVersion - } - - /** - * @returns {boolean} Whether or not this server is the main - * server. The main server is selected by the launcher when - * no valid server is selected. - */ - isMainServer(){ - return this.mainServer - } - - /** - * @returns {boolean} Whether or not the server is autoconnect. - * by default. - */ - isAutoConnect(){ - return this.autoconnect - } - - /** - * @returns {Array.} An array of modules for this server. - */ - getModules(){ - return this.modules - } - -} -exports.Server - -/** - * Represents the Distribution Index. - */ -class DistroIndex { - - /** - * Parse a JSON object into a DistroIndex. - * - * @param {Object} json A JSON object representing a DistroIndex. - * - * @returns {DistroIndex} The parsed Server object. - */ - static fromJSON(json){ - - const servers = json.servers - json.servers = [] - - const distro = Object.assign(new DistroIndex(), json) - distro._resolveServers(servers) - distro._resolveMainServer() - - return distro - } - - _resolveServers(json){ - const arr = [] - for(let s of json){ - arr.push(Server.fromJSON(s)) - } - this.servers = arr - } - - _resolveMainServer(){ - - for(let serv of this.servers){ - if(serv.mainServer){ - this.mainServer = serv.id - return - } - } - - // If no server declares default_selected, default to the first one declared. - this.mainServer = (this.servers.length > 0) ? this.servers[0].getID() : null - } - - /** - * @returns {string} The version of the distribution index. - */ - getVersion(){ - return this.version - } - - /** - * @returns {string} The URL to the news RSS feed. - */ - getRSS(){ - return this.rss - } - - /** - * @returns {Array.} An array of declared server configurations. - */ - getServers(){ - return this.servers - } - - /** - * Get a server configuration by its ID. If it does not - * exist, null will be returned. - * - * @param {string} id The ID of the server. - * - * @returns {Server} The server configuration with the given ID or null. - */ - getServer(id){ - for(let serv of this.servers){ - if(serv.id === id){ - return serv - } - } - return null - } - - /** - * Get the main server. - * - * @returns {Server} The main server. - */ - getMainServer(){ - return this.mainServer != null ? this.getServer(this.mainServer) : null - } - -} -exports.DistroIndex - -exports.Types = { - Library: 'Library', - ForgeHosted: 'ForgeHosted', - Forge: 'Forge', // Unimplemented - LiteLoader: 'LiteLoader', - ForgeMod: 'ForgeMod', - LiteMod: 'LiteMod', - File: 'File', - VersionManifest: 'VersionManifest' -} - -let DEV_MODE = false - -const DISTRO_PATH = path.join(ConfigManager.getLauncherDirectory(), 'distribution.json') -const DEV_PATH = path.join(ConfigManager.getLauncherDirectory(), 'dev_distribution.json') - -let data = null - -/** - * @returns {Promise.} - */ -exports.pullRemote = function(){ - if(DEV_MODE){ - return exports.pullLocal() - } - return new Promise((resolve, reject) => { - const distroURL = 'http://mc.westeroscraft.com/WesterosCraftLauncher/distribution.json' - //const distroURL = 'https://gist.githubusercontent.com/dscalzi/53b1ba7a11d26a5c353f9d5ae484b71b/raw/' - const opts = { - url: distroURL, - timeout: 2500 - } - const distroDest = path.join(ConfigManager.getLauncherDirectory(), 'distribution.json') - request(opts, (error, resp, body) => { - if(!error){ - - try { - data = DistroIndex.fromJSON(JSON.parse(body)) - } catch (e) { - reject(e) - } - - fs.writeFile(distroDest, body, 'utf-8', (err) => { - if(!err){ - resolve(data) - } else { - reject(err) - } - }) - } else { - reject(error) - } - }) - }) -} - -/** - * @returns {Promise.} - */ -exports.pullLocal = function(){ - return new Promise((resolve, reject) => { - fs.readFile(DEV_MODE ? DEV_PATH : DISTRO_PATH, 'utf-8', (err, d) => { - if(!err){ - data = DistroIndex.fromJSON(JSON.parse(d)) - resolve(data) - } else { - reject(err) - } - }) - }) -} - -exports.setDevMode = function(value){ - if(value){ - logger.log('Developer mode enabled.') - logger.log('If you don\'t know what that means, revert immediately.') - } else { - logger.log('Developer mode disabled.') - } - DEV_MODE = value -} - -exports.isDevMode = function(){ - return DEV_MODE -} - -/** - * @returns {DistroIndex} - */ -exports.getDistribution = function(){ - return data -} \ No newline at end of file diff --git a/app/assets/js/isdev.js b/app/assets/js/isdev.js deleted file mode 100644 index 1ed55e5..0000000 --- a/app/assets/js/isdev.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict' -const getFromEnv = parseInt(process.env.ELECTRON_IS_DEV, 10) === 1 -const isEnvSet = 'ELECTRON_IS_DEV' in process.env - -module.exports = isEnvSet ? getFromEnv : (process.defaultApp || /node_modules[\\/]electron[\\/]/.test(process.execPath)) \ No newline at end of file diff --git a/app/assets/js/langloader.js b/app/assets/js/langloader.js deleted file mode 100644 index 24ab84a..0000000 --- a/app/assets/js/langloader.js +++ /dev/null @@ -1,21 +0,0 @@ -const fs = require('fs-extra') -const path = require('path') - -let lang - -exports.loadLanguage = function(id){ - lang = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'lang', `${id}.json`))) || {} -} - -exports.query = function(id){ - let query = id.split('.') - let res = lang - for(let q of query){ - res = res[q] - } - return res === lang ? {} : res -} - -exports.queryJS = function(id){ - return exports.query(`js.${id}`) -} \ No newline at end of file diff --git a/app/assets/js/loggerutil.js b/app/assets/js/loggerutil.js deleted file mode 100644 index 7389941..0000000 --- a/app/assets/js/loggerutil.js +++ /dev/null @@ -1,32 +0,0 @@ -class LoggerUtil { - - constructor(prefix, style){ - this.prefix = prefix - this.style = style - } - - log(){ - console.log.apply(null, [this.prefix, this.style, ...arguments]) - } - - info(){ - console.info.apply(null, [this.prefix, this.style, ...arguments]) - } - - warn(){ - console.warn.apply(null, [this.prefix, this.style, ...arguments]) - } - - debug(){ - console.debug.apply(null, [this.prefix, this.style, ...arguments]) - } - - error(){ - console.error.apply(null, [this.prefix, this.style, ...arguments]) - } - -} - -module.exports = function (prefix, style){ - return new LoggerUtil(prefix, style) -} \ No newline at end of file diff --git a/app/assets/js/mojang.js b/app/assets/js/mojang.js deleted file mode 100644 index 7514383..0000000 --- a/app/assets/js/mojang.js +++ /dev/null @@ -1,271 +0,0 @@ -/** - * Mojang - * - * This module serves as a minimal wrapper for Mojang's REST api. - * - * @module mojang - */ -// Requirements -const request = require('request') -const logger = require('./loggerutil')('%c[Mojang]', 'color: #a02d2a; font-weight: bold') - -// Constants -const minecraftAgent = { - name: 'Minecraft', - version: 1 -} -const authpath = 'https://authserver.mojang.com' -const statuses = [ - { - service: 'sessionserver.mojang.com', - status: 'grey', - name: 'Multiplayer Session Service', - essential: true - }, - { - service: 'authserver.mojang.com', - status: 'grey', - name: 'Authentication Service', - essential: true - }, - { - service: 'textures.minecraft.net', - status: 'grey', - name: 'Minecraft Skins', - essential: false - }, - { - service: 'api.mojang.com', - status: 'grey', - name: 'Public API', - essential: false - }, - { - service: 'minecraft.net', - status: 'grey', - name: 'Minecraft.net', - essential: false - }, - { - service: 'account.mojang.com', - status: 'grey', - name: 'Mojang Accounts Website', - essential: false - } -] - -// Functions - -/** - * Converts a Mojang status color to a hex value. Valid statuses - * are 'green', 'yellow', 'red', and 'grey'. Grey is a custom status - * to our project which represents an unknown status. - * - * @param {string} status A valid status code. - * @returns {string} The hex color of the status code. - */ -exports.statusToHex = function(status){ - switch(status.toLowerCase()){ - case 'green': - return '#a5c325' - case 'yellow': - return '#eac918' - case 'red': - return '#c32625' - case 'grey': - default: - return '#848484' - } -} - -/** - * Retrieves the status of Mojang's services. - * The response is condensed into a single object. Each service is - * a key, where the value is an object containing a status and name - * property. - * - * @see http://wiki.vg/Mojang_API#API_Status - */ -exports.status = function(){ - return new Promise((resolve, reject) => { - request.get('https://status.mojang.com/check', - { - json: true, - timeout: 2500 - }, - function(error, response, body){ - - if(error || response.statusCode !== 200){ - logger.warn('Unable to retrieve Mojang status.') - logger.debug('Error while retrieving Mojang statuses:', error) - //reject(error || response.statusCode) - for(let i=0; i { - - const body = { - agent, - username, - password, - requestUser - } - if(clientToken != null){ - body.clientToken = clientToken - } - - request.post(authpath + '/authenticate', - { - json: true, - body - }, - function(error, response, body){ - if(error){ - logger.error('Error during authentication.', error) - reject(error) - } else { - if(response.statusCode === 200){ - resolve(body) - } else { - reject(body || {code: 'ENOTFOUND'}) - } - } - }) - }) -} - -/** - * Validate an access token. This should always be done before launching. - * The client token should match the one used to create the access token. - * - * @param {string} accessToken The access token to validate. - * @param {string} clientToken The launcher's client token. - * - * @see http://wiki.vg/Authentication#Validate - */ -exports.validate = function(accessToken, clientToken){ - return new Promise((resolve, reject) => { - request.post(authpath + '/validate', - { - json: true, - body: { - accessToken, - clientToken - } - }, - function(error, response, body){ - if(error){ - logger.error('Error during validation.', error) - reject(error) - } else { - if(response.statusCode === 403){ - resolve(false) - } else { - // 204 if valid - resolve(true) - } - } - }) - }) -} - -/** - * Invalidates an access token. The clientToken must match the - * token used to create the provided accessToken. - * - * @param {string} accessToken The access token to invalidate. - * @param {string} clientToken The launcher's client token. - * - * @see http://wiki.vg/Authentication#Invalidate - */ -exports.invalidate = function(accessToken, clientToken){ - return new Promise((resolve, reject) => { - request.post(authpath + '/invalidate', - { - json: true, - body: { - accessToken, - clientToken - } - }, - function(error, response, body){ - if(error){ - logger.error('Error during invalidation.', error) - reject(error) - } else { - if(response.statusCode === 204){ - resolve() - } else { - reject(body) - } - } - }) - }) -} - -/** - * Refresh a user's authentication. This should be used to keep a user logged - * in without asking them for their credentials again. A new access token will - * be generated using a recent invalid access token. See Wiki for more info. - * - * @param {string} accessToken The old access token. - * @param {string} clientToken The launcher's client token. - * @param {boolean} requestUser Optional. Adds user object to the reponse. - * - * @see http://wiki.vg/Authentication#Refresh - */ -exports.refresh = function(accessToken, clientToken, requestUser = true){ - return new Promise((resolve, reject) => { - request.post(authpath + '/refresh', - { - json: true, - body: { - accessToken, - clientToken, - requestUser - } - }, - function(error, response, body){ - if(error){ - logger.error('Error during refresh.', error) - reject(error) - } else { - if(response.statusCode === 200){ - resolve(body) - } else { - reject(body) - } - } - }) - }) -} \ No newline at end of file diff --git a/app/assets/css/launcher.css b/assets/css/launcher.css similarity index 99% rename from app/assets/css/launcher.css rename to assets/css/launcher.css index 8088d98..4b55b15 100644 --- a/app/assets/css/launcher.css +++ b/assets/css/launcher.css @@ -1,5 +1,5 @@ /* Github Code Highlighting. */ -@import "../../../node_modules/github-syntax-dark/lib/github-dark.css"; +@import "../../node_modules/github-syntax-dark/lib/github-dark.css"; /******************************************************************************* * * diff --git a/app/assets/fonts/Avenir-Black.ttf b/assets/fonts/Avenir-Black.ttf similarity index 100% rename from app/assets/fonts/Avenir-Black.ttf rename to assets/fonts/Avenir-Black.ttf diff --git a/app/assets/fonts/Avenir-BlackOblique.ttf b/assets/fonts/Avenir-BlackOblique.ttf similarity index 100% rename from app/assets/fonts/Avenir-BlackOblique.ttf rename to assets/fonts/Avenir-BlackOblique.ttf diff --git a/app/assets/fonts/Avenir-Book.ttf b/assets/fonts/Avenir-Book.ttf similarity index 100% rename from app/assets/fonts/Avenir-Book.ttf rename to assets/fonts/Avenir-Book.ttf diff --git a/app/assets/fonts/Avenir-BookOblique.ttf b/assets/fonts/Avenir-BookOblique.ttf similarity index 100% rename from app/assets/fonts/Avenir-BookOblique.ttf rename to assets/fonts/Avenir-BookOblique.ttf diff --git a/app/assets/fonts/Avenir-Heavy.ttf b/assets/fonts/Avenir-Heavy.ttf similarity index 100% rename from app/assets/fonts/Avenir-Heavy.ttf rename to assets/fonts/Avenir-Heavy.ttf diff --git a/app/assets/fonts/Avenir-HeavyOblique.ttf b/assets/fonts/Avenir-HeavyOblique.ttf similarity index 100% rename from app/assets/fonts/Avenir-HeavyOblique.ttf rename to assets/fonts/Avenir-HeavyOblique.ttf diff --git a/app/assets/fonts/Avenir-Light.ttf b/assets/fonts/Avenir-Light.ttf similarity index 100% rename from app/assets/fonts/Avenir-Light.ttf rename to assets/fonts/Avenir-Light.ttf diff --git a/app/assets/fonts/Avenir-LightOblique.ttf b/assets/fonts/Avenir-LightOblique.ttf similarity index 100% rename from app/assets/fonts/Avenir-LightOblique.ttf rename to assets/fonts/Avenir-LightOblique.ttf diff --git a/app/assets/fonts/Avenir-Medium.ttf b/assets/fonts/Avenir-Medium.ttf similarity index 100% rename from app/assets/fonts/Avenir-Medium.ttf rename to assets/fonts/Avenir-Medium.ttf diff --git a/app/assets/fonts/Avenir-MediumOblique.ttf b/assets/fonts/Avenir-MediumOblique.ttf similarity index 100% rename from app/assets/fonts/Avenir-MediumOblique.ttf rename to assets/fonts/Avenir-MediumOblique.ttf diff --git a/app/assets/fonts/Avenir-Oblique.ttf b/assets/fonts/Avenir-Oblique.ttf similarity index 100% rename from app/assets/fonts/Avenir-Oblique.ttf rename to assets/fonts/Avenir-Oblique.ttf diff --git a/app/assets/fonts/Avenir-Roman.ttf b/assets/fonts/Avenir-Roman.ttf similarity index 100% rename from app/assets/fonts/Avenir-Roman.ttf rename to assets/fonts/Avenir-Roman.ttf diff --git a/app/assets/fonts/ringbearer.ttf b/assets/fonts/ringbearer.ttf similarity index 100% rename from app/assets/fonts/ringbearer.ttf rename to assets/fonts/ringbearer.ttf diff --git a/app/assets/images/LoadingSeal.png b/assets/images/LoadingSeal.png similarity index 100% rename from app/assets/images/LoadingSeal.png rename to assets/images/LoadingSeal.png diff --git a/app/assets/images/LoadingText.png b/assets/images/LoadingText.png similarity index 100% rename from app/assets/images/LoadingText.png rename to assets/images/LoadingText.png diff --git a/app/assets/images/SealCircle.ico b/assets/images/SealCircle.ico similarity index 100% rename from app/assets/images/SealCircle.ico rename to assets/images/SealCircle.ico diff --git a/app/assets/images/SealCircle.png b/assets/images/SealCircle.png similarity index 100% rename from app/assets/images/SealCircle.png rename to assets/images/SealCircle.png diff --git a/app/assets/images/backgrounds/0.jpg b/assets/images/backgrounds/0.jpg similarity index 100% rename from app/assets/images/backgrounds/0.jpg rename to assets/images/backgrounds/0.jpg diff --git a/app/assets/images/backgrounds/1.jpg b/assets/images/backgrounds/1.jpg similarity index 100% rename from app/assets/images/backgrounds/1.jpg rename to assets/images/backgrounds/1.jpg diff --git a/app/assets/images/backgrounds/2.jpg b/assets/images/backgrounds/2.jpg similarity index 100% rename from app/assets/images/backgrounds/2.jpg rename to assets/images/backgrounds/2.jpg diff --git a/app/assets/images/backgrounds/3.jpg b/assets/images/backgrounds/3.jpg similarity index 100% rename from app/assets/images/backgrounds/3.jpg rename to assets/images/backgrounds/3.jpg diff --git a/app/assets/images/backgrounds/4.jpg b/assets/images/backgrounds/4.jpg similarity index 100% rename from app/assets/images/backgrounds/4.jpg rename to assets/images/backgrounds/4.jpg diff --git a/app/assets/images/backgrounds/5.jpg b/assets/images/backgrounds/5.jpg similarity index 100% rename from app/assets/images/backgrounds/5.jpg rename to assets/images/backgrounds/5.jpg diff --git a/app/assets/images/backgrounds/6.jpg b/assets/images/backgrounds/6.jpg similarity index 100% rename from app/assets/images/backgrounds/6.jpg rename to assets/images/backgrounds/6.jpg diff --git a/app/assets/images/backgrounds/7.jpg b/assets/images/backgrounds/7.jpg similarity index 100% rename from app/assets/images/backgrounds/7.jpg rename to assets/images/backgrounds/7.jpg diff --git a/app/assets/images/icons/arrow.svg b/assets/images/icons/arrow.svg similarity index 100% rename from app/assets/images/icons/arrow.svg rename to assets/images/icons/arrow.svg diff --git a/app/assets/images/icons/discord.svg b/assets/images/icons/discord.svg similarity index 100% rename from app/assets/images/icons/discord.svg rename to assets/images/icons/discord.svg diff --git a/app/assets/images/icons/instagram.svg b/assets/images/icons/instagram.svg similarity index 100% rename from app/assets/images/icons/instagram.svg rename to assets/images/icons/instagram.svg diff --git a/app/assets/images/icons/link.svg b/assets/images/icons/link.svg similarity index 100% rename from app/assets/images/icons/link.svg rename to assets/images/icons/link.svg diff --git a/app/assets/images/icons/lock.svg b/assets/images/icons/lock.svg similarity index 100% rename from app/assets/images/icons/lock.svg rename to assets/images/icons/lock.svg diff --git a/app/assets/images/icons/news.svg b/assets/images/icons/news.svg similarity index 100% rename from app/assets/images/icons/news.svg rename to assets/images/icons/news.svg diff --git a/app/assets/images/icons/profile.svg b/assets/images/icons/profile.svg similarity index 100% rename from app/assets/images/icons/profile.svg rename to assets/images/icons/profile.svg diff --git a/app/assets/images/icons/settings.svg b/assets/images/icons/settings.svg similarity index 100% rename from app/assets/images/icons/settings.svg rename to assets/images/icons/settings.svg diff --git a/app/assets/images/icons/sevenstar.svg b/assets/images/icons/sevenstar.svg similarity index 100% rename from app/assets/images/icons/sevenstar.svg rename to assets/images/icons/sevenstar.svg diff --git a/app/assets/images/icons/sevenstar_circle.svg b/assets/images/icons/sevenstar_circle.svg similarity index 100% rename from app/assets/images/icons/sevenstar_circle.svg rename to assets/images/icons/sevenstar_circle.svg diff --git a/app/assets/images/icons/sevenstar_circle_extended.svg b/assets/images/icons/sevenstar_circle_extended.svg similarity index 100% rename from app/assets/images/icons/sevenstar_circle_extended.svg rename to assets/images/icons/sevenstar_circle_extended.svg diff --git a/app/assets/images/icons/sevenstar_circle_hole.svg b/assets/images/icons/sevenstar_circle_hole.svg similarity index 100% rename from app/assets/images/icons/sevenstar_circle_hole.svg rename to assets/images/icons/sevenstar_circle_hole.svg diff --git a/app/assets/images/icons/sevenstar_circle_hole_extended.svg b/assets/images/icons/sevenstar_circle_hole_extended.svg similarity index 100% rename from app/assets/images/icons/sevenstar_circle_hole_extended.svg rename to assets/images/icons/sevenstar_circle_hole_extended.svg diff --git a/app/assets/images/icons/sevenstar_extended.svg b/assets/images/icons/sevenstar_extended.svg similarity index 100% rename from app/assets/images/icons/sevenstar_extended.svg rename to assets/images/icons/sevenstar_extended.svg diff --git a/app/assets/images/icons/twitter.svg b/assets/images/icons/twitter.svg similarity index 100% rename from app/assets/images/icons/twitter.svg rename to assets/images/icons/twitter.svg diff --git a/app/assets/images/icons/youtube.svg b/assets/images/icons/youtube.svg similarity index 100% rename from app/assets/images/icons/youtube.svg rename to assets/images/icons/youtube.svg diff --git a/app/assets/images/minecraft.icns b/assets/images/minecraft.icns similarity index 100% rename from app/assets/images/minecraft.icns rename to assets/images/minecraft.icns diff --git a/app/assets/lang/en_US.json b/assets/lang/en_US.json similarity index 100% rename from app/assets/lang/en_US.json rename to assets/lang/en_US.json diff --git a/app/app.ejs b/assets/templates/app.ejs similarity index 89% rename from app/app.ejs rename to assets/templates/app.ejs index 4cdb091..74a1a9c 100644 --- a/app/app.ejs +++ b/assets/templates/app.ejs @@ -2,9 +2,9 @@ Westeroscraft Launcher - - - + + +