فهرست منبع

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.
Daniel Scalzi 7 سال پیش
والد
کامیت
aa0e1a20ca
4فایلهای تغییر یافته به همراه204 افزوده شده و 38 حذف شده
  1. 1 2
      app/assets/js/assetguard.js
  2. 92 22
      app/assets/js/processbuilder.js
  3. 79 14
      app/assets/js/scripts/uibinder.js
  4. 32 0
      app/assets/westeroscraft.json

+ 1 - 2
app/assets/js/assetguard.js

@@ -1500,12 +1500,11 @@ class AssetGuard extends EventEmitter {
             switch(obType){
                 case 'forge-hosted':
                 case 'forge':
+                case 'liteloader':
                 case 'library':
                     obPath = path.join(this.commonPath, 'libraries', obPath)
                     break
                 case 'forgemod':
-                    obPath = path.join(this.commonPath, 'modstore', obPath)
-                    break
                 case 'litemod':
                     obPath = path.join(this.commonPath, 'modstore', obPath)
                     break

+ 92 - 22
app/assets/js/processbuilder.js

@@ -19,8 +19,12 @@ class ProcessBuilder {
         this.versionData = versionData
         this.forgeData = forgeData
         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.usingLiteLoader = false
+        this.llPath = null
     }
     
     /**
@@ -30,9 +34,14 @@ class ProcessBuilder {
         mkpath.sync(this.gameDir)
         const tempNativePath = path.join(os.tmpdir(), ConfigManager.getTempNativeFolder(), crypto.pseudoRandomBytes(16).toString('hex'))
         process.throwDeprecation = true
-        const mods = this.resolveDefaultMods()
-        this.constructFMLModList(mods, true)
-        const args = this.constructJVMArguments(mods, tempNativePath)
+        this.setupLiteLoader()
+        const modObj = this.resolveModConfiguration(ConfigManager.getModConfiguration(this.server.id).mods, this.server.modules)
+        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)
 
@@ -65,41 +74,90 @@ class ProcessBuilder {
         return child
     }
 
-    resolveDefaultMods(options = {type: 'forgemod'}){
-        //Returns array of default forge mods to load.
-        const mods = []
+    static isModEnabled(modCfg, required = null){
+        return modCfg != null ? ((typeof modCfg === 'boolean' && modCfg) || (typeof modCfg === 'object' && modCfg.value)) : required != null && required.def != null ? required.def : true
+    }
+
+    static isModOptional(mdl){
+        mdl.required != null && mdl.required.value != null && mdl.required.value === false
+    }
+
+    setupLiteLoader(){
         const mdls = this.server.modules
-        const modCfg = ConfigManager.getModConfiguration(this.server.id).mods
-    
-        for(let i=0; i<mdls.length; ++i){
+        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 {
+                    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 === options.type){
-                if(mdl.required != null && mdl.required.value === false){
-                    const val = modCfg[AssetGuard._resolveWithoutVersion(mdl.id)]
-                    if(val === true){
-                        mods.push(mdl)
+            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 {
-                    mods.push(mdl)
+                    if(mdl.type === 'forgemod'){
+                        fMods.push(mdl)
+                    } else {
+                        lMods.push(mdl)
+                    }
                 }
             }
         }
 
-        return mods
+        return {
+            fMods,
+            lMods
+        }
     }
 
-    constructFMLModList(mods, save = false){
-        const modList = {}
-        modList.repositoryRoot = path.join(this.commonDir, 'modstore')
+    constructModList(type, mods, save = false){
+        const modList = {
+            repositoryRoot: path.join(this.commonDir, 'modstore')
+        }
+        
         const ids = []
         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
         
         if(save){
             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
@@ -185,6 +243,14 @@ class ProcessBuilder {
         mcArgs.push('--modListFile')
         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
         if(ConfigManager.getFullscreen()){
             mcArgs.unshift('--fullscreen')
@@ -225,6 +291,10 @@ class ProcessBuilder {
         const version = this.versionData.id
         cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
 
+        if(this.usingLiteLoader){
+            cpArgs.push(this.llPath)
+        }
+
         // Resolve the Mojang declared libraries.
         const mojangLibs = this._resolveMojangLibraries(tempNativePath)
         cpArgs = cpArgs.concat(mojangLibs)

+ 79 - 14
app/assets/js/scripts/uibinder.js

@@ -161,15 +161,13 @@ function syncModConfigurations(data){
 
             for(let j=0; j<mdls.length; j++){
                 const mdl = mdls[j]
-                if(mdl.type === 'forgemod'){
-                    if(mdl.required != null){
-                        if(mdl.required.value === false){
-                            const mdlID = AssetGuard._resolveWithoutVersion(mdl.id)
-                            if(modsOld[mdlID] == null){
-                                mods[mdlID] = mdl.required.def != null ? mdl.required.def : true
-                            } else {
-                                mods[mdlID] = modsOld[mdlID]
-                            }
+                if(mdl.type === 'forgemod' || mdl.type === 'litemod' || mdl.type === 'liteloader'){
+                    if(mdl.required != null && mdl.required.value != null && mdl.required.value === false){
+                        const mdlID = AssetGuard._resolveWithoutVersion(mdl.id)
+                        if(modsOld[mdlID] == null){
+                            mods[mdlID] = scanOptionalSubModules(mdl.sub_modules, mdl)
+                        } else {
+                            mods[mdlID] = mergeModConfiguration(modsOld[mdlID], scanOptionalSubModules(mdl.sub_modules, mdl))
                         }
                     }
                 }
@@ -186,11 +184,9 @@ function syncModConfigurations(data){
 
             for(let j=0; j<mdls.length; j++){
                 const mdl = mdls[j]
-                if(mdl.type === 'forgemod'){
-                    if(mdl.required != null){
-                        if(mdl.required.value === false){
-                            mods[AssetGuard._resolveWithoutVersion(mdl.id)] = mdl.required.def != null ? mdl.required.def : true
-                        }
+                if(mdl.type === 'forgemod' || mdl.type === 'litemod' || mdl.type === 'liteloader'){
+                    if(mdl.required != null && mdl.required.value != null && mdl.required.value === false){
+                        mods[AssetGuard._resolveWithoutVersion(mdl.id)] = scanOptionalSubModules(mdl.sub_modules, mdl)
                     }
                 }
             }
@@ -207,6 +203,75 @@ function syncModConfigurations(data){
     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){
     if(remote){
         AssetGuard.refreshDistributionDataRemote(ConfigManager.getLauncherDirectory())

+ 32 - 0
app/assets/westeroscraft.json

@@ -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",
                     "name": "Optifine (1.11.2_HD_U_C7)",