From 072d1124a30da1fbe3827b7cc2948fbd45318326 Mon Sep 17 00:00:00 2001 From: Marc Hermans Date: Mon, 25 Mar 2024 10:37:43 +0100 Subject: [PATCH] Add support for locating mod sources with services from the classpath. (#93) Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com> --- .../loading/ClasspathTransformerDiscoverer.java | 15 +++++++++++++++ .../fml/loading/ModDirTransformerDiscoverer.java | 8 +------- .../loading/TransformerDiscovererConstants.java | 13 ++++++++++++- .../loading/moddiscovery/MinecraftLocator.java | 3 +++ .../fml/loading/targets/CommonLaunchHandler.java | 2 +- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/loader/src/main/java/net/neoforged/fml/loading/ClasspathTransformerDiscoverer.java b/loader/src/main/java/net/neoforged/fml/loading/ClasspathTransformerDiscoverer.java index 501959687..038e74908 100644 --- a/loader/src/main/java/net/neoforged/fml/loading/ClasspathTransformerDiscoverer.java +++ b/loader/src/main/java/net/neoforged/fml/loading/ClasspathTransformerDiscoverer.java @@ -7,6 +7,7 @@ import cpw.mods.modlauncher.api.NamedPath; import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService; +import net.neoforged.fml.loading.targets.CommonLaunchHandler; import org.apache.logging.log4j.LogManager; import java.io.File; @@ -16,6 +17,8 @@ import java.nio.file.Path; import java.util.*; +import static net.neoforged.fml.loading.TransformerDiscovererConstants.shouldLoadInServiceLayer; + public class ClasspathTransformerDiscoverer implements ITransformerDiscoveryService { private final List legacyClasspath = Arrays.stream(System.getProperty("legacyClassPath", "").split(File.pathSeparator)).map(Path::of).toList(); @@ -44,6 +47,8 @@ private void scan(final Path gameDirectory) { for (final String serviceClass : TransformerDiscovererConstants.SERVICES) { locateTransformers("META-INF/services/" + serviceClass); } + + scanModClasses(); } catch (IOException e) { LogManager.getLogger().error("Error during discovery of transform services from the classpath", e); } @@ -59,4 +64,14 @@ private void locateTransformers(String resource) throws IOException { found.add(new NamedPath(path.toUri().toString(), path)); } } + + private void scanModClasses() { + final Map> modClassPaths = CommonLaunchHandler.getModClasses(); + modClassPaths.forEach((modid, paths) -> { + if (shouldLoadInServiceLayer(paths.toArray(Path[]::new))) { + found.add(new NamedPath(modid, paths.toArray(Path[]::new))); + } + }); + } + } diff --git a/loader/src/main/java/net/neoforged/fml/loading/ModDirTransformerDiscoverer.java b/loader/src/main/java/net/neoforged/fml/loading/ModDirTransformerDiscoverer.java index 1d45de629..e5afd2afb 100644 --- a/loader/src/main/java/net/neoforged/fml/loading/ModDirTransformerDiscoverer.java +++ b/loader/src/main/java/net/neoforged/fml/loading/ModDirTransformerDiscoverer.java @@ -6,9 +6,6 @@ package net.neoforged.fml.loading; import com.mojang.logging.LogUtils; -import cpw.mods.jarhandling.JarContentsBuilder; -import cpw.mods.jarhandling.JarMetadata; -import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.api.LamdbaExceptionUtils; import cpw.mods.modlauncher.api.NamedPath; import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService; @@ -93,9 +90,6 @@ private static boolean shouldLoadInServiceLayer(Path path) { if (!path.toString().endsWith(".jar")) return false; if (LamdbaExceptionUtils.uncheck(() -> Files.size(path)) == 0) return false; - JarMetadata metadata = JarMetadata.from(new JarContentsBuilder().paths(path).build()); - return metadata.providers().stream() - .map(SecureJar.Provider::serviceName) - .anyMatch(TransformerDiscovererConstants.SERVICES::contains); + return TransformerDiscovererConstants.shouldLoadInServiceLayer(path); } } diff --git a/loader/src/main/java/net/neoforged/fml/loading/TransformerDiscovererConstants.java b/loader/src/main/java/net/neoforged/fml/loading/TransformerDiscovererConstants.java index e4afe967e..c328b22d6 100644 --- a/loader/src/main/java/net/neoforged/fml/loading/TransformerDiscovererConstants.java +++ b/loader/src/main/java/net/neoforged/fml/loading/TransformerDiscovererConstants.java @@ -5,16 +5,20 @@ package net.neoforged.fml.loading; +import cpw.mods.jarhandling.JarContentsBuilder; +import cpw.mods.jarhandling.JarMetadata; +import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.api.IModuleLayerManager.Layer; import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService; +import java.nio.file.Path; import java.util.Set; /** * Defines a class containing constants which implementations of {@link ITransformerDiscoveryService} * may use. */ -public class TransformerDiscovererConstants { +public final class TransformerDiscovererConstants { private TransformerDiscovererConstants() { } /** @@ -29,4 +33,11 @@ private TransformerDiscovererConstants() { } "net.neoforged.fml.loading.ImmediateWindowProvider", // FIXME: remove this when removing the legacy ImmediateWindowProvider "net.neoforged.neoforgespi.earlywindow.ImmediateWindowProvider" ); + + public static boolean shouldLoadInServiceLayer(Path... path) { + JarMetadata metadata = JarMetadata.from(new JarContentsBuilder().paths(path).build()); + return metadata.providers().stream() + .map(SecureJar.Provider::serviceName) + .anyMatch(SERVICES::contains); + } } diff --git a/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/MinecraftLocator.java b/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/MinecraftLocator.java index c5cd1c9ee..44b347739 100644 --- a/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/MinecraftLocator.java +++ b/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/MinecraftLocator.java @@ -9,6 +9,7 @@ import com.mojang.logging.LogUtils; import cpw.mods.jarhandling.JarContentsBuilder; import cpw.mods.jarhandling.SecureJar; +import net.neoforged.fml.loading.ClasspathTransformerDiscoverer; import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.LogMarkers; import net.neoforged.neoforgespi.language.IModFileInfo; @@ -47,7 +48,9 @@ public List scanMods() { .map(SecureJar::from) .map(sj -> new ModFile(sj, this, ModFileParser::modsTomlParser)) .collect(Collectors.toList()); + var otherModsExcluded = ClasspathTransformerDiscoverer.allExcluded(); var othermods = baseMC.otherModPaths().stream() + .filter(p -> p.stream().noneMatch(otherModsExcluded::contains)) //We cannot load MOD_CLASSES from the classpath if they are loaded on the SERVICE layer. .map(p -> createMod(p.toArray(Path[]::new))) .filter(Objects::nonNull); artifacts.add(mcjar); diff --git a/loader/src/main/java/net/neoforged/fml/loading/targets/CommonLaunchHandler.java b/loader/src/main/java/net/neoforged/fml/loading/targets/CommonLaunchHandler.java index a6286ded1..4725f020e 100644 --- a/loader/src/main/java/net/neoforged/fml/loading/targets/CommonLaunchHandler.java +++ b/loader/src/main/java/net/neoforged/fml/loading/targets/CommonLaunchHandler.java @@ -92,7 +92,7 @@ protected final List getFmlPaths(String[] classpath) { .toList(); } - protected final Map> getModClasses() { + public static Map> getModClasses() { final String modClasses = Optional.ofNullable(System.getenv("MOD_CLASSES")).orElse(""); LOGGER.debug(LogMarkers.CORE, "Got mod coordinates {} from env", modClasses);