Version Support
- ModLauncher 8: Forge 1.16.5
- ModLauncher 9: Forge 1.17+ (also supports ModLauncher 10 and 11)
Key Differences
ModLauncher 8 vs 9
Setup for ModLauncher 8 & 9
TransformationService Entrypoint
ModLauncher usesTransformationService as its early entrypoint, discovered via Java’s ServiceLoader mechanism.
Service File
Essential Loader provides a service file at:ModLauncher discovers TransformationServices from jars in the mods folder via this ServiceLoader file, similar to how LaunchWrapper uses manifest entries.
Multi-Stage Architecture
Essential Loader uses a multi-stage architecture for maximum flexibility:- Stage 0: Bundled in your mod (with relocation)
- Stage 1: Updatable, forwards to stage 2
- Stage 2: Auto-updatable, contains all the heavy lifting
Each stage has its own
TransformationService implementation, allowing updates to propagate while maintaining compatibility.ModLauncher 9 Specific Requirements
Package Relocation is Mandatory
Unique TransformationService Names
Because each relocated stage0 must have a unique package, all TransformationServices must:- Be able to handle being instantiated multiple times
- Return a unique name for each instance (generated based on the stage0 package)
Module System Challenges
ModLauncher 9 heavily uses Java 9’s module system, which changes almost everything compared to ModLauncher 8. Public members often cannot be accessed via reflection without using Unsafe to bypass module restrictions.
Upgrading Third-Party Mods (KotlinForForge)
Essential Loader can automatically upgrade outdated third-party mods, particularly KotlinForForge.The Problem
ModLauncher 8 Solution
Replace with SortedLanguageLoadingProvider
The cloned provider is replaced with
SortedLanguageLoadingProvider, which sorts jars by implementation version.This only deals with language mods (like KotlinForForge) because that’s what Essential Loader needs. Regular mods use a different mechanism in Forge.
ModLauncher 9 Solution
ModLauncher 9 introduces additional complexity:Implementation Details
-
SortedJarOrPathList: A custom
Listimplementation that sorts elements by version, replacing the regular list for each ModLauncher layer. - SelfRenamingJarMetadata: On-the-fly renames jar metadata to steal the name of jars with overlapping packages, preventing module conflicts.
The SelfRenamingJarMetadata implementation is elegant enough that it would work even if another mod did the same thing - more compatible than ModLauncher itself!
Upgrading Kotlin Stdlib
KotlinForForge sometimes takes a while to update and may make backwards-incompatible changes. Essential Loader can upgrade the Kotlin stdlib independently.ModLauncher 8 Approach
ModLauncher 9 Challenges
The JarJar Problem
Forge added JiJ support (called JarJar) in mid-2022, but:- It doesn’t work properly for language mods
- KotlinForForge can’t use it
- The issue (MinecraftForge#8878) has been open since 2022 with no fix
Solution: Auto-Generate KotlinForForge
Generate Replacement Jar
Automatically generates a new KotlinForForge jar based on the existing one but with upgraded Kotlin stdlib.
While this approach involves some educated guesses, it works well enough in practice.
Mod/Language Load Order (ModLauncher 8)
Solution
Essential Loader intercepts the Lambda used to fetch class bytes and adjusts the priority. This must happen before any classes are loaded, so it “registers” (via Unsafe) anEssentialLaunchPluginService with a method that’s invoked at the right time.
Complete Example
Here’s a complete example for ModLauncher 9:build.gradle.kts
Troubleshooting
Package Conflict Errors (ModLauncher 9)
TransformationService Not Found
Ensure
mergeServiceFiles() is called in your ShadowJar configuration. This is required for the service files to be properly relocated.KotlinForForge Compatibility
If you see Kotlin version conflicts:- Essential Loader will attempt to auto-upgrade KotlinForForge
- Check logs for details on the upgrade process
- The upgrade happens automatically on game start
File Name Issues (ModLauncher 9)
If a user downloads KotlinForForge from different websites or downloads it twice (browser adds ” (1)” to the name), Forge will derive different automatic module names, causing conflicts.Essential Loader’s
SelfRenamingJarMetadata automatically handles this case by detecting overlapping packages and stealing the appropriate module name.Platform Differences Summary
Best Practices
- Always Relocate on ModLauncher 9: This is mandatory, not optional.
- Don’t Relocate stage1.jar: The stage1.jar file must remain at its original path for discovery.
- Use mergeServiceFiles(): Required for TransformationService discovery after relocation.
- Test with KotlinForForge: If your mod or its dependencies use Kotlin, test with various KotlinForForge versions.
- Monitor Forge Updates: ModLauncher internals can change between Forge versions. Test your mod with new Forge releases.
ModLauncher platforms require more hacks and workarounds than other platforms. Essential Loader’s stage2 auto-update capability is crucial for quickly fixing issues when Forge internals change.