diff --git a/Jenkinsfile b/Jenkinsfile index 4507c95b6f..2f97372ae8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,7 +7,7 @@ pipeline { agent { docker { image 'gradle:7-jdk16' - args '-v forgegc:/home/gradle/.gradle/' + args '-v forgegc:/home/gradle/.gradle_cache/' } } environment { @@ -34,6 +34,13 @@ pipeline { ) } } + stage('pull_cache') { + steps { + sh 'cp -rv /home/gradle/.gradle_cache/jdks/ /home/gradle/.gradle/jdks/' + sh 'cp -rv /home/gradle/.gradle_cache/wrapper/ /home/gradle/.gradle/wrapper/' + sh 'cp -rv /home/gradle/.gradle_cache/caches/ /home/gradle/.gradle/caches/' + } + } stage('setup') { steps { withGradle { diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java index 7c4dc9fb16..ec227d0f84 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java @@ -19,30 +19,23 @@ package net.minecraftforge.fml.loading; -import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.api.*; import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.OptionSpecBuilder; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.forgespi.Environment; -import net.minecraftforge.forgespi.locating.IModFile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; -import java.nio.file.Path; -import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; -import java.util.stream.Collectors; - import static net.minecraftforge.fml.loading.LogMarkers.CORE; public class FMLServiceProvider implements ITransformationService diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/LibraryFinder.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/LibraryFinder.java index 66b23660f9..9b0d99e0fa 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/LibraryFinder.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/LibraryFinder.java @@ -44,11 +44,18 @@ public class LibraryFinder { return libsPath; } + // Not used anywhere in Forge's codebase, scheduled for deletion unless a good need is expressed. + @Deprecated(forRemoval = true, since = "1.171.1") public static Path findJarPathFor(final String className, final String jarName) { final URL resource = LibraryFinder.class.getClassLoader().getResource(className); return findJarPathFor(className, jarName, resource); } + /* + * Only used in ClasspathLocator now, so moved too a private method and depreciated this. + * Scheduled for deletion unless a good need is expressed. + */ + @Deprecated(forRemoval = true, since = "1.171.1") public static Path findJarPathFor(final String resourceName, final String jarName, final URL resource) { try { Path path; diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/AbstractJarFileLocator.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/AbstractJarFileLocator.java index 1fdfc1a3b6..a74b355c27 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/AbstractJarFileLocator.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/AbstractJarFileLocator.java @@ -20,6 +20,10 @@ package net.minecraftforge.fml.loading.moddiscovery; import cpw.mods.jarhandling.SecureJar; +import cpw.mods.jarhandling.JarMetadata; +import net.minecraftforge.forgespi.language.IConfigurable; +import net.minecraftforge.forgespi.language.IModFileInfo; +import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.locating.IModFile; import net.minecraftforge.forgespi.locating.IModLocator; import org.apache.logging.log4j.LogManager; @@ -28,7 +32,10 @@ import org.apache.logging.log4j.Logger; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; @@ -38,6 +45,8 @@ import static net.minecraftforge.fml.loading.LogMarkers.SCAN; public abstract class AbstractJarFileLocator implements IModLocator { private static final Logger LOGGER = LogManager.getLogger(); + protected static final String MODS_TOML = "META-INF/mods.toml"; + protected static final String MANIFEST = "META-INF/MANIFEST.MF"; @Override public void scanFile(final IModFile file, final Consumer pathConsumer) { @@ -54,7 +63,9 @@ public abstract class AbstractJarFileLocator implements IModLocator { @Override public List scanMods() { return scanCandidates() - .map(mc -> ModFile.newFMLInstance(this, mc)) + .map(this::createMod) + .filter(Optional::isPresent) + .map(Optional::get) .collect(Collectors.toList()); } @@ -64,4 +75,63 @@ public abstract class AbstractJarFileLocator implements IModLocator { public boolean isValid(final IModFile modFile) { return true; } + + private Optional createMod(Path path) { + var mjm = new ModJarMetadata(); + var sj = SecureJar.from(() -> ModFile.DEFAULTMANIFEST, + jar -> jar.getManifest() == ModFile.DEFAULTMANIFEST ? mjm : JarMetadata.from(jar, path), + (root, p) -> true, + path + ); + + IModFile mod = null; + var type = sj.getManifest().getMainAttributes().getValue(ModFile.TYPE); + if (sj.findFile(MODS_TOML).isPresent()) { + LOGGER.debug(SCAN, "Found {} mod of type {}: {}", MODS_TOML, type, path); + mod = ModFile.newFMLInstance(this, sj); + } else if (type != null) { + LOGGER.debug(SCAN, "Found {} mod of type {}: {}", MANIFEST, type, path); + mod = new ModFile(sj, this, this::manifestParser); + } else { + return Optional.empty(); + } + + mjm.setModFile(mod); + return Optional.ofNullable(mod); + } + + private IModFileInfo manifestParser(final IModFile mod) { + Function> cfg = name -> Optional.ofNullable(mod.getSecureJar().getManifest().getMainAttributes().getValue(name)); + var license = cfg.apply("LICENSE").orElse(""); + var dummy = new IConfigurable() { + @Override + public Optional getConfigElement(String... key) { + return Optional.empty(); + } + @Override + public List getConfigList(String... key) { + return Collections.emptyList(); + } + }; + + return new IModFileInfo() { + @Override public List getMods() { return Collections.emptyList(); } + @Override public List requiredLanguageLoaders() { return Collections.emptyList(); } + @Override public boolean showAsResourcePack() { return false; } + @Override public Map getFileProperties() { return Collections.emptyMap(); } + @Override public String getLicense() { return license; } + @Override public IModFile getFile() { return mod; } + @Override public IConfigurable getConfig() { return dummy; } + + // These Should never be called as it's only called from ModJarMetadata.version and we bypass that + @Override public String moduleName() { return mod.getSecureJar().name(); } + @Override public String versionString() { return null; } + @Override public List usesServices() { return null; } + + @Override + public String toString() { + return "IModFileInfo(" + mod.getFilePath() + ")"; + } + }; + } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ClasspathLocator.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ClasspathLocator.java index 798a09f5a7..0c9d22bb27 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ClasspathLocator.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ClasspathLocator.java @@ -19,29 +19,27 @@ package net.minecraftforge.fml.loading.moddiscovery; -import cpw.mods.jarhandling.SecureJar; -import net.minecraftforge.fml.loading.LibraryFinder; -import net.minecraftforge.forgespi.locating.IModFile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.Map; -import java.util.function.Predicate; import java.util.stream.Stream; -import static net.minecraftforge.fml.loading.LogMarkers.CORE; +import static net.minecraftforge.fml.loading.LogMarkers.SCAN; public class ClasspathLocator extends AbstractJarFileLocator { private static final Logger LOGGER = LogManager.getLogger(); - private static final String MODS_TOML = "META-INF/mods.toml"; - private static final String MANIFEST = "META-INF/MANIFEST.MF"; private final List legacyClasspath = Arrays.stream(System.getProperty("legacyClassPath", "").split(File.pathSeparator)).map(Path::of).toList(); private boolean enabled = false; @@ -51,38 +49,35 @@ public class ClasspathLocator extends AbstractJarFileLocator { } @Override - public List scanMods() { + public Stream scanCandidates() { if (!enabled) - return List.of(); + return Stream.of(); + try { - var modCoords = Stream.builder(); - locateMods(modCoords, MODS_TOML, "classpath_mod", sj -> true); - locateMods(modCoords, MANIFEST, "manifest_jar", sj -> sj.getManifest() != ModFile.DEFAULTMANIFEST && sj.getManifest().getMainAttributes().getValue(ModFile.TYPE) != null); - return modCoords.build().toList(); + var claimed = new ArrayList<>(legacyClasspath); + var paths = Stream.builder(); + + findPaths(claimed, MODS_TOML).forEach(paths::add); + findPaths(claimed, MANIFEST).forEach(paths::add); + + return paths.build(); } catch (IOException e) { - LOGGER.fatal(CORE, "Error trying to find resources", e); + LOGGER.fatal(SCAN, "Error trying to find resources", e); throw new RuntimeException(e); } } - @Override - public Stream scanCandidates() { - return Stream.of(); - } - - private void locateMods(Stream.Builder modCoords, String resource, String name, Predicate filter) throws IOException { + private List findPaths(List claimed, String resource) throws IOException { + var ret = new ArrayList(); final Enumeration resources = ClassLoader.getSystemClassLoader().getResources(resource); while (resources.hasMoreElements()) { URL url = resources.nextElement(); - Path path = LibraryFinder.findJarPathFor(resource, name, url); - if (legacyClasspath.stream().anyMatch(path::equals) || Files.isDirectory(path)) + Path path = findJarPathFor(resource, resource, url); + if (claimed.stream().anyMatch(path::equals) || !Files.exists(path) || Files.isDirectory(path)) continue; - - ModJarMetadata.buildFile(this, filter, path).ifPresent(mf -> { - LOGGER.debug(CORE, "Found classpath mod: {}", path); - modCoords.add(mf); - }); + ret.add(path); } + return ret; } @Override @@ -90,4 +85,22 @@ public class ClasspathLocator extends AbstractJarFileLocator { var launchTarget = (String) arguments.get("launchTarget"); enabled = launchTarget != null && launchTarget.contains("dev"); } + + private Path findJarPathFor(final String resourceName, final String jarName, final URL resource) { + try { + Path path; + final URI uri = resource.toURI(); + if (uri.getScheme().equals("jar") && uri.getRawSchemeSpecificPart().contains("!/")) { + int lastExcl = uri.getRawSchemeSpecificPart().lastIndexOf("!/"); + path = Paths.get(new URI(uri.getRawSchemeSpecificPart().substring(0, lastExcl))); + } else { + path = Paths.get(new URI("file://"+uri.getRawSchemeSpecificPart().substring(0, uri.getRawSchemeSpecificPart().length()-resourceName.length()))); + } + //LOGGER.debug(CORE, "Found JAR {} at path {}", jarName, path.toString()); + return path; + } catch (NullPointerException | URISyntaxException e) { + LOGGER.fatal(SCAN, "Failed to find JAR for class {} - {}", resourceName, jarName); + throw new RuntimeException("Unable to locate "+resourceName+" - "+jarName, e); + } + } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModJarMetadata.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModJarMetadata.java index 5cd2005110..6613691223 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModJarMetadata.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModJarMetadata.java @@ -41,7 +41,7 @@ public final class ModJarMetadata implements JarMetadata { } } - private ModJarMetadata() { + ModJarMetadata() { } public void setModFile(IModFile file) { diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModsFolderLocator.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModsFolderLocator.java index 8cb724e58a..d5efb19d5b 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModsFolderLocator.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModsFolderLocator.java @@ -22,16 +22,13 @@ package net.minecraftforge.fml.loading.moddiscovery; import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.fml.loading.ModDirTransformerDiscoverer; import net.minecraftforge.fml.loading.StringUtils; -import net.minecraftforge.forgespi.locating.IModFile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.nio.file.Files; import java.nio.file.Path; import java.util.Comparator; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import java.util.stream.Stream; import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.uncheck;