mirror of
https://github.com/dscalzi/HeliosLauncher.git
synced 2024-12-22 11:42:14 -08:00
Added initial support of liteloader + optional submodules.
Liteloader is loaded as a library, with special launch conditions being executed when it is enabled. Litemods are constructed into a mod list and passed to liteloader via the --modRepo argument. The launcher now supports optional submodules. These are parsed recursively, there is no depth limit. Typically the depth will be only 2 as litemods are optional submoduless of liteloader.
This commit is contained in:
parent
145a2fe77b
commit
aa0e1a20ca
@ -1500,12 +1500,11 @@ class AssetGuard extends EventEmitter {
|
|||||||
switch(obType){
|
switch(obType){
|
||||||
case 'forge-hosted':
|
case 'forge-hosted':
|
||||||
case 'forge':
|
case 'forge':
|
||||||
|
case 'liteloader':
|
||||||
case 'library':
|
case 'library':
|
||||||
obPath = path.join(this.commonPath, 'libraries', obPath)
|
obPath = path.join(this.commonPath, 'libraries', obPath)
|
||||||
break
|
break
|
||||||
case 'forgemod':
|
case 'forgemod':
|
||||||
obPath = path.join(this.commonPath, 'modstore', obPath)
|
|
||||||
break
|
|
||||||
case 'litemod':
|
case 'litemod':
|
||||||
obPath = path.join(this.commonPath, 'modstore', obPath)
|
obPath = path.join(this.commonPath, 'modstore', obPath)
|
||||||
break
|
break
|
||||||
|
@ -19,8 +19,12 @@ class ProcessBuilder {
|
|||||||
this.versionData = versionData
|
this.versionData = versionData
|
||||||
this.forgeData = forgeData
|
this.forgeData = forgeData
|
||||||
this.authUser = authUser
|
this.authUser = authUser
|
||||||
this.fmlDir = path.join(this.commonDir, 'versions', this.server.id + '.json')
|
this.fmlDir = path.join(this.gameDir, 'forgeModList.json')
|
||||||
|
this.llDir = path.join(this.gameDir, 'liteloaderModList.json')
|
||||||
this.libPath = path.join(this.commonDir, 'libraries')
|
this.libPath = path.join(this.commonDir, 'libraries')
|
||||||
|
|
||||||
|
this.usingLiteLoader = false
|
||||||
|
this.llPath = null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,9 +34,14 @@ class ProcessBuilder {
|
|||||||
mkpath.sync(this.gameDir)
|
mkpath.sync(this.gameDir)
|
||||||
const tempNativePath = path.join(os.tmpdir(), ConfigManager.getTempNativeFolder(), crypto.pseudoRandomBytes(16).toString('hex'))
|
const tempNativePath = path.join(os.tmpdir(), ConfigManager.getTempNativeFolder(), crypto.pseudoRandomBytes(16).toString('hex'))
|
||||||
process.throwDeprecation = true
|
process.throwDeprecation = true
|
||||||
const mods = this.resolveDefaultMods()
|
this.setupLiteLoader()
|
||||||
this.constructFMLModList(mods, true)
|
const modObj = this.resolveModConfiguration(ConfigManager.getModConfiguration(this.server.id).mods, this.server.modules)
|
||||||
const args = this.constructJVMArguments(mods, tempNativePath)
|
this.constructModList('forge', modObj.fMods, true)
|
||||||
|
if(this.usingLiteLoader){
|
||||||
|
this.constructModList('liteloader', modObj.lMods, true)
|
||||||
|
}
|
||||||
|
const uberModArr = modObj.fMods.concat(modObj.lMods)
|
||||||
|
const args = this.constructJVMArguments(uberModArr, tempNativePath)
|
||||||
|
|
||||||
console.log(args)
|
console.log(args)
|
||||||
|
|
||||||
@ -65,41 +74,90 @@ class ProcessBuilder {
|
|||||||
return child
|
return child
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveDefaultMods(options = {type: 'forgemod'}){
|
static isModEnabled(modCfg, required = null){
|
||||||
//Returns array of default forge mods to load.
|
return modCfg != null ? ((typeof modCfg === 'boolean' && modCfg) || (typeof modCfg === 'object' && modCfg.value)) : required != null && required.def != null ? required.def : true
|
||||||
const mods = []
|
}
|
||||||
const mdls = this.server.modules
|
|
||||||
const modCfg = ConfigManager.getModConfiguration(this.server.id).mods
|
|
||||||
|
|
||||||
for(let i=0; i<mdls.length; ++i){
|
static isModOptional(mdl){
|
||||||
const mdl = mdls[i]
|
mdl.required != null && mdl.required.value != null && mdl.required.value === false
|
||||||
if(mdl.type != null && mdl.type === options.type){
|
}
|
||||||
if(mdl.required != null && mdl.required.value === false){
|
|
||||||
const val = modCfg[AssetGuard._resolveWithoutVersion(mdl.id)]
|
setupLiteLoader(){
|
||||||
if(val === true){
|
const mdls = this.server.modules
|
||||||
mods.push(mdl)
|
for(let i=0; i<mdls.length; i++){
|
||||||
|
if(mdls[i].type === 'liteloader'){
|
||||||
|
const ll = mdls[i]
|
||||||
|
if(ProcessBuilder.isModOptional(ll)){
|
||||||
|
const modCfg = ConfigManager.getModConfiguration(this.server.id).mods
|
||||||
|
if(ProcessBuilder.isModEnabled(modCfg[AssetGuard._resolveWithoutVersion(ll.id)], ll.required)){
|
||||||
|
this.usingLiteLoader = true
|
||||||
|
this.llPath = path.join(this.libPath, ll.artifact.path == null ? AssetGuard._resolvePath(ll.id, ll.artifact.extension) : ll.artifact.path)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mods.push(mdl)
|
this.usingLiteLoader = true
|
||||||
|
this.llPath = path.join(this.libPath, ll.artifact.path == null ? AssetGuard._resolvePath(ll.id, ll.artifact.extension) : ll.artifact.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveModConfiguration(modCfg, mdls){
|
||||||
|
let fMods = []
|
||||||
|
let lMods = []
|
||||||
|
|
||||||
|
for(let i=0; i<mdls.length; i++){
|
||||||
|
const mdl = mdls[i]
|
||||||
|
if(mdl.type != null && (mdl.type === 'forgemod' || mdl.type === 'litemod' || mdl.type === 'liteloader')){
|
||||||
|
if(mdl.sub_modules != null){
|
||||||
|
const v = this.resolveModConfiguration(modCfg[AssetGuard._resolveWithoutVersion(mdl.id)], mdl.sub_modules)
|
||||||
|
fMods = fMods.concat(v.fMods)
|
||||||
|
lMods = lMods.concat(v.lMods)
|
||||||
|
if(mdl.type === 'liteloader'){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ProcessBuilder.isModOptional(mdl)){
|
||||||
|
if(ProcessBuilder.isModEnabled(modCfg[AssetGuard._resolveWithoutVersion(mdl.id)]), mdl.required){
|
||||||
|
if(mdl.type === 'forgemod'){
|
||||||
|
fMods.push(mdl)
|
||||||
|
} else {
|
||||||
|
lMods.push(mdl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(mdl.type === 'forgemod'){
|
||||||
|
fMods.push(mdl)
|
||||||
|
} else {
|
||||||
|
lMods.push(mdl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mods
|
return {
|
||||||
|
fMods,
|
||||||
|
lMods
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructFMLModList(mods, save = false){
|
constructModList(type, mods, save = false){
|
||||||
const modList = {}
|
const modList = {
|
||||||
modList.repositoryRoot = path.join(this.commonDir, 'modstore')
|
repositoryRoot: path.join(this.commonDir, 'modstore')
|
||||||
|
}
|
||||||
|
|
||||||
const ids = []
|
const ids = []
|
||||||
for(let i=0; i<mods.length; ++i){
|
for(let i=0; i<mods.length; ++i){
|
||||||
ids.push(mods[i].id)
|
if(type === 'forge'){
|
||||||
|
ids.push(mods[i].id)
|
||||||
|
} else {
|
||||||
|
ids.push(mods[i].id + '@' + (mods[i].artifact.extension != null ? mods[i].artifact.extension.substring(1) : 'jar'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
modList.modRef = ids
|
modList.modRef = ids
|
||||||
|
|
||||||
if(save){
|
if(save){
|
||||||
const json = JSON.stringify(modList, null, 4)
|
const json = JSON.stringify(modList, null, 4)
|
||||||
fs.writeFileSync(this.fmlDir, json, 'UTF-8')
|
fs.writeFileSync(type === 'forge' ? this.fmlDir : this.llDir, json, 'UTF-8')
|
||||||
}
|
}
|
||||||
|
|
||||||
return modList
|
return modList
|
||||||
@ -185,6 +243,14 @@ class ProcessBuilder {
|
|||||||
mcArgs.push('--modListFile')
|
mcArgs.push('--modListFile')
|
||||||
mcArgs.push('absolute:' + this.fmlDir)
|
mcArgs.push('absolute:' + this.fmlDir)
|
||||||
|
|
||||||
|
if(this.usingLiteLoader){
|
||||||
|
mcArgs.push('--modRepo')
|
||||||
|
mcArgs.push(this.llDir)
|
||||||
|
|
||||||
|
mcArgs.unshift('com.mumfrey.liteloader.launch.LiteLoaderTweaker')
|
||||||
|
mcArgs.unshift('--tweakClass')
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare game resolution
|
// Prepare game resolution
|
||||||
if(ConfigManager.getFullscreen()){
|
if(ConfigManager.getFullscreen()){
|
||||||
mcArgs.unshift('--fullscreen')
|
mcArgs.unshift('--fullscreen')
|
||||||
@ -225,6 +291,10 @@ class ProcessBuilder {
|
|||||||
const version = this.versionData.id
|
const version = this.versionData.id
|
||||||
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
||||||
|
|
||||||
|
if(this.usingLiteLoader){
|
||||||
|
cpArgs.push(this.llPath)
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve the Mojang declared libraries.
|
// Resolve the Mojang declared libraries.
|
||||||
const mojangLibs = this._resolveMojangLibraries(tempNativePath)
|
const mojangLibs = this._resolveMojangLibraries(tempNativePath)
|
||||||
cpArgs = cpArgs.concat(mojangLibs)
|
cpArgs = cpArgs.concat(mojangLibs)
|
||||||
|
@ -161,15 +161,13 @@ function syncModConfigurations(data){
|
|||||||
|
|
||||||
for(let j=0; j<mdls.length; j++){
|
for(let j=0; j<mdls.length; j++){
|
||||||
const mdl = mdls[j]
|
const mdl = mdls[j]
|
||||||
if(mdl.type === 'forgemod'){
|
if(mdl.type === 'forgemod' || mdl.type === 'litemod' || mdl.type === 'liteloader'){
|
||||||
if(mdl.required != null){
|
if(mdl.required != null && mdl.required.value != null && mdl.required.value === false){
|
||||||
if(mdl.required.value === false){
|
const mdlID = AssetGuard._resolveWithoutVersion(mdl.id)
|
||||||
const mdlID = AssetGuard._resolveWithoutVersion(mdl.id)
|
if(modsOld[mdlID] == null){
|
||||||
if(modsOld[mdlID] == null){
|
mods[mdlID] = scanOptionalSubModules(mdl.sub_modules, mdl)
|
||||||
mods[mdlID] = mdl.required.def != null ? mdl.required.def : true
|
} else {
|
||||||
} else {
|
mods[mdlID] = mergeModConfiguration(modsOld[mdlID], scanOptionalSubModules(mdl.sub_modules, mdl))
|
||||||
mods[mdlID] = modsOld[mdlID]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,11 +184,9 @@ function syncModConfigurations(data){
|
|||||||
|
|
||||||
for(let j=0; j<mdls.length; j++){
|
for(let j=0; j<mdls.length; j++){
|
||||||
const mdl = mdls[j]
|
const mdl = mdls[j]
|
||||||
if(mdl.type === 'forgemod'){
|
if(mdl.type === 'forgemod' || mdl.type === 'litemod' || mdl.type === 'liteloader'){
|
||||||
if(mdl.required != null){
|
if(mdl.required != null && mdl.required.value != null && mdl.required.value === false){
|
||||||
if(mdl.required.value === false){
|
mods[AssetGuard._resolveWithoutVersion(mdl.id)] = scanOptionalSubModules(mdl.sub_modules, mdl)
|
||||||
mods[AssetGuard._resolveWithoutVersion(mdl.id)] = mdl.required.def != null ? mdl.required.def : true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,6 +203,75 @@ function syncModConfigurations(data){
|
|||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively scan for optional sub modules. If none are found,
|
||||||
|
* this function returns a boolean. If optional sub modules do exist,
|
||||||
|
* a recursive configuration object is returned.
|
||||||
|
*
|
||||||
|
* @returns {boolean | Object} The resolved mod configuration.
|
||||||
|
*/
|
||||||
|
function scanOptionalSubModules(mdls, origin){
|
||||||
|
if(mdls != null){
|
||||||
|
const mods = {}
|
||||||
|
|
||||||
|
for(let i=0; i<mdls.length; i++){
|
||||||
|
const mdl = mdls[i]
|
||||||
|
// Optional types.
|
||||||
|
if(mdl.type === 'forgemod' || mdl.type === 'litemod' || mdl.type === 'liteloader'){
|
||||||
|
// It is optional.
|
||||||
|
if(mdl.required != null && mdl.required.value != null && mdl.required.value === false){
|
||||||
|
mods[AssetGuard._resolveWithoutVersion(mdl.id)] = scanOptionalSubModules(mdl.sub_modules, mdl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Object.keys(mods).length > 0){
|
||||||
|
return {
|
||||||
|
value: origin.required != null && origin.required.def != null ? origin.required.def : true,
|
||||||
|
mods
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return origin.required != null && origin.required.def != null ? origin.required.def : true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively merge an old configuration into a new configuration.
|
||||||
|
*
|
||||||
|
* @param {boolean | Object} o The old configuration value.
|
||||||
|
* @param {boolean | Object} n The new configuration value.
|
||||||
|
*
|
||||||
|
* @returns {boolean | Object} The merged configuration.
|
||||||
|
*/
|
||||||
|
function mergeModConfiguration(o, n){
|
||||||
|
if(typeof o === 'boolean'){
|
||||||
|
if(typeof n === 'boolean') return o
|
||||||
|
else if(typeof n === 'object'){
|
||||||
|
n.value = o
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
} else if(typeof o === 'object'){
|
||||||
|
if(typeof n === 'boolean') return o.value
|
||||||
|
else if(typeof n === 'object'){
|
||||||
|
n.value = o.value
|
||||||
|
|
||||||
|
const newMods = Object.keys(n.mods)
|
||||||
|
for(let i=0; i<newMods.length; i++){
|
||||||
|
|
||||||
|
const mod = newMods[i]
|
||||||
|
if(o.mods[mod] != null){
|
||||||
|
n.mods[mod] = mergeModConfiguration(o.mods[mod], n.mods[mod])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If for some reason we haven't been able to merge,
|
||||||
|
// wipe the old value and use the new one. Just to be safe
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
function refreshDistributionIndex(remote, onSuccess, onError){
|
function refreshDistributionIndex(remote, onSuccess, onError){
|
||||||
if(remote){
|
if(remote){
|
||||||
AssetGuard.refreshDistributionDataRemote(ConfigManager.getLauncherDirectory())
|
AssetGuard.refreshDistributionDataRemote(ConfigManager.getLauncherDirectory())
|
||||||
|
@ -237,6 +237,38 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "com.mumfrey:liteloader:1.11.2",
|
||||||
|
"name": "Liteloader (1.11.2)",
|
||||||
|
"type": "liteloader",
|
||||||
|
"required": {
|
||||||
|
"value": false,
|
||||||
|
"def": false
|
||||||
|
},
|
||||||
|
"artifact": {
|
||||||
|
"size": 1685422,
|
||||||
|
"MD5": "3a98b5ed95810bf164e71c1a53be568d",
|
||||||
|
"extension": ".jar",
|
||||||
|
"url": "http://mc.westeroscraft.com/WesterosCraftLauncher/files/1.11.2/liteloader-1.11.2.jar"
|
||||||
|
},
|
||||||
|
"sub_modules": [
|
||||||
|
{
|
||||||
|
"id": "com.mumfrey:macrokeybindmod:0.14.4-1.11.2",
|
||||||
|
"name": "Macro/Keybind Mod (0.14.4-1.11.2)",
|
||||||
|
"type": "litemod",
|
||||||
|
"required": {
|
||||||
|
"value": false,
|
||||||
|
"def": false
|
||||||
|
},
|
||||||
|
"artifact": {
|
||||||
|
"size": 1670811,
|
||||||
|
"MD5": "16080785577b391d426c62c8d3138558",
|
||||||
|
"extension": ".litemod",
|
||||||
|
"url": "http://mc.westeroscraft.com/WesterosCraftLauncher/prod-1.11.2/mods/macrokeybindmod.litemod"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "net.optifine:optifine:1.11.2_HD_U_C7",
|
"id": "net.optifine:optifine:1.11.2_HD_U_C7",
|
||||||
"name": "Optifine (1.11.2_HD_U_C7)",
|
"name": "Optifine (1.11.2_HD_U_C7)",
|
||||||
|
Loading…
Reference in New Issue
Block a user