From e6a6392565cd3fc412214f63157c5f7df3faf452 Mon Sep 17 00:00:00 2001 From: SashegDev Date: Mon, 13 Jul 2026 14:37:31 +0000 Subject: [PATCH] fix: dont intercept Forge -p, its a hardcoded bootstrap list not ${classpath} Forge manifest -p is 8 hardcoded bootstrap JARs using ${library_directory}, not ${classpath}. Intercepting it replaced those with ALL libraries causing duplicate module errors. Version jar stays on -cp only (not -p). --- .../launch/LaunchCommandBuilder.java | 41 ++++++------------- 1 file changed, 13 insertions(+), 28 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 8fdd0d3..e784e9d 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,50 +63,35 @@ 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 TWO classpaths for Forge/NeoForge: - // 1. modulePath: libraries only (for -p module path) — version jar excluded - // to prevent split-package conflict with Forge's "minecraft" module - // 2. classpath: libraries + version jar (for -cp classpath) — version jar - // included so PreparableReloadListener and other MC classes are loadable - String modulePath; + // Forge manifest's -p is a HARDCODED list of 8 bootstrap JARs + // (bootstraplauncher, securejarhandler, asm-*, JarJarFileSystems) + // using ${library_directory}. Version jar is NOT on -p. + // Put version jar on -cp only → PreparableReloadListener loadable, + // no _1._20._1 vs minecraft split-package conflict. String classpath; if (manifest != null) { - modulePath = buildClasspathFromManifest(manifest, false); classpath = buildClasspathFromManifest(manifest, true); } else { - modulePath = ""; classpath = ""; } - if (modulePath == null || modulePath.isEmpty()) { - modulePath = buildVanillaClasspath(); - } if (classpath == null || classpath.isEmpty()) { - classpath = modulePath; + classpath = buildVanillaClasspath(); } command.add("-cp"); String cpFile = writeClasspathFile(classpath); - String mpFile = writeClasspathFile(modulePath); command.add(cpFile); - // Add JVM arguments from version.json manifest. - // Intercept -p / --module-path to use mpFile (no version jar) - // and -cp / --classpath to skip (we already added our own -cp). + // Add JVM arguments from version.json manifest as-is. + // Forge's -p is a HARDCODED list of 8 bootstrap JARs (bootstraplauncher, + // securejarhandler, asm-*, JarJarFileSystems) — NOT ${classpath}. + // Do NOT intercept it. Version jar stays on -cp only (not -p), + // preventing _1._20._1 vs minecraft split-package conflicts. if (manifest != null) { Map vars = buildVariableMap(options); vars.put("classpath", cpFile); - List jvmArgs = manifest.getJvmArguments(); - for (int i = 0; i < jvmArgs.size(); i++) { - String raw = jvmArgs.get(i); - if (("-p".equals(raw) || "--module-path".equals(raw)) && i + 1 < jvmArgs.size()) { - command.add(raw); - i++; - command.add(mpFile); - } else if (("-cp".equals(raw) || "--classpath".equals(raw)) && i + 1 < jvmArgs.size()) { - i++; - } else { - command.add(resolveVariable(raw, vars)); - } + for (String arg : manifest.getJvmArguments()) { + command.add(resolveVariable(arg, vars)); } }