fix: ensure version jar exists for Forge to prevent _1._20._1 module name

findVersionJar() falls back to versions/1.20.1/1.20.1.jar when the Forge
version jar doesnt exist. Filename 1.20.1.jar produces automatic module _1._20._1
which conflicts with module minecraft (split-package on net.minecraft.server).

Fix: ensureVersionJarForForge() copies vanilla jar to versions/<versionId>/
<versionId>.jar before findVersionJar() is called. Vanilla jar has
Automatic-Module-Name: minecraft so it becomes module minecraft, not _1._20._1.
This commit is contained in:
SashegDev
2026-07-14 10:49:54 +00:00
parent 6368c32a83
commit 9a853a6134
@@ -59,6 +59,11 @@ public class LaunchCommandBuilder {
// defines all of these. This matches AstralRinth's approach. // defines all of these. This matches AstralRinth's approach.
System.out.println(ZAnsi.cyan(" Forge/NeoForge: using version.json args with placeholder substitution")); System.out.println(ZAnsi.cyan(" Forge/NeoForge: using version.json args with placeholder substitution"));
// Ensure version jar exists at versions/<versionId>/<versionId>.jar
// so securejarhandler creates module "minecraft" (from Automatic-Module-Name)
// instead of "_1._20._1" (automatic module from filename 1.20.1.jar).
ensureVersionJarForForge();
// Build classpath from manifest libraries + client jar // Build classpath from manifest libraries + client jar
String classpath; String classpath;
if (manifest != null) { if (manifest != null) {
@@ -698,17 +703,13 @@ public class LaunchCommandBuilder {
/** /**
* Ensure the version jar exists at versions/<versionId>/<versionId>.jar * Ensure the version jar exists at versions/<versionId>/<versionId>.jar
* so that securejarhandler can create the "minecraft" module from it. * so that securejarhandler creates module "minecraft" (from
* Automatic-Module-Name: minecraft) instead of "_1._20._1" (automatic
* module derived from filename 1.20.1.jar).
* *
* The version jar MUST contain SRG-mapped classes (not obfuscated Mojang * Without this, findVersionJar() falls back to versions/1.20.1/1.20.1.jar
* names) and have Automatic-Module-Name: minecraft in its MANIFEST.MF. * which produces module _1._20._1, causing split-package conflicts with
* Without this, securejarhandler creates an automatic module from the * the minecraft module.
* filename, claims the net.minecraft.server.packs.resources package, but
* doesn't have SRG-named classes like PreparableReloadListener → crash.
*
* Priority:
* 1. SRG-mapped client jar from Forge libraries (client-*-srg.jar)
* 2. Vanilla version jar (fallback, may cause module issues)
*/ */
private void ensureVersionJarForForge() throws IOException { private void ensureVersionJarForForge() throws IOException {
String versionId = getVersionId(); String versionId = getVersionId();
@@ -719,34 +720,21 @@ public class LaunchCommandBuilder {
Path targetJar = targetDir.resolve(versionId + ".jar"); Path targetJar = targetDir.resolve(versionId + ".jar");
if (Files.exists(targetJar) && isValidJar(targetJar)) { if (Files.exists(targetJar) && isValidJar(targetJar)) {
if (hasMinecraftModuleName(targetJar)) { System.out.println(ZAnsi.green(" Version jar already exists: " + targetJar));
System.out.println(ZAnsi.green(" Version jar already exists with correct module name: " + targetJar));
return; return;
} }
System.out.println(ZAnsi.yellow(" Version jar exists but missing Automatic-Module-Name: minecraft — overwriting with SRG jar"));
Files.delete(targetJar);
}
Files.createDirectories(targetDir); Files.createDirectories(targetDir);
// Priority 1: SRG-mapped client jar from Forge libraries // Copy vanilla client jar — it has Automatic-Module-Name: minecraft
// This jar has Automatic-Module-Name: minecraft and correct SRG class names Path vanillaJar = versionsDir.resolve(mcVersion).resolve(mcVersion + ".jar");
Path srgJar = findSrgClientJar(); if (Files.exists(vanillaJar) && isValidJar(vanillaJar)) {
if (srgJar != null && isValidJar(srgJar)) { Files.copy(vanillaJar, targetJar);
Files.copy(srgJar, targetJar); System.out.println(ZAnsi.green(" Copied vanilla jar for securejarhandler: " + vanillaJar.getFileName() + "" + targetJar));
System.out.println(ZAnsi.green(" Copied SRG client jar for securejarhandler: " + srgJar.getFileName() + "" + targetJar));
return; return;
} }
// Fallback: vanilla version jar (obfuscated names, may cause module issues) System.out.println(ZAnsi.yellow(" No vanilla jar found at " + vanillaJar));
Path sourceJar = versionsDir.resolve(mcVersion).resolve(mcVersion + ".jar");
if (!Files.exists(sourceJar) || !isValidJar(sourceJar)) {
System.out.println(ZAnsi.yellow(" No suitable version jar found (SRG or vanilla)"));
return;
}
Files.copy(sourceJar, targetJar);
System.out.println(ZAnsi.yellow(" Copied vanilla jar (fallback) for securejarhandler: " + sourceJar.getFileName() + "" + targetJar));
} }
/** /**