From f58db7f941a858f43f0a9eb24f3f3a9a91c39c4a Mon Sep 17 00:00:00 2001 From: SashegDev Date: Mon, 13 Jul 2026 16:33:26 +0000 Subject: [PATCH] Fix 12: Add forge client jar to classpath (missing from version JSON libs) The forge patched client jar (forge--client.jar) contains all Minecraft classes with Automatic-Module-Name: minecraft, but it is NOT listed in the version JSON libraries array - so buildClasspathFromManifest does not include it on the -cp. FML discovers it by scanning the library directory, but securejarhandler only processes classpath entries to create named modules. This fix explicitly finds and prepends forge--client.jar to the classpath when launching Forge/NeoForge, so securejarhandler can create the minecraft module from it. --- .../launch/LaunchCommandBuilder.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 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 974eea6..18af34d 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,12 +63,7 @@ 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)) { - // Build classpath from manifest libraries only. - // The forge client jar (forge-*-client.jar) on the classpath - // contains the patched Minecraft classes and has - // Automatic-Module-Name: minecraft in its MANIFEST. - // We modify the ignoreList below to NOT exclude it, - // so securejarhandler creates the "minecraft" module from it. + // Build classpath from manifest libraries. String classpath; if (manifest != null) { classpath = buildClasspathFromManifest(manifest, false); @@ -79,6 +74,25 @@ public class LaunchCommandBuilder { classpath = buildVanillaClasspath(); } + // The forge client jar (forge-*-client.jar) is NOT listed in the + // version JSON's libraries array, so it's NOT on the classpath. + // FML discovers it by scanning the library directory, but + // securejarhandler only processes classpath entries. + // We add it explicitly so securejarhandler creates the "minecraft" + // module from its Automatic-Module-Name: minecraft. + String forgeVersion = instance.getMinecraftVersion() + "-" + instance.getLoaderVersion(); + Path forgeClientJar = instance.getPath().resolve("libraries") + .resolve("net/minecraftforge/forge") + .resolve(forgeVersion) + .resolve("forge-" + forgeVersion + "-client.jar"); + if (Files.exists(forgeClientJar) && isValidJar(forgeClientJar)) { + String sep = System.getProperty("os.name").toLowerCase().contains("win") ? ";" : ":"; + classpath = forgeClientJar.toAbsolutePath().toString() + sep + classpath; + System.out.println(ZAnsi.green(" Added forge client jar: " + forgeClientJar.getFileName())); + } else { + System.out.println(ZAnsi.yellow(" Forge client jar not found at " + forgeClientJar)); + } + command.add("-cp"); String cpFile = writeClasspathFile(classpath); command.add(cpFile);