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.
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
String classpath;
if (manifest != null) {
@@ -698,17 +703,13 @@ public class LaunchCommandBuilder {
/**
* 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
* names) and have Automatic-Module-Name: minecraft in its MANIFEST.MF.
* Without this, securejarhandler creates an automatic module from the
* 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)
* Without this, findVersionJar() falls back to versions/1.20.1/1.20.1.jar
* which produces module _1._20._1, causing split-package conflicts with
* the minecraft module.
*/
private void ensureVersionJarForForge() throws IOException {
String versionId = getVersionId();
@@ -719,34 +720,21 @@ public class LaunchCommandBuilder {
Path targetJar = targetDir.resolve(versionId + ".jar");
if (Files.exists(targetJar) && isValidJar(targetJar)) {
if (hasMinecraftModuleName(targetJar)) {
System.out.println(ZAnsi.green(" Version jar already exists with correct module name: " + targetJar));
return;
}
System.out.println(ZAnsi.yellow(" Version jar exists but missing Automatic-Module-Name: minecraft — overwriting with SRG jar"));
Files.delete(targetJar);
System.out.println(ZAnsi.green(" Version jar already exists: " + targetJar));
return;
}
Files.createDirectories(targetDir);
// Priority 1: SRG-mapped client jar from Forge libraries
// This jar has Automatic-Module-Name: minecraft and correct SRG class names
Path srgJar = findSrgClientJar();
if (srgJar != null && isValidJar(srgJar)) {
Files.copy(srgJar, targetJar);
System.out.println(ZAnsi.green(" Copied SRG client jar for securejarhandler: " + srgJar.getFileName() + "" + targetJar));
// Copy vanilla client jar — it has Automatic-Module-Name: minecraft
Path vanillaJar = versionsDir.resolve(mcVersion).resolve(mcVersion + ".jar");
if (Files.exists(vanillaJar) && isValidJar(vanillaJar)) {
Files.copy(vanillaJar, targetJar);
System.out.println(ZAnsi.green(" Copied vanilla jar for securejarhandler: " + vanillaJar.getFileName() + "" + targetJar));
return;
}
// Fallback: vanilla version jar (obfuscated names, may cause module issues)
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));
System.out.println(ZAnsi.yellow(" No vanilla jar found at " + vanillaJar));
}
/**