diff --git a/src/main/java/net/fabricmc/loader/impl/discovery/BuiltinMetadataWrapper.java b/src/main/java/net/fabricmc/loader/impl/discovery/BuiltinMetadataWrapper.java index e6888687d..f94391d67 100644 --- a/src/main/java/net/fabricmc/loader/impl/discovery/BuiltinMetadataWrapper.java +++ b/src/main/java/net/fabricmc/loader/impl/discovery/BuiltinMetadataWrapper.java @@ -23,6 +23,7 @@ import java.util.Optional; import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.Version; import net.fabricmc.loader.api.metadata.ContactInformation; import net.fabricmc.loader.api.metadata.CustomValue; @@ -138,7 +139,7 @@ public Collection getJars() { } @Override - public Collection getMixinConfigs(EnvType type) { + public Collection getMixinConfigs(EnvType type, FabricLoader loader) { return Collections.emptyList(); } diff --git a/src/main/java/net/fabricmc/loader/impl/launch/FabricMixinBootstrap.java b/src/main/java/net/fabricmc/loader/impl/launch/FabricMixinBootstrap.java index 582b2c89b..f9731f739 100644 --- a/src/main/java/net/fabricmc/loader/impl/launch/FabricMixinBootstrap.java +++ b/src/main/java/net/fabricmc/loader/impl/launch/FabricMixinBootstrap.java @@ -80,7 +80,7 @@ public static void init(EnvType side, FabricLoaderImpl loader) { Map configToModMap = new HashMap<>(); for (ModContainerImpl mod : loader.getModsInternal()) { - for (String config : mod.getMetadata().getMixinConfigs(side)) { + for (String config : mod.getMetadata().getMixinConfigs(side, loader)) { ModContainerImpl prev = configToModMap.putIfAbsent(config, mod); if (prev != null) throw new RuntimeException(String.format("Non-unique mixin config name %s used by %s and %s", config, prev.getMetadata().getId(), mod.getMetadata().getId())); diff --git a/src/main/java/net/fabricmc/loader/impl/metadata/LoaderModMetadata.java b/src/main/java/net/fabricmc/loader/impl/metadata/LoaderModMetadata.java index ef0807596..217266ea8 100644 --- a/src/main/java/net/fabricmc/loader/impl/metadata/LoaderModMetadata.java +++ b/src/main/java/net/fabricmc/loader/impl/metadata/LoaderModMetadata.java @@ -21,6 +21,7 @@ import java.util.Map; import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; /** * Internal variant of the ModMetadata interface. @@ -35,7 +36,7 @@ default String getOldStyleLanguageAdapter() { Map getLanguageAdapterDefinitions(); Collection getJars(); - Collection getMixinConfigs(EnvType type); + Collection getMixinConfigs(EnvType type, FabricLoader loader); /* @Nullable */ String getAccessWidener(); @Override diff --git a/src/main/java/net/fabricmc/loader/impl/metadata/V0ModMetadata.java b/src/main/java/net/fabricmc/loader/impl/metadata/V0ModMetadata.java index 82c814ba7..17e29d659 100644 --- a/src/main/java/net/fabricmc/loader/impl/metadata/V0ModMetadata.java +++ b/src/main/java/net/fabricmc/loader/impl/metadata/V0ModMetadata.java @@ -24,6 +24,7 @@ import java.util.Optional; import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.Version; import net.fabricmc.loader.api.metadata.ContactInformation; import net.fabricmc.loader.api.metadata.CustomValue; @@ -221,7 +222,7 @@ public Collection getEntrypointKeys() { public void emitFormatWarnings() { } @Override - public Collection getMixinConfigs(EnvType type) { + public Collection getMixinConfigs(EnvType type, FabricLoader loader) { List mixinConfigs = new ArrayList<>(this.mixins.common); switch (type) { diff --git a/src/main/java/net/fabricmc/loader/impl/metadata/V1ModMetadata.java b/src/main/java/net/fabricmc/loader/impl/metadata/V1ModMetadata.java index 5f00b8429..04dd7785c 100644 --- a/src/main/java/net/fabricmc/loader/impl/metadata/V1ModMetadata.java +++ b/src/main/java/net/fabricmc/loader/impl/metadata/V1ModMetadata.java @@ -22,9 +22,11 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.SortedMap; import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.Version; import net.fabricmc.loader.api.metadata.ContactInformation; import net.fabricmc.loader.api.metadata.CustomValue; @@ -220,12 +222,12 @@ public Collection getJars() { } @Override - public Collection getMixinConfigs(EnvType type) { + public Collection getMixinConfigs(EnvType type, FabricLoader loader) { final List mixinConfigs = new ArrayList<>(); // This is only ever called once, so no need to store the result of this. for (MixinEntry mixin : this.mixins) { - if (mixin.environment.matches(type)) { + if (mixin.environment.matches(type) && mixin.areDependencesMet(loader)) { mixinConfigs.add(mixin.config); } } @@ -306,10 +308,22 @@ public String getFile() { static final class MixinEntry { private final String config; private final ModEnvironment environment; + private final Set depends; - MixinEntry(String config, ModEnvironment environment) { + MixinEntry(String config, ModEnvironment environment, Set depends) { this.config = config; this.environment = environment; + this.depends = depends; + } + + public boolean areDependencesMet(FabricLoader loader) { + for (String modid : depends) { + if (!loader.isModLoaded(modid)) { + return false; + } + } + + return true; } } diff --git a/src/main/java/net/fabricmc/loader/impl/metadata/V1ModMetadataParser.java b/src/main/java/net/fabricmc/loader/impl/metadata/V1ModMetadataParser.java index cf65a6ccc..37564b8b1 100644 --- a/src/main/java/net/fabricmc/loader/impl/metadata/V1ModMetadataParser.java +++ b/src/main/java/net/fabricmc/loader/impl/metadata/V1ModMetadataParser.java @@ -18,11 +18,14 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -104,7 +107,7 @@ static LoaderModMetadata parse(JsonReader reader) throws IOException, ParseMetad break; case "id": if (reader.peek() != JsonToken.STRING) { - throw new ParseMetadataException("Mod id must be a non-empty string with a length of 3-64 characters.", reader); + throw new ParseMetadataException("Mod id must be a non-empty string with a length of 2-64 characters.", reader); } id = reader.nextString(); @@ -382,13 +385,14 @@ private static void readMixinConfigs(List warnings, JsonReader rea switch (reader.peek()) { case STRING: // All mixin configs specified via string are assumed to be universal - mixins.add(new V1ModMetadata.MixinEntry(reader.nextString(), ModEnvironment.UNIVERSAL)); + mixins.add(new V1ModMetadata.MixinEntry(reader.nextString(), ModEnvironment.UNIVERSAL, Collections.emptySet())); break; case BEGIN_OBJECT: reader.beginObject(); String config = null; ModEnvironment environment = null; + Set depends = null; while (reader.hasNext()) { final String key = reader.nextName(); @@ -398,6 +402,27 @@ private static void readMixinConfigs(List warnings, JsonReader rea case "environment": environment = V1ModMetadataParser.readEnvironment(reader); break; + case "depends": + if (reader.peek() != JsonToken.BEGIN_ARRAY) { + warnings.add(new ParseWarning(reader.getLineNumber(), reader.getColumn(), "Mixin config \"depends\" must be an array")); + reader.skipValue(); + continue; + } + + reader.beginArray(); + depends = new HashSet<>(); + + while (reader.hasNext()) { + if (reader.peek() == JsonToken.STRING) { + depends.add(reader.nextString()); + } else { + warnings.add(new ParseWarning(reader.getLineNumber(), reader.getColumn(), "Invalid mixin config dependency type")); + reader.skipValue(); + } + } + + reader.endArray(); + break; case "config": if (reader.peek() != JsonToken.STRING) { throw new ParseMetadataException("Value of \"config\" must be a string", reader); @@ -417,11 +442,15 @@ private static void readMixinConfigs(List warnings, JsonReader rea environment = ModEnvironment.UNIVERSAL; // Default to universal } + if (depends == null) { + depends = Collections.emptySet(); // Default to depending on nothing + } + if (config == null) { throw new ParseMetadataException.MissingField("Missing mandatory key 'config' in mixin entry!"); } - mixins.add(new V1ModMetadata.MixinEntry(config, environment)); + mixins.add(new V1ModMetadata.MixinEntry(config, environment, depends)); break; default: warnings.add(new ParseWarning(reader.getLineNumber(), reader.getColumn(), "Invalid mixin entry type"));