From 84d354a7ddd34dcd6196b8557ff12e174cd09d4a Mon Sep 17 00:00:00 2001 From: noeppi_noeppi <63002502+noeppi-noeppi@users.noreply.github.com> Date: Mon, 8 Aug 2022 15:07:38 +0200 Subject: [PATCH] Backport: Load custom ITransformationServices from the classpath in dev (#8350) --- .../fml/loading/ClasspathLocatorUtils.java | 38 ++++++++++++ .../ClasspathTransformerDiscoverer.java | 61 +++++++++++++++++++ .../moddiscovery/ClasspathLocator.java | 24 +------- ...er.serviceapi.ITransformerDiscoveryService | 3 +- 4 files changed, 103 insertions(+), 23 deletions(-) create mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/ClasspathLocatorUtils.java create mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/ClasspathTransformerDiscoverer.java diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/ClasspathLocatorUtils.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ClasspathLocatorUtils.java new file mode 100644 index 0000000000..da89557f02 --- /dev/null +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ClasspathLocatorUtils.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.fml.loading; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ClasspathLocatorUtils { + + private static final Logger LOGGER = LogManager.getLogger(); + + public static 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(LogMarkers.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/ClasspathTransformerDiscoverer.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ClasspathTransformerDiscoverer.java new file mode 100644 index 0000000000..6b8bbf1dfd --- /dev/null +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ClasspathTransformerDiscoverer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.fml.loading; + +import cpw.mods.modlauncher.api.NamedPath; +import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService; +import org.apache.logging.log4j.LogManager; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; + +public class ClasspathTransformerDiscoverer implements ITransformerDiscoveryService { + + private final List legacyClasspath = Arrays.stream(System.getProperty("legacyClassPath", "").split(File.pathSeparator)).map(Path::of).toList(); + + @Override + public List candidates(Path gameDirectory) { + return Collections.emptyList(); + } + + @Override + public List candidates(final Path gameDirectory, final String launchTarget) { + if (launchTarget != null && launchTarget.contains("dev")) { + this.scan(gameDirectory); + } + return List.copyOf(found); + } + + private final static List found = new ArrayList<>(); + + public static List allExcluded() { + return found.stream().map(np->np.paths()[0]).toList(); + } + + private void scan(final Path gameDirectory) { + try { + locateTransformers("META-INF/services/cpw.mods.modlauncher.api.ITransformationService"); + locateTransformers("META-INF/services/net.minecraftforge.forgespi.locating.IModLocator"); + } catch (IOException e) { + LogManager.getLogger().error("Error during discovery of transform services from the classpath", e); + } + } + + private void locateTransformers(String resource) throws IOException { + final Enumeration resources = ClassLoader.getSystemClassLoader().getResources(resource); + while (resources.hasMoreElements()) { + URL url = resources.nextElement(); + Path path = ClasspathLocatorUtils.findJarPathFor(resource, url.toString(), url); + if (legacyClasspath.stream().anyMatch(path::equals) || !Files.exists(path) || Files.isDirectory(path)) + continue; + found.add(new NamedPath(path.toUri().toString(), path)); + } + } +} 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 849ff43ac5..44b4a9015a 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 @@ -5,18 +5,16 @@ package net.minecraftforge.fml.loading.moddiscovery; +import net.minecraftforge.fml.loading.ClasspathLocatorUtils; import net.minecraftforge.fml.loading.LogMarkers; 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; @@ -58,7 +56,7 @@ public class ClasspathLocator extends AbstractJarFileModLocator { final Enumeration resources = ClassLoader.getSystemClassLoader().getResources(resource); while (resources.hasMoreElements()) { URL url = resources.nextElement(); - Path path = findJarPathFor(resource, resource, url); + Path path = ClasspathLocatorUtils.findJarPathFor(resource, resource, url); if (claimed.stream().anyMatch(path::equals) || !Files.exists(path) || Files.isDirectory(path)) continue; ret.add(path); @@ -71,22 +69,4 @@ public class ClasspathLocator extends AbstractJarFileModLocator { 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(LogMarkers.SCAN, "Failed to find JAR for class {} - {}", resourceName, jarName); - throw new RuntimeException("Unable to locate "+resourceName+" - "+jarName, e); - } - } } diff --git a/fmlloader/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService b/fmlloader/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService index 48b92283d6..8838a64024 100644 --- a/fmlloader/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService +++ b/fmlloader/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService @@ -1 +1,2 @@ -net.minecraftforge.fml.loading.ModDirTransformerDiscoverer \ No newline at end of file +net.minecraftforge.fml.loading.ModDirTransformerDiscoverer +net.minecraftforge.fml.loading.ClasspathTransformerDiscoverer \ No newline at end of file