diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java index e210ecdf68..bc44581c29 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java @@ -173,7 +173,7 @@ public class FMLLoader { } public static void addAccessTransformer(Path atPath, ModFile modName) { - LOGGER.debug(SCAN, "Adding Access Transformer in {}", modName.getFilePath()); + LOGGER.debug(SCAN, "Adding Access Transformer {} in {}", atPath, modName.getFilePath()); accessTransformer.offerResource(atPath, modName.getFileName()); } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/LoadingModList.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/LoadingModList.java index 7b7947821e..2d81a2dde9 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/LoadingModList.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/LoadingModList.java @@ -5,11 +5,14 @@ package net.minecraftforge.fml.loading; +import com.mojang.logging.LogUtils; +import net.minecraftforge.fml.loading.EarlyLoadingException.ExceptionData; import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.forgespi.locating.IModFile; +import org.slf4j.Logger; import java.nio.file.Files; import java.nio.file.Path; @@ -24,6 +27,7 @@ import java.util.stream.Collectors; * loading package */ public class LoadingModList { + private static final Logger LOGGER = LogUtils.getLogger(); private static LoadingModList INSTANCE; private final List modFiles; private final List sortedList; @@ -65,13 +69,22 @@ public class LoadingModList { } public void addAccessTransformers() { + var errors = new ArrayList(); + for (ModFileInfo modFile : modFiles) { ModFile mod = modFile.getFile(); - var at = mod.getAccessTransformer().orElse(null); - if (at != null) { - FMLLoader.addAccessTransformer(at, mod); + for (var at : mod.getAccessTransformers()) { + if (!Files.exists(at)) { + var message = "Invalid mod file: " + modFile.getFile().getFileName() + ". Missing Access Transformer: " + at; + errors.add(new ExceptionData(message)); + LOGGER.error(message); + } else + FMLLoader.addAccessTransformer(at, mod); } } + + if (!errors.isEmpty()) + preLoadErrors.add(new EarlyLoadingException("Invalid Access Transformers", null, errors)); } public void addForScanning(BackgroundScanHandler backgroundScanHandler) { diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java index 3c033d878b..8bdd47f6ee 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java @@ -50,6 +50,7 @@ public class ModFile implements IModFile { private CompletableFuture futureScanResult; private List coreMods; private Path accessTransformer; + private List accessTransformers = Collections.emptyList(); static final Attributes.Name TYPE = new Attributes.Name("FMLModType"); private SecureJar.Status securityStatus; @@ -92,8 +93,14 @@ public class ModFile implements IModFile { return modFileInfo.getMods(); } + /** @deprecated Use {@link #getAccessTransformers()} instead */ + @Deprecated(forRemoval = true, since = "1.21.11") public Optional getAccessTransformer() { - return Optional.ofNullable(Files.exists(accessTransformer) ? accessTransformer : null); + return Optional.ofNullable(accessTransformer); + } + + public List getAccessTransformers() { + return this.accessTransformers; } public boolean identifyMods() { @@ -104,7 +111,29 @@ public class ModFile implements IModFile { LOGGER.warn("Mod file {} contains javascript coremods! JS CoreMods are deprecated and will be removed in a future release. Consider using Mixin or ModLauncher transformers.", this.getFileName()); for (var mi : this.coreMods) LOGGER.debug(LogMarkers.LOADING, "Found coremod {}", mi.getPath()); - this.accessTransformer = findResource("META-INF", "accesstransformer.cfg"); + + List cfg; + // Note: Some mods may have invalid tomls copied from other projects. + // Unfortunately we must protect against those landmines. + try { + cfg = this.modFileInfo.getConfig().>getConfigElement("accessTransformers").orElse(null); + } catch (Exception e) { + cfg = null; + LOGGER.warn("{} contains an invalid 'accessTransformers' TOML entry. Should be e.g. accessTransformers = [\"META-INF/accesstransformer.cfg\", \"META-INF/extra_at.cfg\"] or accessTransformers = [] for no ATs. Falling back to default.", this.getFileName()); + } + if (cfg == null) { + var path = findResource("META-INF", "accesstransformer.cfg"); + if (Files.exists(path)) { + this.accessTransformer = path; + this.accessTransformers = List.of(path); + } + } else if (!cfg.isEmpty()) { + var paths = new ArrayList(cfg.size()); + for (var path : cfg) + paths.add(getSecureJar().getPath(path.replace('\\', '/'))); + this.accessTransformers = List.copyOf(paths); + } + return true; } diff --git a/mdk/src/main/resources/META-INF/mods.toml b/mdk/src/main/resources/META-INF/mods.toml index 904335467c..7859faedbb 100644 --- a/mdk/src/main/resources/META-INF/mods.toml +++ b/mdk/src/main/resources/META-INF/mods.toml @@ -19,6 +19,12 @@ displayName="Example Mod" authors="YourNameHere, OtherNameHere" #optional #displayTest="MATCH_VERSION" #optional, default=MATCH_VERSION when not clientSideOnly, else IGNORE_ALL_VERSION +# Access Transformers +# Optional, if not specified Forge will attempt to find the default META-INF/accesstransformer.cfg and silently continue if not found. May default to an empty list in a future MC. +# If you specify AT path strings in this list, Forge will attempt to load each of them and throw errors for any that aren't found. +# Specifying an empty list when your mod has no ATs is recommended to opt-out of the default for slightly better loading performance. +#accessTransformers = [] + description='''Example mod description. Newline characters can be used like this, and rendered on the mods screen properly.'''