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
// 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<String, String> vars = buildVariableMap(options);
vars.put("classpath", cpFile);
List<String> 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));
}
}