diff --git a/build.gradle b/build.gradle index bc9a75869a..8c6cf1a58a 100644 --- a/build.gradle +++ b/build.gradle @@ -65,7 +65,7 @@ ext { APACHE_COMMONS_LANG3_VERSION = '3.12.0' JOPT_SIMPLE_VERSION = '5.0.4' COMMONS_IO_VERSION = '2.11.0' - JARJAR_VERSION = '0.3.0' + JARJAR_VERSION = '0.3.9' GIT_INFO = gradleutils.gitInfo VERSION = gradleutils.getFilteredMCTagOffsetBranchVersion(true, '[0-9]', MC_VERSION) diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/JarInJarDependencyLocator.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/JarInJarDependencyLocator.java index a1cd4a5520..295dae8624 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/JarInJarDependencyLocator.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/JarInJarDependencyLocator.java @@ -5,21 +5,28 @@ package net.minecraftforge.fml.loading.moddiscovery; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.mojang.logging.LogUtils; import net.minecraftforge.fml.loading.EarlyLoadingException; import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.locating.IModFile; +import net.minecraftforge.forgespi.locating.ModFileLoadingException; import net.minecraftforge.jarjar.selection.JarSelector; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.VersionRange; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -34,20 +41,16 @@ public class JarInJarDependencyLocator extends AbstractJarFileDependencyLocator } @Override - public List scanMods(final Iterable loadedMods) { + public List scanMods(final Iterable loadedMods) + { final List sources = Lists.newArrayList(); loadedMods.forEach(sources::add); - final List dependenciesToLoad = JarSelector.detectAndSelect( - sources, - this::loadResourceFromModFile, - this::loadModFileFrom, - this::identifyMod, - this::exception - ); + final List dependenciesToLoad = JarSelector.detectAndSelect(sources, this::loadResourceFromModFile, this::loadModFileFrom, this::identifyMod, this::exception); - if (dependenciesToLoad.isEmpty()) { + if (dependenciesToLoad.isEmpty()) + { LOGGER.info("No dependencies to load found. Skipping!"); return Collections.emptyList(); } @@ -68,46 +71,89 @@ public class JarInJarDependencyLocator extends AbstractJarFileDependencyLocator return IModFile.Type.GAMELIBRARY.name(); } + @SuppressWarnings("resource") + @Override + protected Optional loadModFileFrom(final IModFile file, final Path path) + { + try + { + final Path pathInModFile = file.findResource(path.toString()); + final URI filePathUri = new URI("jij:" + (pathInModFile.toAbsolutePath().toUri().getRawSchemeSpecificPart())).normalize(); + final Map outerFsArgs = ImmutableMap.of("packagePath", pathInModFile); + final FileSystem zipFS = FileSystems.newFileSystem(filePathUri, outerFsArgs); + final Path pathInFS = zipFS.getPath("/"); + return Optional.of(createMod(pathInFS).file()); + } + catch (Exception e) + { + LOGGER.error("Failed to load mod file {} from {}", path, file.getFileName()); + final RuntimeException exception = new ModFileLoadingException("Failed to load mod file " + file.getFileName()); + exception.initCause(e); + + throw exception; + } + } + protected EarlyLoadingException exception(Collection> failedDependencies) { final List errors = failedDependencies.stream() - .filter(entry -> !entry.sources().isEmpty()) //Should never be the case, but just to be sure - .map(entry -> new EarlyLoadingException.ExceptionData( - getErrorTranslationKey(entry), - entry.identifier().group() + ":" + entry.identifier().artifact(), - entry.sources() - .stream() - .flatMap(this::getModWithVersionRangeStream) - .map(this::formatError) - .collect(Collectors.joining(", ")))).toList(); + .filter(entry -> !entry.sources().isEmpty()) //Should never be the case, but just to be sure + .map(this::buildExceptionData) + .toList(); return new EarlyLoadingException(failedDependencies.size() + " Dependency restrictions were not met.", null, errors); } + @NotNull + private EarlyLoadingException.ExceptionData buildExceptionData(final JarSelector.ResolutionFailureInformation entry) + { + return new EarlyLoadingException.ExceptionData( + getErrorTranslationKey(entry), + entry.identifier().group() + ":" + entry.identifier().artifact(), + entry.sources() + .stream() + .flatMap(this::getModWithVersionRangeStream) + .map(this::formatError) + .collect(Collectors.joining(", ")) + ); + } + @NotNull private String getErrorTranslationKey(final JarSelector.ResolutionFailureInformation entry) { - return entry.failureReason() == JarSelector.FailureReason.VERSION_RESOLUTION_FAILED - ? "fml.dependencyloading.conflictingdependencies" - : "fml.dependencyloading.mismatchedcontaineddependencies"; + return entry.failureReason() == JarSelector.FailureReason.VERSION_RESOLUTION_FAILED ? + "fml.dependencyloading.conflictingdependencies" : + "fml.dependencyloading.mismatchedcontaineddependencies"; } @NotNull private Stream getModWithVersionRangeStream(final JarSelector.SourceWithRequestedVersionRange file) { - return file.sources().stream().map(IModFile::getModFileInfo) - .flatMap(modFileInfo -> modFileInfo.getMods().stream()) - .map(modInfo -> new ModWithVersionRange(modInfo, file.requestedVersionRange(), file.includedVersion())); + return file.sources() + .stream() + .map(IModFile::getModFileInfo) + .flatMap(modFileInfo -> modFileInfo.getMods().stream()) + .map(modInfo -> new ModWithVersionRange(modInfo, file.requestedVersionRange(), file.includedVersion())); } @NotNull private String formatError(final ModWithVersionRange modWithVersionRange) { - return "\u00a7e" + modWithVersionRange.modInfo().getModId() + "\u00a7r - \u00a74" - + modWithVersionRange.versionRange().toString() + "\u00a74 - \u00a72" - + modWithVersionRange.artifactVersion().toString() + "\u00a72"; + return "\u00a7e" + modWithVersionRange.modInfo().getModId() + "\u00a7r - \u00a74" + modWithVersionRange.versionRange().toString() + "\u00a74 - \u00a72" + modWithVersionRange.artifactVersion().toString() + "\u00a72"; } - private record ModWithVersionRange(IModInfo modInfo, VersionRange versionRange, ArtifactVersion artifactVersion) {} + @Override + protected String identifyMod(final IModFile modFile) + { + if (modFile.getModFileInfo() == null || modFile.getModInfos().isEmpty()) + { + return modFile.getFileName(); + } + + return modFile.getModInfos().stream().map(IModInfo::getModId).collect(Collectors.joining()); + } + + private record ModWithVersionRange(IModInfo modInfo, VersionRange versionRange, ArtifactVersion artifactVersion) + {} } diff --git a/src/test/resources/META-INF/jarjar/ForgeJiJTestMod-1.5.jar b/src/test/resources/META-INF/jarjar/ForgeJiJTestMod-1.5.jar new file mode 100644 index 0000000000..be2cb6620a Binary files /dev/null and b/src/test/resources/META-INF/jarjar/ForgeJiJTestMod-1.5.jar differ diff --git a/src/test/resources/META-INF/jarjar/metadata.json b/src/test/resources/META-INF/jarjar/metadata.json index e0fb91ebeb..0bf777d705 100644 --- a/src/test/resources/META-INF/jarjar/metadata.json +++ b/src/test/resources/META-INF/jarjar/metadata.json @@ -7,10 +7,11 @@ }, "version": { "range": "[1.0,)", - "artifactVersion": "1.2" + "artifactVersion": "1.5" }, + "_pathMixin_should_crash_on_startup": "META-INF/jarjar/ForgeJiJTestMod-1.5.jar", "path": "META-INF/jarjar/ForgeJiJTestMod-1.2.jar", - "_Broken_path": "META-INF/jarjar/jijroot-1.3.jar" + "_path_crash_test": "META-INF/jarjar/jijroot-1.3.jar" } ] } \ No newline at end of file