Replace distromanager, assetguard is probably broken.

This commit is contained in:
Daniel Scalzi
2023-02-24 21:02:18 -05:00
parent 45630c068c
commit a22bd32cb1
12 changed files with 280 additions and 1124 deletions

View File

@@ -6,6 +6,8 @@ const crypto = require('crypto')
const EventEmitter = require('events')
const fs = require('fs-extra')
const { LoggerUtil } = require('helios-core')
const { DistributionAPI } = require('helios-core/common')
const { Type } = require('helios-distribution-types')
const nodeDiskInfo = require('node-disk-info')
const StreamZip = require('node-stream-zip')
const path = require('path')
@@ -15,7 +17,7 @@ const tar = require('tar-fs')
const zlib = require('zlib')
const ConfigManager = require('./configmanager')
const DistroManager = require('./distromanager')
const { REMOTE_DISTRO_URL } = require('./distromanager')
const isDev = require('./isdev')
const isARM64 = process.arch === 'arm64'
@@ -1538,11 +1540,11 @@ class AssetGuard extends EventEmitter {
const modules = server.getModules()
for(let ob of modules){
const type = ob.getType()
if(type === DistroManager.Types.ForgeHosted || type === DistroManager.Types.Forge){
if(type === Type.ForgeHosted || type === Type.Forge){
if(Util.isForgeGradle3(server.getMinecraftVersion(), ob.getVersion())){
// Read Manifest
for(let sub of ob.getSubModules()){
if(sub.getType() === DistroManager.Types.VersionManifest){
if(sub.getType() === Type.VersionManifest){
resolve(JSON.parse(fs.readFileSync(sub.getArtifact().getPath(), 'utf-8')))
return
}
@@ -1861,9 +1863,15 @@ class AssetGuard extends EventEmitter {
if(!ConfigManager.isLoaded()){
ConfigManager.load()
}
DistroManager.setDevMode(dev)
const dI = await DistroManager.pullLocal()
const api = new DistributionAPI(
ConfigManager.getLauncherDirectory(),
REMOTE_DISTRO_URL,
dev
)
const dI = await api.getDistributionLocalLoadOnly()
// TODO replace all
const server = dI.getServer(serverid)
// Validate Everything

View File

@@ -1,5 +1,6 @@
const fs = require('fs-extra')
const { LoggerUtil } = require('helios-core')
const { mcVersionAtLeast } = require('helios-core/common')
const os = require('os')
const path = require('path')
@@ -64,27 +65,6 @@ function resolveMinRAM(){
return resolveMaxRAM()
}
/**
* TODO Copy pasted, should be in a utility file.
*
* Returns true if the actual version is greater than
* or equal to the desired version.
*
* @param {string} desired The desired version.
* @param {string} actual The actual version.
*/
function mcVersionAtLeast(desired, actual){
const des = desired.split('.')
const act = actual.split('.')
for(let i=0; i<des.length; i++){
if(!(parseInt(act[i]) >= parseInt(des[i]))){
return false
}
}
return true
}
/**
* Three types of values:
* Static = Explicitly declared.

View File

@@ -1,621 +1,13 @@
const fs = require('fs')
const path = require('path')
const request = require('request')
const { LoggerUtil } = require('helios-core')
const { DistributionAPI } = require('helios-core/common')
const ConfigManager = require('./configmanager')
const logger = LoggerUtil.getLogger('DistroManager')
exports.REMOTE_DISTRO_URL = 'http://mc.westeroscraft.com/WesterosCraftLauncher/distribution.json'
/**
* 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)
}
const api = new DistributionAPI(
ConfigManager.getLauncherDirectory(),
exports.REMOTE_DISTRO_URL,
false
)
/**
* 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.classpath, 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, classpath, required, artifact, subModules, serverid) {
this.identifier = id
this.type = type
this.classpath = classpath
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.<Module>} An array of sub modules.
*/
getSubModules(){
return this.subModules
}
/**
* @returns {string} The type of the module.
*/
getType(){
return this.type
}
/**
* @returns {boolean} Whether or not this library should be on the classpath.
*/
getClasspath(){
return this.classpath ?? true
}
}
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.<Module>} 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.<Server>} 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.<DistroIndex>}
*/
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)
return
}
fs.writeFile(distroDest, body, 'utf-8', (err) => {
if(!err){
resolve(data)
return
} else {
reject(err)
return
}
})
} else {
reject(error)
return
}
})
})
}
/**
* @returns {Promise.<DistroIndex>}
*/
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)
return
} else {
reject(err)
return
}
})
})
}
exports.setDevMode = function(value){
if(value){
logger.info('Developer mode enabled.')
logger.info('If you don\'t know what that means, revert immediately.')
} else {
logger.info('Developer mode disabled.')
}
DEV_MODE = value
}
exports.isDevMode = function(){
return DEV_MODE
}
/**
* @returns {DistroIndex}
*/
exports.getDistribution = function(){
return data
}
exports.DistroAPI = api

View File

