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).
This commit is contained in:
SashegDev
2026-07-13 14:37:31 +00:00
parent 1efd283234
commit e6a6392565
@@ -63,50 +63,35 @@ public class LaunchCommandBuilder {
// always use ModLauncher as main class (version.json might have // always use ModLauncher as main class (version.json might have
// BootstrapLauncher which breaks with Java module system) // BootstrapLauncher which breaks with Java module system)
if ("forge".equals(loaderType) || "neoforge".equals(loaderType)) { if ("forge".equals(loaderType) || "neoforge".equals(loaderType)) {
// Build TWO classpaths for Forge/NeoForge: // Forge manifest's -p is a HARDCODED list of 8 bootstrap JARs
// 1. modulePath: libraries only (for -p module path) — version jar excluded // (bootstraplauncher, securejarhandler, asm-*, JarJarFileSystems)
// to prevent split-package conflict with Forge's "minecraft" module // using ${library_directory}. Version jar is NOT on -p.
// 2. classpath: libraries + version jar (for -cp classpath) — version jar // Put version jar on -cp only → PreparableReloadListener loadable,
// included so PreparableReloadListener and other MC classes are loadable // no _1._20._1 vs minecraft split-package conflict.
String modulePath;
String classpath; String classpath;
if (manifest != null) { if (manifest != null) {
modulePath = buildClasspathFromManifest(manifest, false);
classpath = buildClasspathFromManifest(manifest, true); classpath = buildClasspathFromManifest(manifest, true);
} else { } else {
modulePath = "";
classpath = ""; classpath = "";
} }
if (modulePath == null || modulePath.isEmpty()) {
modulePath = buildVanillaClasspath();
}
if (classpath == null || classpath.isEmpty()) { if (classpath == null || classpath.isEmpty()) {
classpath = modulePath; classpath = buildVanillaClasspath();
} }
command.add("-cp"); command.add("-cp");
String cpFile = writeClasspathFile(classpath); String cpFile = writeClasspathFile(classpath);
String mpFile = writeClasspathFile(modulePath);
command.add(cpFile); command.add(cpFile);
// Add JVM arguments from version.json manifest. // Add JVM arguments from version.json manifest as-is.
// Intercept -p / --module-path to use mpFile (no version jar) // Forge's -p is a HARDCODED list of 8 bootstrap JARs (bootstraplauncher,
// and -cp / --classpath to skip (we already added our own -cp). // 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) { if (manifest != null) {
Map<String, String> vars = buildVariableMap(options); Map<String, String> vars = buildVariableMap(options);
vars.put("classpath", cpFile); vars.put("classpath", cpFile);
List<String> jvmArgs = manifest.getJvmArguments(); for (String arg : manifest.getJvmArguments()) {
for (int i = 0; i < jvmArgs.size(); i++) { command.add(resolveVariable(arg, vars));
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));
}
} }
} }