Removed enumerator, converting to static Config Manager (fixes so many issues), constants will now be stored by config manager in an internal object.

This commit is contained in:
Daniel Scalzi 2017-12-03 00:38:22 -05:00
parent 0dde4bce42
commit 98684a9c1f
6 changed files with 357 additions and 206 deletions

View File

@ -2,7 +2,7 @@ const mojang = require('mojang')
const path = require('path') const path = require('path')
const {AssetGuard} = require(path.join(__dirname, 'assets', 'js', 'assetguard.js')) const {AssetGuard} = require(path.join(__dirname, 'assets', 'js', 'assetguard.js'))
const ProcessBuilder = require(path.join(__dirname, 'assets', 'js', 'processbuilder.js')) const ProcessBuilder = require(path.join(__dirname, 'assets', 'js', 'processbuilder.js'))
const {GAME_DIRECTORY, DEFAULT_CONFIG} = require(path.join(__dirname, 'assets', 'js', 'enumerator.js')).enum const ConfigManager = require(path.join(__dirname, 'assets', 'js', 'configmanager.js'))
document.addEventListener('readystatechange', function(){ document.addEventListener('readystatechange', function(){
if (document.readyState === 'interactive'){ if (document.readyState === 'interactive'){
@ -15,7 +15,7 @@ document.addEventListener('readystatechange', function(){
// TODO convert this to dropdown menu. // TODO convert this to dropdown menu.
// Bind selected server // Bind selected server
document.getElementById('server_selection').innerHTML = '\u2022 ' + AssetGuard.getServerById(GAME_DIRECTORY, DEFAULT_CONFIG.getSelectedServer()).name document.getElementById('server_selection').innerHTML = '\u2022 ' + AssetGuard.getServerById(ConfigManager.getGameDirectory(), ConfigManager.getSelectedServer()).name
} }
}, false) }, false)
@ -35,11 +35,10 @@ testdownloads = async function(){
details.style.display = 'flex' details.style.display = 'flex'
content.style.display = 'none' content.style.display = 'none'
console.log(DEFAULT_CONFIG.getJavaExecutable()) tracker = new AssetGuard(ConfigManager.getGameDirectory(), ConfigManager.getJavaExecutable())
tracker = new AssetGuard(GAME_DIRECTORY, DEFAULT_CONFIG.getJavaExecutable())
det_text.innerHTML = 'Loading server information..' det_text.innerHTML = 'Loading server information..'
const serv = await tracker.validateDistribution(DEFAULT_CONFIG.getSelectedServer()) const serv = await tracker.validateDistribution(ConfigManager.getSelectedServer())
progress.setAttribute('value', 20) progress.setAttribute('value', 20)
progress_text.innerHTML = '20%' progress_text.innerHTML = '20%'
console.log('forge stuff done') console.log('forge stuff done')
@ -78,11 +77,11 @@ testdownloads = async function(){
det_text.innerHTML = 'Preparing to launch..' det_text.innerHTML = 'Preparing to launch..'
const forgeData = await tracker.loadForgeData(serv.id) const forgeData = await tracker.loadForgeData(serv.id)
const authUser = await mojang.auth('EMAIL', 'PASS', DEFAULT_CONFIG.getClientToken(), { const authUser = await mojang.auth('EMAIL', 'PASS', ConfigManager.getClientToken(), {
name: 'Minecraft', name: 'Minecraft',
version: 1 version: 1
}) })
let pb = new ProcessBuilder(GAME_DIRECTORY, serv, versionData, forgeData, authUser) let pb = new ProcessBuilder(ConfigManager.getGameDirectory(), serv, versionData, forgeData, authUser)
det_text.innerHTML = 'Launching game..' det_text.innerHTML = 'Launching game..'
let proc; let proc;
try{ try{

View File

@ -4,32 +4,22 @@ const os = require('os')
const path = require('path') const path = require('path')
const uuidV4 = require('uuid/v4') const uuidV4 = require('uuid/v4')
class ConfigManager { function resolveMaxRAM(){
constructor(path){
this.path = path
this.config = null
this.load()
}
/* Private functions to resolve default settings based on system specs. */
static _resolveMaxRAM(){
const mem = os.totalmem() const mem = os.totalmem()
return mem >= 8000000000 ? '4G' : (mem >= 6000000000 ? '3G' : '2G') return mem >= 8000000000 ? '4G' : (mem >= 6000000000 ? '3G' : '2G')
} }
/** /**
* Generates a default configuration object and saves it. * Three types of values:
* * Static = Explicitly declared.
* @param {Boolean} save - optional. If true, the default config will be saved after being generated. * Dynamic = Calculated by a private function.
* Resolved = Resolved externally, defaults to null.
*/ */
_generateDefault(save = true){ const DEFAULT_CONFIG = {
this.config = {
settings: { settings: {
java: { java: {
minRAM: '2G', minRAM: '2G',
maxRAM: ConfigManager._resolveMaxRAM(), maxRAM: resolveMaxRAM(), // Dynamic
executable: 'C:\\Program Files\\Java\\jdk1.8.0_152\\bin\\javaw.exe', // TODO Resolve executable: 'C:\\Program Files\\Java\\jdk1.8.0_152\\bin\\javaw.exe', // TODO Resolve
jvmOptions: [ jvmOptions: [
'-XX:+UseConcMarkSweepGC', '-XX:+UseConcMarkSweepGC',
@ -39,6 +29,7 @@ class ConfigManager {
], ],
}, },
game: { game: {
directory: path.join(__dirname, '..', '..', '..', 'target', 'test', 'mcfiles'),
resWidth: 1280, resWidth: 1280,
resHeight: 720, resHeight: 720,
fullscreen: false, fullscreen: false,
@ -49,126 +40,295 @@ class ConfigManager {
} }
}, },
clientToken: uuidV4(), clientToken: uuidV4(),
selectedServer: null, selectedServer: null, // Resolved
selectedAccount: null, selectedAccount: null,
authenticationDatabase: [], authenticationDatabase: [],
discord: { discord: {
clientID: 385581240906022916 clientID: 385581240906022916
} }
} }
if(save){
this.save() let config = null;
}
// Persistance Utility Functions
/**
* Save the current configuration to a file.
*/
exports.save = function(){
const filePath = path.join(config.settings.game.directory, 'config.json')
fs.writeFileSync(filePath, JSON.stringify(config, null, 4), 'UTF-8')
} }
/** /**
* Load the launcher configuration into memory. If the specified file does * Load the configuration into memory. If a configuration file exists,
* not exist, a default configuration will be generated and saved. * 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.
*/ */
load(){ exports.load = function(){
if(!fs.existsSync(this.path)){ // Determine the effective configuration.
mkpath.sync(path.join(this.path, '..')) const EFFECTIVE_CONFIG = config == null ? DEFAULT_CONFIG : config
this._generateDefault() const filePath = path.join(EFFECTIVE_CONFIG.settings.game.directory, 'config.json')
if(!fs.existsSync(filePath)){
// Create all parent directories.
mkpath.sync(path.join(filePath, '..'))
config = DEFAULT_CONFIG
exports.save()
} else { } else {
this.config = JSON.parse(fs.readFileSync(this.path, 'UTF-8')) config = JSON.parse(fs.readFileSync(filePath, 'UTF-8'))
} }
} }
/** // System Settings (Unconfigurable on UI)
* Save the launcher configuration to the specified file.
*/
save(){
fs.writeFileSync(this.path, JSON.stringify(this.config, null, 4), 'UTF-8')
}
/** /**
* Retrieve the launcher's Client Token. * Retrieve the launcher's Client Token.
*/
getClientToken(){
return this.config.clientToken
}
/**
* Retrieve the selected server configuration value.
*/
getSelectedServer(){
return this.config.selectedServer
}
/**
* Set the selected server configuration value.
* *
* @param {String} serverID - the id of the new selected server. * @param {Boolean} def - optional. If true, the default value will be returned.
* @returns {String} - the launcher's Client Token.
*/ */
setSelectedServer(serverID){ exports.getClientToken = function(def = false){
this.config.selectedServer = serverID return !def ? config.clientToken : DEFAULT_CONFIG.clientToken
this.save()
} }
/**
* Set the launcher's Client Token.
*
* @param {String} clientToken - the launcher's new Client Token.
*/
exports.setClientToken = function(clientToken){
config.clientToken = clientToken
}
/**
* Retrieve the ID of the selected serverpack.
*
* @param {Boolean} def - optional. If true, the default value will be returned.
* @returns {String} - the ID of the selected serverpack.
*/
exports.getSelectedServer = function(def = false){
return !def ? config.selectedServer : DEFAULT_CONFIG.clientToken
}
/**
* Set the ID of the selected serverpack.
*
* @param {String} serverID - the ID of the new selected serverpack.
*/
exports.setSelectedServer = function(serverID){
config.selectedServer = serverID
}
//TODO Write Authentication Database/Selected Account accessors here
/** /**
* Retrieve the launcher's Discord Client ID. * Retrieve the launcher's Discord Client ID.
*
* @param {Boolean} def - optional. If true, the default value will be returned.
* @returns {String} - the launcher's Discord Client ID.
*/ */
getDiscordClientID(){ exports.getDiscordClientID = function(def = false){
return this.config.discord.clientID return !def ? config.discord.clientID : DEFAULT_CONFIG.discord.clientID
} }
/** /**
* Retrieve the minimum amount of memory for JVM initialization. * Set the launcher's Discord Client ID.
*
* @param {String} clientID - the launcher's new Discord Client ID.
*/ */
getMinRAM(){ exports.setDiscordClientID = function(clientID){
return this.config.settings.java.minRAM config.discord.clientID = clientID
}
// User Configurable Settings
// Java Settings
/**
* Retrieve the minimum amount of memory for JVM initialization. This value
* contains the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
* 1024 MegaBytes, etc.
*
* @param {Boolean} def - optional. If true, the default value will be returned.
* @returns {String} - the minimum amount of memory for JVM initialization.
*/
exports.getMinRAM = function(def = false){
return !def ? config.settings.java.minRAM : DEFAULT_CONFIG.settings.java.minRAM
} }
/** /**
* Retrieve the maximum amount of memory for JVM initialization. * Set the minimum amount of memory for JVM initialization. This value should
* contain the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
* 1024 MegaBytes, etc.
*
* @param {String} minRAM - the new minimum amount of memory for JVM initialization.
*/ */
getMaxRAM(){ exports.setMinRAM = function(minRAM){
return this.config.settings.java.maxRAM config.settings.java.minRAM = minRAM
} }
/** /**
* Retrieve the path of the java executable. * Retrieve the maximum amount of memory for JVM initialization. This value
* contains the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
* 1024 MegaBytes, etc.
*
* @param {Boolean} def - optional. If true, the default value will be returned.
* @returns {String} - the maximum amount of memory for JVM initialization.
*/ */
getJavaExecutable(){ exports.getMaxRAM = function(def = false){
return this.config.settings.java.executable return !def ? config.settings.java.maxRAM : resolveMaxRAM()
}
/**
* Set the maximum amount of memory for JVM initialization. This value should
* contain the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
* 1024 MegaBytes, etc.
*
* @param {String} maxRAM - the new maximum amount of memory for JVM initialization.
*/
exports.setMaxRAM = function(maxRAM){
config.settings.java.maxRAM = maxRAM
}
/**
* Retrieve the path of the Java Executable.
*
* This is a resolved configuration value and defaults to null until externally assigned.
*
* @returns {String} - the path of the Java Executable.
*/
exports.getJavaExecutable = function(){
return config.settings.java.executable
}
/**
* Set the path of the Java Executable.
*
* @param {String} executable - the new path of the Java Executable.
*/
exports.setJavaExecutable = function(executable){
config.settings.java.executable = executable
} }
/** /**
* Retrieve the additional arguments for JVM initialization. Required arguments, * Retrieve the additional arguments for JVM initialization. Required arguments,
* such as memory allocation, will be dynamically resolved. * such as memory allocation, will be dynamically resolved and will not be included
* in this value.
*
* @param {Boolean} def - optional. If true, the default value will be returned.
* @returns {Array.<String>} - an array of the additional arguments for JVM initialization.
*/ */
getJVMOptions(){ exports.getJVMOptions = function(def = false){
return this.config.settings.java.jvmOptions 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.<String>} jvmOptions - an array of the new additional arguments for JVM
* initialization.
*/
exports.setJVMOptions = function(jvmOptions){
config.settings.java.jvmOptions = jvmOptions
}
// Game Settings
/**
* Retrieve the absolute path of the game directory.
*
* @param {Boolean} def - optional. If true, the default value will be returned.
* @returns {String} - the absolute path of the game directory.
*/
exports.getGameDirectory = function(def = false){
return !def ? config.settings.game.directory : DEFAULT_CONFIG.settings.game.directory
}
/**
* Set the absolute path of the game directory.
*
* @param {String} directory - the absolute path of the new game directory.
*/
exports.setGameDirectory = function(directory){
config.settings.game.directory = directory
} }
/** /**
* Retrieve the width of the game window. * 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.
*/ */
getGameWidth(){ exports.getGameWidth = function(def = false){
return this.config.settings.game.resWidth 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 = resWidth
} }
/** /**
* Retrieve the height of the game window. * 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.
*/ */
getGameHeight(){ exports.getGameHeight = function(def = false){
return this.config.settings.game.resHeight 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 = resHeight
} }
/** /**
* Check if the game should be launched in fullscreen mode. * 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.
*/ */
isFullscreen(){ exports.isFullscreen = function(def = false){
return this.config.settings.game.fullscreen return !def ? config.settings.game.fullscreen : DEFAULT_CONFIG.settings.game.fullscreen
} }
/** /**
* Check if auto connect is enabled. * 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.
*/ */
isAutoConnect(){ exports.setFullscreen = function(fullscreen){
return this.config.settings.game.autoConnect 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.isAutoConnect = function(def = false){
return !def ? config.settings.game.autoConnect : DEFAULT_CONFIG.settings.game.autoConnect
} }
module.exports = ConfigManager /**
* 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
}

View File

@ -1,19 +1,24 @@
// Work in progress // Work in progress
const Client = require('discord-rpc') const Client = require('discord-rpc')
const {DEFAULT_CONFIG} = require('./enumerator.js').enum const ConfigManager = require('./configmanager.js')
let rpc let rpc
function initRPC(){ function initRPC(){
rpc = new Client({ transport: 'ipc' }); rpc = new Client({ transport: 'ipc' });
rpc.login(DEFAULT_CONFIG.getDiscordClientID()).catch(error => { rpc.login(ConfigManager.getDiscordClientID()).catch(error => {
if(error.message.includes('ENOENT')) { if(error.message.includes('ENOENT')) {
console.log('Unable to initialize Discord Rich Presence, no client detected.') console.log('Unable to initialize Discord Rich Presence, no client detected.')
} else { } else {
console.log('Unable to initialize Discord Rich Presence: ' + error.message) console.log('Unable to initialize Discord Rich Presence: ' + error.message)
} }
}) })
const activity = {
details: 'Playing on WesterosCraft',
}
} }
function shutdownRPC(){ function shutdownRPC(){

View File

@ -1,9 +0,0 @@
/**
* 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 = {
}

View File

@ -1,22 +1,18 @@
// Note: The following modules CANNOT require enumerator.js
const {AssetGuard} = require('./assetguard.js') const {AssetGuard} = require('./assetguard.js')
const ConfigManager = require('./configmanager.js') const ConfigManager = require('./configmanager.js')
const constants = require('./enumerator.js').enum
const path = require('path') const path = require('path')
console.log('Preloading') console.log('Preloading')
// Load ConfigManager
ConfigManager.load()
// Ensure Distribution is downloaded and cached. // Ensure Distribution is downloaded and cached.
AssetGuard.retrieveDistributionDataSync(false) AssetGuard.retrieveDistributionDataSync(ConfigManager.getGameDirectory(), false)
// TODO: Resolve game directory based on windows, linux, or mac.. // Resolve the selected server if its value has yet to be set.
constants.GAME_DIRECTORY = path.join(__dirname, '..', '..', '..', 'target', 'test', 'mcfiles') if(ConfigManager.getSelectedServer() == null){
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..') console.log('Determining default selected server..')
conf.setSelectedServer(AssetGuard.resolveSelectedServer(constants.GAME_DIRECTORY)) ConfigManager.setSelectedServer(AssetGuard.resolveSelectedServer(ConfigManager.getGameDirectory()))
ConfigManager.save()
} }
constants.DEFAULT_CONFIG = conf

View File

@ -8,7 +8,7 @@
const AdmZip = require('adm-zip') const AdmZip = require('adm-zip')
const {AssetGuard, Library} = require('./assetguard.js') const {AssetGuard, Library} = require('./assetguard.js')
const child_process = require('child_process') const child_process = require('child_process')
const {DEFAULT_CONFIG} = require('./enumerator.js').enum const ConfigManager = require('./configmanager.js')
const fs = require('fs') const fs = require('fs')
const mkpath = require('mkdirp') const mkpath = require('mkdirp')
const path = require('path') const path = require('path')
@ -42,7 +42,7 @@ class ProcessBuilder {
console.log(args) console.log(args)
const child = child_process.spawn(DEFAULT_CONFIG.getJavaExecutable(), args) const child = child_process.spawn(ConfigManager.getJavaExecutable(), args)
child.stdout.on('data', (data) => { child.stdout.on('data', (data) => {
console.log('Minecraft:', data.toString('utf8')) console.log('Minecraft:', data.toString('utf8'))
@ -98,8 +98,8 @@ class ProcessBuilder {
*/ */
constructJVMArguments(mods){ constructJVMArguments(mods){
let args = ['-Xmx' + DEFAULT_CONFIG.getMaxRAM(), let args = ['-Xmx' + ConfigManager.getMaxRAM(),
'-Xms' + DEFAULT_CONFIG.getMinRAM(),, '-Xms' + ConfigManager.getMinRAM(),,
'-Djava.library.path=' + path.join(this.dir, 'natives'), '-Djava.library.path=' + path.join(this.dir, 'natives'),
'-cp', '-cp',
this.classpathArg(mods).join(';'), this.classpathArg(mods).join(';'),
@ -108,7 +108,7 @@ class ProcessBuilder {
// For some reason this will add an undefined value unless // For some reason this will add an undefined value unless
// the delete count is 1. I suspect this is unintended behavior // the delete count is 1. I suspect this is unintended behavior
// by the function.. need to keep an eye on this. // by the function.. need to keep an eye on this.
args.splice(2, 1, ...DEFAULT_CONFIG.getJVMOptions()) args.splice(2, 1, ...ConfigManager.getJVMOptions())
args = args.concat(this._resolveForgeArgs()) args = args.concat(this._resolveForgeArgs())
@ -168,17 +168,17 @@ class ProcessBuilder {
mcArgs.push('absolute:' + this.fmlDir) mcArgs.push('absolute:' + this.fmlDir)
// Prepare game resolution // Prepare game resolution
if(DEFAULT_CONFIG.isFullscreen()){ if(ConfigManager.isFullscreen()){
mcArgs.unshift('--fullscreen') mcArgs.unshift('--fullscreen')
} else { } else {
mcArgs.unshift(DEFAULT_CONFIG.getGameWidth()) mcArgs.unshift(ConfigManager.getGameWidth())
mcArgs.unshift('--width') mcArgs.unshift('--width')
mcArgs.unshift(DEFAULT_CONFIG.getGameHeight()) mcArgs.unshift(ConfigManager.getGameHeight())
mcArgs.unshift('--height') mcArgs.unshift('--height')
} }
// Prepare autoconnect // Prepare autoconnect
if(DEFAULT_CONFIG.isAutoConnect() && this.server.autoconnect){ if(ConfigManager.isAutoConnect() && this.server.autoconnect){
const serverURL = new URL('my://' + this.server.server_ip) const serverURL = new URL('my://' + this.server.server_ip)
mcArgs.unshift(serverURL.hostname) mcArgs.unshift(serverURL.hostname)
mcArgs.unshift('--server') mcArgs.unshift('--server')