From 6cbf8a6549501e5f9c09e2946ee07d3583c8c0ea Mon Sep 17 00:00:00 2001 From: SashegDev Date: Mon, 13 Jul 2026 16:05:28 +0000 Subject: [PATCH] Fix 10: Add copied version jar to classpath for securejarhandler minecraft module The copied version jar (1.20.1-forge-47.4.20.jar) is now on -cp so securejarhandler can scan it and create the minecraft module. The jar name does not match the ignoreList pattern forge- (starts with 1), so it is included in the module layer. This ensures PreparableReloadListener and other vanilla classes are findable in the minecraft module. --- .../launch/LaunchCommandBuilder.java | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/launcher/launcher/src/main/java/sashegdev/zernmc/launcher/minecraft/launch/LaunchCommandBuilder.java b/launcher/launcher/src/main/java/sashegdev/zernmc/launcher/minecraft/launch/LaunchCommandBuilder.java index faffc0b..c58add8 100644 --- a/launcher/launcher/src/main/java/sashegdev/zernmc/launcher/minecraft/launch/LaunchCommandBuilder.java +++ b/launcher/launcher/src/main/java/sashegdev/zernmc/launcher/minecraft/launch/LaunchCommandBuilder.java @@ -63,19 +63,18 @@ public class LaunchCommandBuilder { // always use ModLauncher as main class (version.json might have // BootstrapLauncher which breaks with Java module system) if ("forge".equals(loaderType) || "neoforge".equals(loaderType)) { - // Ensure securejarhandler can create the "minecraft" module: - // It looks for versions//.jar. - // The Forge installer only creates the JSON there, not the jar. - // We copy the vanilla version jar (e.g. versions/1.20.1/1.20.1.jar) - // to that location so securejarhandler finds it and creates the - // "minecraft" module (identified by Automatic-Module-Name: minecraft - // in the jar's MANIFEST.MF). + // Ensure securejarhandler can create the "minecraft" module. + // The Forge installer only creates versions//.json, + // NOT the jar. We copy the vanilla version jar there so + // securejarhandler finds it and creates the "minecraft" module. ensureVersionJarForForge(); - // Build classpath from manifest libraries only (no version jar on -cp). - // Putting the vanilla jar on -cp would create automatic module _1._20._1 - // (from filename 1.20.1.jar) which conflicts with the "minecraft" module - // created by securejarhandler → split-package ResolutionException. + // Build classpath from manifest libraries + the copied version jar. + // The copied jar (e.g. 1.20.1-forge-47.4.20.jar) does NOT match the + // "-DignoreList" pattern "forge-" (it starts with "1", not "forge-"), + // so securejarhandler will include it in the module layer. + // It also won't create automatic module "_1._20._1" because the + // filename is "1.20.1-forge-47.4.20.jar", not "1.20.1.jar". String classpath; if (manifest != null) { classpath = buildClasspathFromManifest(manifest, false); @@ -86,6 +85,18 @@ public class LaunchCommandBuilder { classpath = buildVanillaClasspath(); } + // Add the copied version jar to classpath (if it exists). + // securejarhandler scans classpath JARs and creates modules. + // The jar name "1.20.1-forge-47.4.20.jar" is NOT in ignoreList, + // so it becomes a proper module with Automatic-Module-Name: minecraft. + Path copiedVersionJar = instance.getPath().resolve("versions") + .resolve(getVersionId()).resolve(getVersionId() + ".jar"); + if (Files.exists(copiedVersionJar) && isValidJar(copiedVersionJar)) { + String sep = System.getProperty("os.name").toLowerCase().contains("win") ? ";" : ":"; + classpath = copiedVersionJar.toAbsolutePath().toString() + sep + classpath; + System.out.println(ZAnsi.green(" Added version jar for minecraft module: " + copiedVersionJar.getFileName())); + } + command.add("-cp"); String cpFile = writeClasspathFile(classpath); command.add(cpFile);