From e85be8a6218cf42a5439b1a9e5d69b04bf6a02b3 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 23 Mar 2026 14:18:49 -0400 Subject: [PATCH] Add support for multiple access transformer configs. --- .../minecraftforge/fml/loading/FMLLoader.java | 2 +- .../fml/loading/LoadingModList.java | 22 ++++++++++-- .../fml/loading/moddiscovery/ModFile.java | 34 +++++++++++++++++-- mdk/src/main/resources/META-INF/mods.toml | 6 ++++ 4 files changed, 57 insertions(+), 7 deletions(-) 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 9ec3dd687f..0418597fb9 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java @@ -190,7 +190,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 6f48b42b46..f891e3e92d 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/LoadingModList.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/LoadingModList.java @@ -5,12 +5,14 @@ package net.minecraftforge.fml.loading; +import com.mojang.logging.LogUtils; import cpw.mods.modlauncher.api.LamdbaExceptionUtils; 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.net.URL; import java.nio.file.Files; @@ -30,6 +32,7 @@ import java.util.stream.Collectors; */ public class LoadingModList { + private static final Logger LOGGER = LogUtils.getLogger(); private static LoadingModList INSTANCE; private final List modFiles; private final List sortedList; @@ -78,9 +81,22 @@ public class LoadingModList public void addAccessTransformers() { - modFiles.stream() - .map(ModFileInfo::getFile) - .forEach(mod -> mod.getAccessTransformer().ifPresent(path -> FMLLoader.addAccessTransformer(path, mod))); + var errors = new ArrayList(); + for (ModFileInfo modFile : modFiles) { + ModFile mod = modFile.getFile(); + for (Path at : mod.getAccessTransformers()) { + if (!Files.exists(at)) { + var message = "Invalid mod file: " + modFile.getFile().getFileName() + ". Missing Access Transformer: " + at; + errors.add(new EarlyLoadingException.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 76475da581..026f064dbb 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 @@ -52,6 +52,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; @@ -94,9 +95,15 @@ public class ModFile implements IModFile { public List getModInfos() { 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 accessTransformers; } public boolean identifyMods() { @@ -105,7 +112,28 @@ public class ModFile implements IModFile { LOGGER.debug(LogMarkers.LOADING,"Loading mod file {} with languages {}", this.getFilePath(), this.modFileInfo.requiredLanguageLoaders()); this.coreMods = ModFileParser.getCoreMods(this); this.coreMods.forEach(mi-> 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.'''