@@ -4,9 +4,11 @@ const os = require('os')
const path = require('path')
const ConfigManager = require('./configmanager')
const DistroManager = require('./distromanager')
const { DistroAPI } = require('./distromanager')
const LangLoader = require('./langloader')
const { LoggerUtil } = require('helios-core')
// eslint-disable-next-line no-unused-vars
const { HeliosDistribution } = require('helios-core/common')
const logger = LoggerUtil.getLogger('Preloader')
@@ -18,13 +20,17 @@ ConfigManager.load()
// Load Strings
LangLoader.loadLanguage('en_US')
/**
*
* @param {HeliosDistribution} data
*/
function onDistroLoad(data){
if(data != null){
// Resolve the selected server if its value has yet to be set.
if(ConfigManager.getSelectedServer() == null || data.getServer(ConfigManager.getSelectedServer()) == null){
if(ConfigManager.getSelectedServer() == null || data.getServerById(ConfigManager.getSelectedServer()) == null){
logger.info('Determining default selected server..')
ConfigManager.setSelectedServer(data.getMainServer().getID())
ConfigManager.setSelectedServer(data.getMainServer().rawServer.id)
ConfigManager.save()
}
}
@@ -32,35 +38,20 @@ function onDistroLoad(data){
}
// Ensure Distribution is downloaded and cached.
DistroManager.pullRemote().then((data) => {
logger.info('Loaded distribution index.')
onDistroLoad(data)
}).catch((err) => {
logger.info('Failed to load distribution index.')
logger.error(err)
logger.info('Attempting to load an older version of the distribution index.')
// Try getting a local copy, better than nothing.
DistroManager.pullLocal().then((data) => {
logger.info('Successfully loaded an older version of the distribution index.')
onDistroLoad(data)
}).catch((err) => {
DistroAPI.getDistribution()
.then(heliosDistro => {
logger.info('Loaded distribution index.')
onDistroLoad(heliosDistro)
})
.catch(err => {
logger.info('Failed to load an older version of the distribution index.')
logger.info('Application cannot run.')
logger.error(err)
onDistroLoad(null)
})
})
// Clean up temp dir incase previous launches ended unexpectedly.
fs.remove(path.join(os.tmpdir(), ConfigManager.getTempNativeFolder()), (err) => {
if(err){

View File

@@ -3,13 +3,13 @@ const child_process = require('child_process')
const crypto = require('crypto')
const fs = require('fs-extra')
const { LoggerUtil } = require('helios-core')
const { getMojangOS, isLibraryCompatible, mcVersionAtLeast } = require('helios-core/common')
const { Type } = require('helios-distribution-types')
const os = require('os')
const path = require('path')
const { URL } = require('url')
const { Util, Library } = require('./assetguard')
const ConfigManager = require('./configmanager')
const DistroManager = require('./distromanager')
const logger = LoggerUtil.getLogger('ProcessBuilder')
@@ -44,7 +44,7 @@ class ProcessBuilder {
const modObj = this.resolveModConfiguration(ConfigManager.getModConfiguration(this.server.getID()).mods, this.server.getModules())
// Mod list below 1.13
if(!Util.mcVersionAtLeast('1.13', this.server.getMinecraftVersion())){
if(!mcVersionAtLeast('1.13', this.server.getMinecraftVersion())){
this.constructJSONModList('forge', modObj.fMods, true)
if(this.usingLiteLoader){
this.constructJSONModList('liteloader', modObj.lMods, true)
@@ -54,7 +54,7 @@ class ProcessBuilder {
const uberModArr = modObj.fMods.concat(modObj.lMods)
let args = this.constructJVMArguments(uberModArr, tempNativePath)
if(Util.mcVersionAtLeast('1.13', this.server.getMinecraftVersion())){
if(mcVersionAtLeast('1.13', this.server.getMinecraftVersion())){
//args = args.concat(this.constructModArguments(modObj.fMods))
args = args.concat(this.constructModList(modObj.fMods))
}
@@ -122,7 +122,7 @@ class ProcessBuilder {
* @returns {boolean} True if the mod is enabled, false otherwise.
*/
static isModEnabled(modCfg, required = null){
return modCfg != null ? ((typeof modCfg === 'boolean' && modCfg) || (typeof modCfg === 'object' && (typeof modCfg.value !== 'undefined' ? modCfg.value : true))) : required != null ? required.isDefault() : true
return modCfg != null ? ((typeof modCfg === 'boolean' && modCfg) || (typeof modCfg === 'object' && (typeof modCfg.value !== 'undefined' ? modCfg.value : true))) : required != null ? required.def : true
}
/**
@@ -132,20 +132,20 @@ class ProcessBuilder {
* mod. It must not be declared as a submodule.
*/
setupLiteLoader(){
for(let ll of this.server.getModules()){
if(ll.getType() === DistroManager.Types.LiteLoader){
if(!ll.getRequired().isRequired()){
const modCfg = ConfigManager.getModConfiguration(this.server.getID()).mods
if(ProcessBuilder.isModEnabled(modCfg[ll.getVersionlessID()], ll.getRequired())){
if(fs.existsSync(ll.getArtifact().getPath())){
for(let ll of this.server.modules){
if(ll.rawModule.type === Type.LiteLoader){
if(!ll.getRequired().value){
const modCfg = ConfigManager.getModConfiguration(this.server.rawServer.id).mods
if(ProcessBuilder.isModEnabled(modCfg[ll.getVersionlessMavenIdentifier()], ll.getRequired())){
if(fs.existsSync(ll.localPath)){
this.usingLiteLoader = true
this.llPath = ll.getArtifact().getPath()
this.llPath = ll.localPath
}
}
} else {
if(fs.existsSync(ll.getArtifact().getPath())){
if(fs.existsSync(ll.localPath)){
this.usingLiteLoader = true
this.llPath = ll.getArtifact().getPath()
this.llPath = ll.localPath
}
}
}
@@ -166,20 +166,20 @@ class ProcessBuilder {
let lMods = []
for(let mdl of mdls){
const type = mdl.getType()
if(type === DistroManager.Types.ForgeMod || type === DistroManager.Types.LiteMod || type === DistroManager.Types.LiteLoader){
const o = !mdl.getRequired().isRequired()
const e = ProcessBuilder.isModEnabled(modCfg[mdl.getVersionlessID()], mdl.getRequired())
const type = mdl.rawModule.type
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){
const o = !mdl.getRequired().value
const e = ProcessBuilder.isModEnabled(modCfg[mdl.getVersionlessMavenIdentifier()], mdl.getRequired())
if(!o || (o && e)){
if(mdl.hasSubModules()){
const v = this.resolveModConfiguration(modCfg[mdl.getVersionlessID()].mods, mdl.getSubModules())
if(mdl.subModules.length > 0){
const v = this.resolveModConfiguration(modCfg[mdl.getVersionlessMavenIdentifier()].mods, mdl.subModules)
fMods = fMods.concat(v.fMods)
lMods = lMods.concat(v.lMods)
if(mdl.type === DistroManager.Types.LiteLoader){
if(mdl.type === Type.LiteLoader){
continue
}
}
if(mdl.type === DistroManager.Types.ForgeMod){
if(mdl.type === Type.ForgeMod){
fMods.push(mdl)
} else {
lMods.push(mdl)
@@ -326,7 +326,7 @@ class ProcessBuilder {
* @returns {Array.<string>} An array containing the full JVM arguments for this process.
*/
constructJVMArguments(mods, tempNativePath){
if(Util.mcVersionAtLeast('1.13', this.server.getMinecraftVersion())){
if(mcVersionAtLeast('1.13', this.server.getMinecraftVersion())){
return this._constructJVMArguments113(mods, tempNativePath)
} else {
return this._constructJVMArguments112(mods, tempNativePath)
@@ -421,7 +421,7 @@ class ProcessBuilder {
let checksum = 0
for(let rule of args[i].rules){
if(rule.os != null){
if(rule.os.name === Library.mojangFriendlyOS()
if(rule.os.name === getMojangOS()
&& (rule.os.version == null || new RegExp(rule.os.version).test(os.release))){
if(rule.action === 'allow'){
checksum++
@@ -523,7 +523,7 @@ class ProcessBuilder {
// Autoconnect
let isAutoconnectBroken
try {
isAutoconnectBroken = Util.isAutoconnectBroken(this.forgeData.id.split('-')[2])
isAutoconnectBroken = ProcessBuilder.isAutoconnectBroken(this.forgeData.id.split('-')[2])
} catch(err) {
logger.error(err)
logger.error('Forge version format changed.. assuming autoconnect works.')
@@ -668,7 +668,7 @@ class ProcessBuilder {
classpathArg(mods, tempNativePath){
let cpArgs = []
if(!Util.mcVersionAtLeast('1.17', this.server.getMinecraftVersion())) {
if(!mcVersionAtLeast('1.17', this.server.getMinecraftVersion())) {
// Add the version.jar to the classpath.
// Must not be added to the classpath for Forge 1.17+.
const version = this.versionData.id
@@ -714,13 +714,13 @@ class ProcessBuilder {
fs.ensureDirSync(tempNativePath)
for(let i=0; i<libArr.length; i++){
const lib = libArr[i]
if(Library.validateRules(lib.rules, lib.natives)){
if(isLibraryCompatible(lib.rules, lib.natives)){
// Pre-1.19 has a natives object.
if(lib.natives != null) {
// Extract the native library.
const exclusionArr = lib.extract != null ? lib.extract.exclude : ['META-INF/']
const artifact = lib.downloads.classifiers[lib.natives[Library.mojangFriendlyOS()].replace('${arch}', process.arch.replace('x', ''))]
const artifact = lib.downloads.classifiers[lib.natives[getMojangOS()].replace('${arch}', process.arch.replace('x', ''))]
// Location of native zip.
const to = path.join(this.libPath, artifact.path)
@@ -832,7 +832,7 @@ class ProcessBuilder {
// Locate Forge/Libraries
for(let mdl of mdls){
const type = mdl.getType()
if(type === DistroManager.Types.ForgeHosted || type === DistroManager.Types.Library){
if(type === Type.ForgeHosted || type === Type.Library){
libs[mdl.getVersionlessID()] = mdl.getArtifact().getPath()
if(mdl.hasSubModules()){
const res = this._resolveModuleLibraries(mdl)
@@ -868,7 +868,7 @@ class ProcessBuilder {
}
let libs = []
for(let sm of mdl.getSubModules()){
if(sm.getType() === DistroManager.Types.Library){
if(sm.getType() === Type.Library){
if(sm.getClasspath()) {
libs.push(sm.getArtifact().getPath())
@@ -886,6 +886,24 @@ class ProcessBuilder {
return libs
}
static isAutoconnectBroken(forgeVersion) {
const minWorking = [31, 2, 15]
const verSplit = forgeVersion.split('.').map(v => Number(v))
if(verSplit[0] === 31) {
for(let i=0; i<minWorking.length; i++) {
if(verSplit[i] > minWorking[i]) {
return false
} else if(verSplit[i] < minWorking[i]) {
return true
}
}
}
return false
}
}
module.exports = ProcessBuilder

View File

@@ -10,8 +10,7 @@ const { MojangRestAPI, getServerStatus } = require('helios-core/mojang')
// Internal Requirements
const DiscordWrapper = require('./assets/js/discordwrapper')
const ProcessBuilder = require('./assets/js/processbuilder')
const { Util } = require('./assets/js/assetguard')
const { RestResponseStatus, isDisplayableError } = require('helios-core/common')
const { RestResponseStatus, isDisplayableError, mcVersionAtLeast } = require('helios-core/common')
const { stdout } = require('process')
// Launch Elements
@@ -86,9 +85,9 @@ function setLaunchEnabled(val){
}
// Bind launch button
document.getElementById('launch_button').addEventListener('click', function(e){
document.getElementById('launch_button').addEventListener('click', async (e) => {
loggerLanding.info('Launching game..')
const mcVersion = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
const mcVersion = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer()).rawServer.minecraftVersion
const jExe = ConfigManager.getJavaExecutable(ConfigManager.getSelectedServer())
if(jExe == null){
asyncSystemScan(mcVersion)
@@ -111,14 +110,14 @@ document.getElementById('launch_button').addEventListener('click', function(e){
})
// Bind settings button
document.getElementById('settingsMediaButton').onclick = (e) => {
prepareSettings()
document.getElementById('settingsMediaButton').onclick = async e => {
await prepareSettings()
switchView(getCurrentView(), VIEWS.settings)
}
// Bind avatar overlay button.
document.getElementById('avatarOverlay').onclick = (e) => {
prepareSettings()
document.getElementById('avatarOverlay').onclick = async e => {
await prepareSettings()
switchView(getCurrentView(), VIEWS.settings, 500, 500, () => {
settingsNavItemListener(document.getElementById('settingsNavAccount'), false)
})
@@ -144,9 +143,9 @@ function updateSelectedServer(serv){
if(getCurrentView() === VIEWS.settings){
fullSettingsSave()
}
ConfigManager.setSelectedServer(serv != null ? serv.getID() : null)
ConfigManager.setSelectedServer(serv != null ? serv.rawServer.id : null)
ConfigManager.save()
server_selection_button.innerHTML = '\u2022 ' + (serv != null ? serv.getName() : 'No Server Selected')
server_selection_button.innerHTML = '\u2022 ' + (serv != null ? serv.rawServer.name : 'No Server Selected')
if(getCurrentView() === VIEWS.settings){
animateSettingsTabRefresh()
}
@@ -154,9 +153,9 @@ function updateSelectedServer(serv){
}
// Real text is set in uibinder.js on distributionIndexDone.
server_selection_button.innerHTML = '\u2022 Loading..'
server_selection_button.onclick = (e) => {
server_selection_button.onclick = async e => {
e.target.blur()
toggleServerSelection(true)
await toggleServerSelection(true)
}
// Update Mojang Status Color
@@ -220,17 +219,16 @@ const refreshMojangStatuses = async function(){
document.getElementById('mojang_status_icon').style.color = MojangRestAPI.statusToHex(status)
}
const refreshServerStatus = async function(fade = false){
const refreshServerStatus = async (fade = false) => {
loggerLanding.info('Refreshing Server Status')
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
const serv = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer())
let pLabel = 'SERVER'
let pVal = 'OFFLINE'
try {
const serverURL = new URL('my://' + serv.getAddress())
const servStat = await getServerStatus(47, serverURL.hostname, Number(serverURL.port))
const servStat = await getServerStatus(47, serv.hostname, serv.port)
console.log(servStat)
pLabel = 'PLAYERS'
pVal = servStat.players.online + '/' + servStat.players.max
@@ -318,9 +316,9 @@ function asyncSystemScan(mcVersion, launchAfter = true){
console.log(`\x1b[31m[SysAEx]\x1b[0m ${data}`)
})
const javaVer = Util.mcVersionAtLeast('1.17', mcVersion) ? '17' : '8'
const javaVer = mcVersionAtLeast('1.17', mcVersion) ? '17' : '8'
sysAEx.on('message', (m) => {
sysAEx.on('message', async (m) => {
if(m.context === 'validateJava'){
if(m.result == null){
@@ -368,7 +366,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){
// We need to make sure that the updated value is on the settings UI.
// Just incase the settings UI is already open.
settingsJavaExecVal.value = m.result
populateJavaExecDetails(settingsJavaExecVal.value)
await populateJavaExecDetails(settingsJavaExecVal.value)
if(launchAfter){
dlAsync()
@@ -534,7 +532,7 @@ function dlAsync(login = true){
})
// Establish communications between the AssetExec and current process.
aEx.on('message', (m) => {
aEx.on('message', async (m) => {
if(m.context === 'validate'){
switch(m.data){
@@ -710,9 +708,9 @@ function dlAsync(login = true){
setLaunchDetails('Done. Enjoy the server!')
// Init Discord Hook
const distro = DistroManager.getDistribution()
if(distro.discord != null && serv.discord != null){
DiscordWrapper.initRPC(distro.discord, serv.discord)
const distro = await DistroAPI.getDistribution()
if(distro.rawDistribution.discord != null && serv.rawServerdiscord != null){
DiscordWrapper.initRPC(distro.rawDistribution.discord, serv.rawServer.discord)
hasRPC = true
proc.on('close', (code, signal) => {
loggerLaunchSuite.info('Shutting down Discord Rich Presence..')
@@ -741,29 +739,19 @@ function dlAsync(login = true){
// Validate Forge files.
setLaunchDetails('Loading server information..')
refreshDistributionIndex(true, (data) => {
onDistroRefresh(data)
serv = data.getServer(ConfigManager.getSelectedServer())
aEx.send({task: 'execute', function: 'validateEverything', argsArr: [ConfigManager.getSelectedServer(), DistroManager.isDevMode()]})
}, (err) => {
loggerLaunchSuite.info('Error while fetching a fresh copy of the distribution index.', err)
refreshDistributionIndex(false, (data) => {
DistroAPI.refreshDistributionOrFallback()
.then(data => {
onDistroRefresh(data)
serv = data.getServer(ConfigManager.getSelectedServer())
aEx.send({task: 'execute', function: 'validateEverything', argsArr: [ConfigManager.getSelectedServer(), DistroManager.isDevMode()]})
}, (err) => {
loggerLaunchSuite.error('Unable to refresh distribution index.', err)
if(DistroManager.getDistribution() == null){
showLaunchFailure('Fatal Error', 'Could not load a copy of the distribution index. See the console (CTRL + Shift + i) for more details.')
// Disconnect from AssetExec
aEx.disconnect()
} else {
serv = data.getServer(ConfigManager.getSelectedServer())
aEx.send({task: 'execute', function: 'validateEverything', argsArr: [ConfigManager.getSelectedServer(), DistroManager.isDevMode()]})
}
serv = data.getServerById(ConfigManager.getSelectedServer())
aEx.send({task: 'execute', function: 'validateEverything', argsArr: [ConfigManager.getSelectedServer(), DistroAPI.isDevMode()]})
})
.catch(err => {
loggerLaunchSuite.error('Unable to refresh distribution index.', err)
showLaunchFailure('Fatal Error', 'Could not load a copy of the distribution index. See the console (CTRL + Shift + i) for more details.')
// Disconnect from AssetExec
aEx.disconnect()
})
})
}
/**
@@ -1089,10 +1077,13 @@ function displayArticle(articleObject, index){
* Load news information from the RSS feed specified in the
* distribution index.
*/
function loadNews(){
return new Promise((resolve, reject) => {
const distroData = DistroManager.getDistribution()
const newsFeed = distroData.getRSS()
async function loadNews(){
const distroData = await DistroAPI.getDistribution()
const promise = new Promise((resolve, reject) => {
const newsFeed = distroData.rawDistribution.rss
const newsHost = new URL(newsFeed).origin + '/'
$.ajax({
url: newsFeed,
@@ -1147,4 +1138,6 @@ function loadNews(){
})
})
})
return await promise
}

View File

@@ -193,10 +193,10 @@ loginButton.addEventListener('click', () => {
$('.circle-loader').toggleClass('load-complete')
$('.checkmark').toggle()
setTimeout(() => {
switchView(VIEWS.login, loginViewOnSuccess, 500, 500, () => {
switchView(VIEWS.login, loginViewOnSuccess, 500, 500, async () => {
// Temporary workaround
if(loginViewOnSuccess === VIEWS.settings){
prepareSettings()
await prepareSettings()
}
loginViewOnSuccess = VIEWS.landing // Reset this for good measure.
loginCancelEnabled(false) // Reset this for good measure.

View File

@@ -117,8 +117,8 @@ function toggleOverlay(toggleState, dismissable = false, content = 'overlayConte
}
}
function toggleServerSelection(toggleState){
prepareServerSelectionList()
async function toggleServerSelection(toggleState){
await prepareServerSelectionList()
toggleOverlay(toggleState, true, 'serverSelectContent')
}
@@ -171,11 +171,11 @@ function setDismissHandler(handler){
/* Server Select View */
document.getElementById('serverSelectConfirm').addEventListener('click', () => {
document.getElementById('serverSelectConfirm').addEventListener('click', async () => {
const listings = document.getElementsByClassName('serverListing')
for(let i=0; i<listings.length; i++){
if(listings[i].hasAttribute('selected')){
const serv = DistroManager.getDistribution().getServer(listings[i].getAttribute('servid'))
const serv = (await DistroAPI.getDistribution()).getServerById(listings[i].getAttribute('servid'))
updateSelectedServer(serv)
refreshServerStatus(true)
toggleOverlay(false)
@@ -184,13 +184,13 @@ document.getElementById('serverSelectConfirm').addEventListener('click', () => {
}
// None are selected? Not possible right? Meh, handle it.
if(listings.length > 0){
const serv = DistroManager.getDistribution().getServer(listings[i].getAttribute('servid'))
const serv = (await DistroAPI.getDistribution()).getServerById(listings[i].getAttribute('servid'))
updateSelectedServer(serv)
toggleOverlay(false)
}
})
document.getElementById('accountSelectConfirm').addEventListener('click', () => {
document.getElementById('accountSelectConfirm').addEventListener('click', async () => {
const listings = document.getElementsByClassName('accountListing')
for(let i=0; i<listings.length; i++){
if(listings[i].hasAttribute('selected')){
@@ -198,7 +198,7 @@ document.getElementById('accountSelectConfirm').addEventListener('click', () =>
ConfigManager.save()
updateSelectedAccount(authAcc)
if(getCurrentView() === VIEWS.settings) {
prepareSettings()
await prepareSettings()
}
toggleOverlay(false)
validateSelectedAccount()
@@ -211,7 +211,7 @@ document.getElementById('accountSelectConfirm').addEventListener('click', () =>
ConfigManager.save()
updateSelectedAccount(authAcc)
if(getCurrentView() === VIEWS.settings) {
prepareSettings()
await prepareSettings()
}
toggleOverlay(false)
validateSelectedAccount()
@@ -267,21 +267,21 @@ function setAccountListingHandlers(){
})
}
function populateServerListings(){
const distro = DistroManager.getDistribution()
async function populateServerListings(){
const distro = await DistroAPI.getDistribution()
const giaSel = ConfigManager.getSelectedServer()
const servers = distro.getServers()
const servers = distro.servers
let htmlString = ''
for(const serv of servers){
htmlString += `<button class="serverListing" servid="${serv.getID()}" ${serv.getID() === giaSel ? 'selected' : ''}>
<img class="serverListingImg" src="${serv.getIcon()}"/>
htmlString += `<button class="serverListing" servid="${serv.rawServer.id}" ${serv.rawServer.id === giaSel ? 'selected' : ''}>
<img class="serverListingImg" src="${serv.rawServer.icon}"/>
<div class="serverListingDetails">
<span class="serverListingName">${serv.getName()}</span>
<span class="serverListingDescription">${serv.getDescription()}</span>
<span class="serverListingName">${serv.rawServer.name}</span>
<span class="serverListingDescription">${serv.rawServer.description}</span>
<div class="serverListingInfo">
<div class="serverListingVersion">${serv.getMinecraftVersion()}</div>
<div class="serverListingRevision">${serv.getVersion()}</div>
${serv.isMainServer() ? `<div class="serverListingStarWrapper">
<div class="serverListingVersion">${serv.rawServer.minecraftVersion}</div>
<div class="serverListingRevision">${serv.rawServer.version}</div>
${serv.rawServer.mainServer ? `<div class="serverListingStarWrapper">
<svg id="Layer_1" viewBox="0 0 107.45 104.74" width="20px" height="20px">
<defs>
<style>.cls-1{fill:#fff;}.cls-2{fill:none;stroke:#fff;stroke-miterlimit:10;}</style>
@@ -313,8 +313,8 @@ function populateAccountListings(){
}
function prepareServerSelectionList(){
populateServerListings()
async function prepareServerSelectionList(){
await populateServerListings()
setServerListingHandlers()
}

View File

@@ -69,7 +69,7 @@ function bindFileSelectors(){
if(!res.canceled) {
ele.previousElementSibling.value = res.filePaths[0]
if(isJavaExecSel) {
populateJavaExecDetails(ele.previousElementSibling.value)
await populateJavaExecDetails(ele.previousElementSibling.value)
}
}
}
@@ -123,9 +123,10 @@ function initSettingsValidators(){
/**
* Load configuration values onto the UI. This is an automated process.
*/
function initSettingsValues(){
async function initSettingsValues(){
const sEls = document.getElementById('settingsContainer').querySelectorAll('[cValue]')
Array.from(sEls).map((v, index, arr) => {
for(const v of sEls) {
const cVal = v.getAttribute('cValue')
const serverDependent = v.hasAttribute('serverDependent') // Means the first argument is the server id.
const gFn = ConfigManager['get' + cVal]
@@ -139,7 +140,7 @@ function initSettingsValues(){
// Special Conditions
if(cVal === 'JavaExecutable'){
v.value = gFn.apply(null, gFnOpts)
populateJavaExecDetails(v.value)
await populateJavaExecDetails(v.value)
} else if (cVal === 'DataDirectory'){
v.value = gFn.apply(null, gFnOpts)
} else if(cVal === 'JVMOptions'){
@@ -168,8 +169,8 @@ function initSettingsValues(){
}
}
}
}
})
}
/**
@@ -416,8 +417,8 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => {
const authCode = queryMap.code
AuthManager.addMicrosoftAccount(authCode).then(value => {
updateSelectedAccount(value)
switchView(getCurrentView(), viewOnClose, 500, 500, () => {
prepareSettings()
switchView(getCurrentView(), viewOnClose, 500, 500, async () => {
await prepareSettings()
})
})
.catch((displayableError) => {
@@ -713,13 +714,13 @@ const settingsModsContainer = document.getElementById('settingsModsContainer')
/**
* Resolve and update the mods on the UI.
*/
function resolveModsForUI(){
async function resolveModsForUI(){
const serv = ConfigManager.getSelectedServer()
const distro = DistroManager.getDistribution()
const distro = await DistroAPI.getDistribution()
const servConf = ConfigManager.getModConfiguration(serv)
const modStr = parseModulesForUI(distro.getServer(serv).getModules(), false, servConf.mods)
const modStr = parseModulesForUI(distro.getServerById(serv).modules, false, servConf.mods)
document.getElementById('settingsReqModsContent').innerHTML = modStr.reqMods
document.getElementById('settingsOptModsContent').innerHTML = modStr.optMods
@@ -739,17 +740,17 @@ function parseModulesForUI(mdls, submodules, servConf){
for(const mdl of mdls){
if(mdl.getType() === DistroManager.Types.ForgeMod || mdl.getType() === DistroManager.Types.LiteMod || mdl.getType() === DistroManager.Types.LiteLoader){
if(mdl.rawModule.type === Type.ForgeMod || mdl.rawModule.type === Type.LiteMod || mdl.rawModule.type === Type.LiteLoader){
if(mdl.getRequired().isRequired()){
if(mdl.getRequired().value){
reqMods += `<div id="${mdl.getVersionlessID()}" class="settingsBaseMod settings${submodules ? 'Sub' : ''}Mod" enabled>
reqMods += `<div id="${mdl.getVersionlessMavenIdentifier()}" class="settingsBaseMod settings${submodules ? 'Sub' : ''}Mod" enabled>
<div class="settingsModContent">
<div class="settingsModMainWrapper">
<div class="settingsModStatus"></div>
<div class="settingsModDetails">
<span class="settingsModName">${mdl.getName()}</span>
<span class="settingsModVersion">v${mdl.getVersion()}</span>
<span class="settingsModName">${mdl.rawModule.name}</span>
<span class="settingsModVersion">v${mdl.mavenComponents.version}</span>
</div>
</div>
<label class="toggleSwitch" reqmod>
@@ -757,32 +758,32 @@ function parseModulesForUI(mdls, submodules, servConf){
<span class="toggleSwitchSlider"></span>
</label>
</div>
${mdl.hasSubModules() ? `<div class="settingsSubModContainer">
${Object.values(parseModulesForUI(mdl.getSubModules(), true, servConf[mdl.getVersionlessID()])).join('')}
${mdl.subModules.length > 0 ? `<div class="settingsSubModContainer">
${Object.values(parseModulesForUI(mdl.subModules, true, servConf[mdl.getVersionlessMavenIdentifier()])).join('')}
</div>` : ''}
</div>`
} else {
const conf = servConf[mdl.getVersionlessID()]
const conf = servConf[mdl.getVersionlessMavenIdentifier()]
const val = typeof conf === 'object' ? conf.value : conf
optMods += `<div id="${mdl.getVersionlessID()}" class="settingsBaseMod settings${submodules ? 'Sub' : ''}Mod" ${val ? 'enabled' : ''}>
optMods += `<div id="${mdl.getVersionlessMavenIdentifier()}" class="settingsBaseMod settings${submodules ? 'Sub' : ''}Mod" ${val ? 'enabled' : ''}>
<div class="settingsModContent">
<div class="settingsModMainWrapper">
<div class="settingsModStatus"></div>
<div class="settingsModDetails">
<span class="settingsModName">${mdl.getName()}</span>
<span class="settingsModVersion">v${mdl.getVersion()}</span>
<span class="settingsModName">${mdl.rawModule.name}</span>
<span class="settingsModVersion">v${mdl.mavenComponents.version}</span>
</div>
</div>
<label class="toggleSwitch">
<input type="checkbox" formod="${mdl.getVersionlessID()}" ${val ? 'checked' : ''}>
<input type="checkbox" formod="${mdl.getVersionlessMavenIdentifier()}" ${val ? 'checked' : ''}>
<span class="toggleSwitchSlider"></span>
</label>
</div>
${mdl.hasSubModules() ? `<div class="settingsSubModContainer">
${Object.values(parseModulesForUI(mdl.getSubModules(), true, conf.mods)).join('')}
${mdl.subModules.length > 0 ? `<div class="settingsSubModContainer">
${Object.values(parseModulesForUI(mdl.subModules, true, conf.mods)).join('')}
</div>` : ''}
</div>`
@@ -858,10 +859,10 @@ let CACHE_DROPIN_MODS
* Resolve any located drop-in mods for this server and
* populate the results onto the UI.
*/
function resolveDropinModsForUI(){
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
CACHE_SETTINGS_MODS_DIR = path.join(ConfigManager.getInstanceDirectory(), serv.getID(), 'mods')
CACHE_DROPIN_MODS = DropinModUtil.scanForDropinMods(CACHE_SETTINGS_MODS_DIR, serv.getMinecraftVersion())
async function resolveDropinModsForUI(){
const serv = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer())
CACHE_SETTINGS_MODS_DIR = path.join(ConfigManager.getInstanceDirectory(), serv.rawServer.id, 'mods')
CACHE_DROPIN_MODS = DropinModUtil.scanForDropinMods(CACHE_SETTINGS_MODS_DIR, serv.rawServer.minecraftVersion)
let dropinMods = ''
@@ -934,12 +935,12 @@ function bindDropinModFileSystemButton(){
fsBtn.removeAttribute('drag')
}
fsBtn.ondrop = e => {
fsBtn.ondrop = async e => {
fsBtn.removeAttribute('drag')
e.preventDefault()
DropinModUtil.addDropinMods(e.dataTransfer.files, CACHE_SETTINGS_MODS_DIR)
reloadDropinMods()
await reloadDropinMods()
}
}
@@ -971,18 +972,18 @@ function saveDropinModConfiguration(){
// Refresh the drop-in mods when F5 is pressed.
// Only active on the mods tab.
document.addEventListener('keydown', (e) => {
document.addEventListener('keydown', async (e) => {
if(getCurrentView() === VIEWS.settings && selectedSettingsTab === 'settingsTabMods'){
if(e.key === 'F5'){
reloadDropinMods()
await reloadDropinMods()
saveShaderpackSettings()
resolveShaderpacksForUI()
await resolveShaderpacksForUI()
}
}
})
function reloadDropinMods(){
resolveDropinModsForUI()
async function reloadDropinMods(){
await resolveDropinModsForUI()
bindDropinModsRemoveButton()
bindDropinModFileSystemButton()
bindModsToggleSwitch()
@@ -997,9 +998,9 @@ let CACHE_SELECTED_SHADERPACK
/**
* Load shaderpack information.
*/
function resolveShaderpacksForUI(){
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
CACHE_SETTINGS_INSTANCE_DIR = path.join(ConfigManager.getInstanceDirectory(), serv.getID())
async function resolveShaderpacksForUI(){
const serv = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer())
CACHE_SETTINGS_INSTANCE_DIR = path.join(ConfigManager.getInstanceDirectory(), serv.rawServer.id)
CACHE_SHADERPACKS = DropinModUtil.scanForShaderpacks(CACHE_SETTINGS_INSTANCE_DIR)
CACHE_SELECTED_SHADERPACK = DropinModUtil.getEnabledShaderpack(CACHE_SETTINGS_INSTANCE_DIR)
@@ -1058,13 +1059,13 @@ function bindShaderpackButton() {
spBtn.removeAttribute('drag')
}
spBtn.ondrop = e => {
spBtn.ondrop = async e => {
spBtn.removeAttribute('drag')
e.preventDefault()
DropinModUtil.addShaderpacks(e.dataTransfer.files, CACHE_SETTINGS_INSTANCE_DIR)
saveShaderpackSettings()
resolveShaderpacksForUI()
await resolveShaderpacksForUI()
}
}
@@ -1073,19 +1074,19 @@ function bindShaderpackButton() {
/**
* Load the currently selected server information onto the mods tab.
*/
function loadSelectedServerOnModsTab(){
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
async function loadSelectedServerOnModsTab(){
const serv = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer())
for(const el of document.getElementsByClassName('settingsSelServContent')) {
el.innerHTML = `
<img class="serverListingImg" src="${serv.getIcon()}"/>
<img class="serverListingImg" src="${serv.rawServer.icon}"/>
<div class="serverListingDetails">
<span class="serverListingName">${serv.getName()}</span>
<span class="serverListingDescription">${serv.getDescription()}</span>
<span class="serverListingName">${serv.rawServer.name}</span>
<span class="serverListingDescription">${serv.rawServer.description}</span>
<div class="serverListingInfo">
<div class="serverListingVersion">${serv.getMinecraftVersion()}</div>
<div class="serverListingRevision">${serv.getVersion()}</div>
${serv.isMainServer() ? `<div class="serverListingStarWrapper">
<div class="serverListingVersion">${serv.rawServer.minecraftVersion}</div>
<div class="serverListingRevision">${serv.rawServer.version}</div>
${serv.rawServer.mainServer ? `<div class="serverListingStarWrapper">
<svg id="Layer_1" viewBox="0 0 107.45 104.74" width="20px" height="20px">
<defs>
<style>.cls-1{fill:#fff;}.cls-2{fill:none;stroke:#fff;stroke-miterlimit:10;}</style>
@@ -1103,9 +1104,9 @@ function loadSelectedServerOnModsTab(){
// Bind functionality to the server switch button.
Array.from(document.getElementsByClassName('settingsSwitchServerButton')).forEach(el => {
el.addEventListener('click', (e) => {
el.addEventListener('click', async e => {
e.target.blur()
toggleServerSelection(true)
await toggleServerSelection(true)
})
})
@@ -1123,8 +1124,8 @@ function saveAllModConfigurations(){
* server is changed.
*/
function animateSettingsTabRefresh(){
$(`#${selectedSettingsTab}`).fadeOut(500, () => {
prepareSettings()
$(`#${selectedSettingsTab}`).fadeOut(500, async () => {
await prepareSettings()
$(`#${selectedSettingsTab}`).fadeIn(500)
})
}
@@ -1132,15 +1133,15 @@ function animateSettingsTabRefresh(){
/**
* Prepare the Mods tab for display.
*/
function prepareModsTab(first){
resolveModsForUI()
resolveDropinModsForUI()
resolveShaderpacksForUI()
async function prepareModsTab(first){
await resolveModsForUI()
await resolveDropinModsForUI()
await resolveShaderpacksForUI()
bindDropinModsRemoveButton()
bindDropinModFileSystemButton()
bindShaderpackButton()
bindModsToggleSwitch()
loadSelectedServerOnModsTab()
await loadSelectedServerOnModsTab()
}
/**
@@ -1348,8 +1349,8 @@ function populateMemoryStatus(){
*
* @param {string} execPath The executable path to populate against.
*/
function populateJavaExecDetails(execPath){
const jg = new JavaGuard(DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion())
async function populateJavaExecDetails(execPath){
const jg = new JavaGuard((await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer()).rawServer.minecraftVersion)
jg._validateJavaBinary(execPath).then(v => {
if(v.valid){
const vendor = v.vendor != null ? ` (${v.vendor})` : ''
@@ -1364,18 +1365,18 @@ function populateJavaExecDetails(execPath){
})
}
function populateJavaReqDesc() {
const mcVer = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
if(Util.mcVersionAtLeast('1.17', mcVer)) {
async function populateJavaReqDesc() {
const mcVer = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer()).rawServer.minecraftVersion
if(mcVersionAtLeast('1.17', mcVer)) {
settingsJavaReqDesc.innerHTML = 'Requires Java 17 x64.'
} else {
settingsJavaReqDesc.innerHTML = 'Requires Java 8 x64.'
}
}
function populateJvmOptsLink() {
const mcVer = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
if(Util.mcVersionAtLeast('1.17', mcVer)) {
async function populateJvmOptsLink() {
const mcVer = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer()).rawServer.minecraftVersion
if(mcVersionAtLeast('1.17', mcVer)) {
settingsJvmOptsLink.innerHTML = 'Available Options for Java 17 (HotSpot VM)'
settingsJvmOptsLink.href = 'https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html#extra-options-for-java'
} else {
@@ -1387,11 +1388,11 @@ function populateJvmOptsLink() {
/**
* Prepare the Java tab for display.
*/
function prepareJavaTab(){
async function prepareJavaTab(){
bindRangeSlider()
populateMemoryStatus()
populateJavaReqDesc()
populateJvmOptsLink()
await populateJavaReqDesc()
await populateJvmOptsLink()
}
/**
@@ -1567,17 +1568,17 @@ function prepareUpdateTab(data = null){
*
* @param {boolean} first Whether or not it is the first load.
*/
function prepareSettings(first = false) {
async function prepareSettings(first = false) {
if(first){
setupSettingsTabs()
initSettingsValidators()
prepareUpdateTab()
} else {
prepareModsTab()
await prepareModsTab()
}
initSettingsValues()
await initSettingsValues()
prepareAccountsTab()
prepareJavaTab()
await prepareJavaTab()
prepareAboutTab()
}

View File

@@ -4,10 +4,11 @@
*/
// Requirements
const path = require('path')
const { Type } = require('helios-distribution-types')
const AuthManager = require('./assets/js/authmanager')
const ConfigManager = require('./assets/js/configmanager')
const DistroManager = require('./assets/js/distromanager')
const { DistroAPI } = require('./assets/js/distromanager')
const Lang = require('./assets/js/langloader')
let rscShouldLoad = false
@@ -40,10 +41,10 @@ let currentView
*/
function switchView(current, next, currentFadeTime = 500, nextFadeTime = 500, onCurrentFade = () => {}, onNextFade = () => {}){
currentView = next
$(`${current}`).fadeOut(currentFadeTime, () => {
onCurrentFade()
$(`${next}`).fadeIn(nextFadeTime, () => {
onNextFade()
$(`${current}`).fadeOut(currentFadeTime, async () => {
await onCurrentFade()
$(`${next}`).fadeIn(nextFadeTime, async () => {
await onNextFade()
})
})
}
@@ -57,15 +58,15 @@ function getCurrentView(){
return currentView
}
function showMainUI(data){
async function showMainUI(data){
if(!isDev){
loggerAutoUpdater.info('Initializing..')
ipcRenderer.send('autoUpdateAction', 'initAutoUpdater', ConfigManager.getAllowPrerelease())
}
prepareSettings(true)
updateSelectedServer(data.getServer(ConfigManager.getSelectedServer()))
await prepareSettings(true)
updateSelectedServer(data.getServerById(ConfigManager.getSelectedServer()))
refreshServerStatus()
setTimeout(() => {
document.getElementById('frameBar').style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
@@ -133,7 +134,7 @@ function showFatalStartupError(){
* @param {Object} data The distro index object.
*/
function onDistroRefresh(data){
updateSelectedServer(data.getServer(ConfigManager.getSelectedServer()))
updateSelectedServer(data.getServerById(ConfigManager.getSelectedServer()))
refreshServerStatus()
initNews()
syncModConfigurations(data)
@@ -149,10 +150,10 @@ function syncModConfigurations(data){
const syncedCfgs = []
for(let serv of data.getServers()){
for(let serv of data.servers){
const id = serv.getID()
const mdls = serv.getModules()
const id = serv.rawServer.id
const mdls = serv.modules
const cfg = ConfigManager.getModConfiguration(id)
if(cfg != null){
@@ -161,20 +162,20 @@ function syncModConfigurations(data){
const mods = {}
for(let mdl of mdls){
const type = mdl.getType()
const type = mdl.rawModule.type
if(type === DistroManager.Types.ForgeMod || type === DistroManager.Types.LiteMod || type === DistroManager.Types.LiteLoader){
if(!mdl.getRequired().isRequired()){
const mdlID = mdl.getVersionlessID()
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){
if(!mdl.getRequired().value){
const mdlID = mdl.getVersionlessMavenIdentifier()
if(modsOld[mdlID] == null){
mods[mdlID] = scanOptionalSubModules(mdl.getSubModules(), mdl)
mods[mdlID] = scanOptionalSubModules(mdl.subModules, mdl)
} else {
mods[mdlID] = mergeModConfiguration(modsOld[mdlID], scanOptionalSubModules(mdl.getSubModules(), mdl), false)
mods[mdlID] = mergeModConfiguration(modsOld[mdlID], scanOptionalSubModules(mdl.subModules, mdl), false)
}
} else {
if(mdl.hasSubModules()){
const mdlID = mdl.getVersionlessID()
const v = scanOptionalSubModules(mdl.getSubModules(), mdl)
if(mdl.subModules.length > 0){
const mdlID = mdl.getVersionlessMavenIdentifier()
const v = scanOptionalSubModules(mdl.subModules, mdl)
if(typeof v === 'object'){
if(modsOld[mdlID] == null){
mods[mdlID] = v
@@ -197,15 +198,15 @@ function syncModConfigurations(data){
const mods = {}
for(let mdl of mdls){
const type = mdl.getType()
if(type === DistroManager.Types.ForgeMod || type === DistroManager.Types.LiteMod || type === DistroManager.Types.LiteLoader){
if(!mdl.getRequired().isRequired()){
mods[mdl.getVersionlessID()] = scanOptionalSubModules(mdl.getSubModules(), mdl)
const type = mdl.rawModule.type
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){
if(!mdl.getRequired().value){
mods[mdl.getVersionlessMavenIdentifier()] = scanOptionalSubModules(mdl.subModules, mdl)
} else {
if(mdl.hasSubModules()){
const v = scanOptionalSubModules(mdl.getSubModules(), mdl)
if(mdl.subModules.length > 0){
const v = scanOptionalSubModules(mdl.subModules, mdl)
if(typeof v === 'object'){
mods[mdl.getVersionlessID()] = v
mods[mdl.getVersionlessMavenIdentifier()] = v
}
}
}
@@ -232,8 +233,8 @@ function syncModConfigurations(data){
function ensureJavaSettings(data) {
// Nothing too fancy for now.
for(const serv of data.getServers()){
ConfigManager.ensureJavaConfig(serv.getID(), serv.getMinecraftVersion())
for(const serv of data.servers){
ConfigManager.ensureJavaConfig(serv.rawServer.id, serv.rawServer.minecraftVersion)
}
ConfigManager.save()
@@ -251,17 +252,17 @@ function scanOptionalSubModules(mdls, origin){
const mods = {}
for(let mdl of mdls){
const type = mdl.getType()
const type = mdl.rawModule.type
// Optional types.
if(type === DistroManager.Types.ForgeMod || type === DistroManager.Types.LiteMod || type === DistroManager.Types.LiteLoader){
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){
// It is optional.
if(!mdl.getRequired().isRequired()){
mods[mdl.getVersionlessID()] = scanOptionalSubModules(mdl.getSubModules(), mdl)
if(!mdl.getRequired().value){
mods[mdl.getVersionlessMavenIdentifier()] = scanOptionalSubModules(mdl.subModules, mdl)
} else {
if(mdl.hasSubModules()){
const v = scanOptionalSubModules(mdl.getSubModules(), mdl)
const v = scanOptionalSubModules(mdl.subModules, mdl)
if(typeof v === 'object'){
mods[mdl.getVersionlessID()] = v
mods[mdl.getVersionlessMavenIdentifier()] = v
}
}
}
@@ -272,13 +273,13 @@ function scanOptionalSubModules(mdls, origin){
const ret = {
mods
}
if(!origin.getRequired().isRequired()){
ret.value = origin.getRequired().isDefault()
if(!origin.getRequired().value){
ret.value = origin.getRequired().def
}
return ret
}
}
return origin.getRequired().isDefault()
return origin.getRequired().def
}
/**
@@ -323,18 +324,6 @@ function mergeModConfiguration(o, n, nReq = false){
return n
}
function refreshDistributionIndex(remote, onSuccess, onError){
if(remote){
DistroManager.pullRemote()
.then(onSuccess)
.catch(onError)
} else {
DistroManager.pullLocal()
.then(onSuccess)
.catch(onError)
}
}
async function validateSelectedAccount(){
const selectedAcc = ConfigManager.getSelectedAccount()
if(selectedAcc != null){
@@ -429,14 +418,14 @@ function setSelectedAccount(uuid){
}
// Synchronous Listener
document.addEventListener('readystatechange', function(){
document.addEventListener('readystatechange', async () => {
if (document.readyState === 'interactive' || document.readyState === 'complete'){
if(rscShouldLoad){
rscShouldLoad = false
if(!fatalStartupError){
const data = DistroManager.getDistribution()
showMainUI(data)
const data = await DistroAPI.getDistribution()
await showMainUI(data)
} else {
showFatalStartupError()
}
@@ -446,13 +435,13 @@ document.addEventListener('readystatechange', function(){
}, false)
// Actions that must be performed after the distribution index is downloaded.
ipcRenderer.on('distributionIndexDone', (event, res) => {
ipcRenderer.on('distributionIndexDone', async (event, res) => {
if(res) {
const data = DistroManager.getDistribution()
const data = await DistroAPI.getDistribution()
syncModConfigurations(data)
ensureJavaSettings(data)
if(document.readyState === 'interactive' || document.readyState === 'complete'){
showMainUI(data)
await showMainUI(data)
} else {
rscShouldLoad = true
}
@@ -467,11 +456,10 @@ ipcRenderer.on('distributionIndexDone', (event, res) => {
})
// Util for development
function devModeToggle() {
DistroManager.setDevMode(true)
DistroManager.pullLocal().then((data) => {
ensureJavaSettings(data)
updateSelectedServer(data.getServers()[0])
syncModConfigurations(data)
})
async function devModeToggle() {
DistroAPI.toggleDevMode(true)
const data = await DistroAPI.getDistributionLocalLoadOnly()
ensureJavaSettings(data)
updateSelectedServer(data.getServers()[0])
syncModConfigurations(data)
}