From bc2dc371d0379ec8c6e1a60a32710585fd5665de Mon Sep 17 00:00:00 2001 From: jebibot <83044352+jebibot@users.noreply.github.com> Date: Fri, 24 Nov 2023 09:45:21 +0900 Subject: [PATCH 1/3] feat: support Fabric --- app/assets/js/processbuilder.js | 23 +++++++++++++++-------- app/assets/js/scripts/landing.js | 4 ++-- app/assets/js/scripts/settings.js | 2 +- app/assets/js/scripts/uibinder.js | 6 +++--- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/app/assets/js/processbuilder.js b/app/assets/js/processbuilder.js index 18c48fb5..e02a90c8 100644 --- a/app/assets/js/processbuilder.js +++ b/app/assets/js/processbuilder.js @@ -28,6 +28,7 @@ class ProcessBuilder { this.libPath = path.join(this.commonDir, 'libraries') this.usingLiteLoader = false + this.usingFabricLoader = false this.llPath = null } @@ -40,9 +41,12 @@ class ProcessBuilder { process.throwDeprecation = true this.setupLiteLoader() logger.info('Using liteloader:', this.usingLiteLoader) + this.usingFabricLoader = this.server.modules.some(mdl => mdl.rawModule.type === Type.Fabric) + logger.info('Using fabric loader:', this.usingFabricLoader) const modObj = this.resolveModConfiguration(ConfigManager.getModConfiguration(this.server.rawServer.id).mods, this.server.modules) // Mod list below 1.13 + // Fabric only supports 1.14+ if(!mcVersionAtLeast('1.13', this.server.rawServer.minecraftVersion)){ this.constructJSONModList('forge', modObj.fMods, true) if(this.usingLiteLoader){ @@ -166,7 +170,7 @@ class ProcessBuilder { for(let mdl of mdls){ const type = mdl.rawModule.type - if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){ + if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){ const o = !mdl.getRequired().value const e = ProcessBuilder.isModEnabled(modCfg[mdl.getVersionlessMavenIdentifier()], mdl.getRequired()) if(!o || (o && e)){ @@ -178,7 +182,7 @@ class ProcessBuilder { continue } } - if(type === Type.ForgeMod){ + if(type === Type.ForgeMod || type === Type.FabricMod){ fMods.push(mdl) } else { lMods.push(mdl) @@ -282,18 +286,21 @@ class ProcessBuilder { // } /** - * Construct the mod argument list for forge 1.13 + * Construct the mod argument list for forge 1.13 and Fabric * * @param {Array.} mods An array of mods to add to the mod list. */ constructModList(mods) { const writeBuffer = mods.map(mod => { - return mod.getExtensionlessMavenIdentifier() + return this.usingFabricLoader ? mod.getPath() : mod.getExtensionlessMavenIdentifier() }).join('\n') if(writeBuffer) { fs.writeFileSync(this.forgeModListFile, writeBuffer, 'UTF-8') - return [ + return this.usingFabricLoader ? [ + '--fabric.addMods', + `@${this.forgeModListFile}` + ] : [ '--fml.mavenRoots', path.join('..', '..', 'common', 'modstore'), '--fml.modLists', @@ -669,7 +676,7 @@ class ProcessBuilder { classpathArg(mods, tempNativePath){ let cpArgs = [] - if(!mcVersionAtLeast('1.17', this.server.rawServer.minecraftVersion)) { + if(!mcVersionAtLeast('1.17', this.server.rawServer.minecraftVersion) || this.usingFabricLoader) { // Add the version.jar to the classpath. // Must not be added to the classpath for Forge 1.17+. const version = this.versionData.id @@ -830,10 +837,10 @@ class ProcessBuilder { const mdls = this.server.modules let libs = {} - // Locate Forge/Libraries + // Locate Forge/Fabric/Libraries for(let mdl of mdls){ const type = mdl.rawModule.type - if(type === Type.ForgeHosted || type === Type.Library){ + if(type === Type.ForgeHosted || type === Type.Fabric || type === Type.Library){ libs[mdl.getVersionlessMavenIdentifier()] = mdl.getPath() if(mdl.subModules.length > 0){ const res = this._resolveModuleLibraries(mdl) diff --git a/app/assets/js/scripts/landing.js b/app/assets/js/scripts/landing.js index 1c73e044..e96b7a3f 100644 --- a/app/assets/js/scripts/landing.js +++ b/app/assets/js/scripts/landing.js @@ -548,13 +548,13 @@ async function dlAsync(login = true) { serv.rawServer.id ) - const forgeData = await distributionIndexProcessor.loadForgeVersionJson(serv) + const modLoaderData = await distributionIndexProcessor.loadModLoaderVersionJson(serv) const versionData = await mojangIndexProcessor.getVersionJson() if(login) { const authUser = ConfigManager.getSelectedAccount() loggerLaunchSuite.info(`Sending selected account (${authUser.displayName}) to ProcessBuilder.`) - let pb = new ProcessBuilder(serv, versionData, forgeData, authUser, remote.app.getVersion()) + let pb = new ProcessBuilder(serv, versionData, modLoaderData, authUser, remote.app.getVersion()) setLaunchDetails(Lang.queryJS('landing.dlAsync.launchingGame')) // const SERVER_JOINED_REGEX = /\[.+\]: \[CHAT\] [a-zA-Z0-9_]{1,16} joined the game/ diff --git a/app/assets/js/scripts/settings.js b/app/assets/js/scripts/settings.js index 628c63ce..81a65a70 100644 --- a/app/assets/js/scripts/settings.js +++ b/app/assets/js/scripts/settings.js @@ -736,7 +736,7 @@ function parseModulesForUI(mdls, submodules, servConf){ for(const mdl of mdls){ - if(mdl.rawModule.type === Type.ForgeMod || mdl.rawModule.type === Type.LiteMod || mdl.rawModule.type === Type.LiteLoader){ + if(mdl.rawModule.type === Type.ForgeMod || mdl.rawModule.type === Type.LiteMod || mdl.rawModule.type === Type.LiteLoader || mdl.rawModule.type === Type.FabricMod){ if(mdl.getRequired().value){ diff --git a/app/assets/js/scripts/uibinder.js b/app/assets/js/scripts/uibinder.js index 469f49fd..5fe79df5 100644 --- a/app/assets/js/scripts/uibinder.js +++ b/app/assets/js/scripts/uibinder.js @@ -163,7 +163,7 @@ function syncModConfigurations(data){ for(let mdl of mdls){ const type = mdl.rawModule.type - if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){ + if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){ if(!mdl.getRequired().value){ const mdlID = mdl.getVersionlessMavenIdentifier() if(modsOld[mdlID] == null){ @@ -198,7 +198,7 @@ function syncModConfigurations(data){ for(let mdl of mdls){ const type = mdl.rawModule.type - if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){ + if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){ if(!mdl.getRequired().value){ mods[mdl.getVersionlessMavenIdentifier()] = scanOptionalSubModules(mdl.subModules, mdl) } else { @@ -253,7 +253,7 @@ function scanOptionalSubModules(mdls, origin){ for(let mdl of mdls){ const type = mdl.rawModule.type // Optional types. - if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){ + if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){ // It is optional. if(!mdl.getRequired().value){ mods[mdl.getVersionlessMavenIdentifier()] = scanOptionalSubModules(mdl.subModules, mdl) From 3185146d60a69635a31b14dc3d113858967b7c62 Mon Sep 17 00:00:00 2001 From: jebibot <83044352+jebibot@users.noreply.github.com> Date: Fri, 24 Nov 2023 11:30:52 +0900 Subject: [PATCH 2/3] fix: GAME_LAUNCH_REGEX for Fabric --- app/assets/js/scripts/landing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/js/scripts/landing.js b/app/assets/js/scripts/landing.js index e96b7a3f..1a1c1768 100644 --- a/app/assets/js/scripts/landing.js +++ b/app/assets/js/scripts/landing.js @@ -442,7 +442,7 @@ let hasRPC = false // Joined server regex // Change this if your server uses something different. const GAME_JOINED_REGEX = /\[.+\]: Sound engine started/ -const GAME_LAUNCH_REGEX = /^\[.+\]: (?:MinecraftForge .+ Initialized|ModLauncher .+ starting: .+)$/ +const GAME_LAUNCH_REGEX = /^\[.+\]: (?:MinecraftForge .+ Initialized|ModLauncher .+ starting: .+|Loading Minecraft .+ with Fabric Loader .+)$/ const MIN_LINGER = 5000 async function dlAsync(login = true) { From fe1f8d63f37b059825df1b23a78524f2be30374d Mon Sep 17 00:00:00 2001 From: Daniel Scalzi Date: Sat, 2 Dec 2023 01:48:06 -0500 Subject: [PATCH 3/3] Small refactor. --- app/assets/js/processbuilder.js | 87 ++++++++++++--------------------- 1 file changed, 32 insertions(+), 55 deletions(-) diff --git a/app/assets/js/processbuilder.js b/app/assets/js/processbuilder.js index e02a90c8..0e955621 100644 --- a/app/assets/js/processbuilder.js +++ b/app/assets/js/processbuilder.js @@ -12,14 +12,23 @@ const ConfigManager = require('./configmanager') const logger = LoggerUtil.getLogger('ProcessBuilder') + +/** + * Only forge and fabric are top level mod loaders. + * + * Forge 1.13+ launch logic is similar to fabrics, for now using usingFabricLoader flag to + * change minor details when needed. + * + * Rewrite of this module may be needed in the future. + */ class ProcessBuilder { - constructor(distroServer, versionData, forgeData, authUser, launcherVersion){ + constructor(distroServer, vanillaManifest, modManifest, authUser, launcherVersion){ this.gameDir = path.join(ConfigManager.getInstanceDirectory(), distroServer.rawServer.id) this.commonDir = ConfigManager.getCommonDirectory() this.server = distroServer - this.versionData = versionData - this.forgeData = forgeData + this.vanillaManifest = vanillaManifest + this.modManifest = modManifest this.authUser = authUser this.launcherVersion = launcherVersion this.forgeModListFile = path.join(this.gameDir, 'forgeMods.list') // 1.13+ @@ -198,7 +207,7 @@ class ProcessBuilder { } _lteMinorVersion(version) { - return Number(this.forgeData.id.split('-')[0].split('.')[1]) <= Number(version) + return Number(this.modManifest.id.split('-')[0].split('.')[1]) <= Number(version) } /** @@ -210,7 +219,7 @@ class ProcessBuilder { if(this._lteMinorVersion(9)) { return false } - const ver = this.forgeData.id.split('-')[2] + const ver = this.modManifest.id.split('-')[2] const pts = ver.split('.') const min = [14, 23, 3, 2655] for(let i=0; i { @@ -563,7 +558,7 @@ class ProcessBuilder { * @returns {Array.} An array containing the arguments required by forge. */ _resolveForgeArgs(){ - const mcArgs = this.forgeData.minecraftArguments.split(' ') + const mcArgs = this.modManifest.minecraftArguments.split(' ') const argDiscovery = /\${*(.*)}/ // Replace the declared variables with their proper values. @@ -576,7 +571,7 @@ class ProcessBuilder { val = this.authUser.displayName.trim() break case 'version_name': - //val = versionData.id + //val = vanillaManifest.id val = this.server.rawServer.id break case 'game_directory': @@ -586,7 +581,7 @@ class ProcessBuilder { val = path.join(this.commonDir, 'assets') break case 'assets_index_name': - val = this.versionData.assets + val = this.vanillaManifest.assets break case 'auth_uuid': val = this.authUser.uuid.trim() @@ -601,7 +596,7 @@ class ProcessBuilder { val = '{}' break case 'version_type': - val = this.versionData.type + val = this.vanillaManifest.type break } if(val != null){ @@ -679,7 +674,7 @@ class ProcessBuilder { if(!mcVersionAtLeast('1.17', this.server.rawServer.minecraftVersion) || this.usingFabricLoader) { // Add the version.jar to the classpath. // Must not be added to the classpath for Forge 1.17+. - const version = this.versionData.id + const version = this.vanillaManifest.id cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar')) } @@ -718,7 +713,7 @@ class ProcessBuilder { const nativesRegex = /.+:natives-([^-]+)(?:-(.+))?/ const libs = {} - const libArr = this.versionData.libraries + const libArr = this.vanillaManifest.libraries fs.ensureDirSync(tempNativePath) for(let i=0; i Number(v)) - - if(verSplit[0] === 31) { - for(let i=0; i minWorking[i]) { - return false - } else if(verSplit[i] < minWorking[i]) { - return true - } - } - } - - return false - } - } module.exports = ProcessBuilder \ No newline at end of file