From f5cf87304b6863aea840db4f4115dbe088bd6632 Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 31 Aug 2014 14:00:28 -0400 Subject: [PATCH] Two new features. ModLists can have a "parent" mod list. Circularity will result in a crash, so be careful. Mods specified in a child will override ones from a parent (using the maven group:name:classifier triple to identify - ignoring the version component) Finally, ModSide is now doable in MANIFEST.MF. If you have this, it can tell a mod to only load on a client, or on a dedicated server (though I'd watch out before using the dediserver one, you'll never load in integrated servers then). The default value is BOTH, which means you'll load both sides, other values are CLIENT and SERVER, obviously. Perhaps, also, CAULDRON might be possible? --- .../fml/common/discovery/ModDiscoverer.java | 4 +- .../mods/fml/relauncher/CoreModManager.java | 10 ++++- .../mods/fml/relauncher/ModListHelper.java | 44 ++++++++++++++----- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/fml/src/main/java/cpw/mods/fml/common/discovery/ModDiscoverer.java b/fml/src/main/java/cpw/mods/fml/common/discovery/ModDiscoverer.java index 5bc49e3c2b..a1fb9812d0 100644 --- a/fml/src/main/java/cpw/mods/fml/common/discovery/ModDiscoverer.java +++ b/fml/src/main/java/cpw/mods/fml/common/discovery/ModDiscoverer.java @@ -85,8 +85,8 @@ public class ModDiscoverer public void findModDirMods(File modsDir) { File[] modList = FileListHelper.sortFileList(modsDir, null); - modList = FileListHelper.sortFileList(ObjectArrays.concat(modList, ModListHelper.additionalMods.toArray(new File[0]), File.class)); - + modList = FileListHelper.sortFileList(ObjectArrays.concat(modList, ModListHelper.additionalMods.values().toArray(new File[0]), File.class)); + for (File modFile : modList) { // skip loaded coremods diff --git a/fml/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java b/fml/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java index fe8b48a303..d30f5fe3a7 100644 --- a/fml/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java +++ b/fml/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java @@ -52,6 +52,7 @@ import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; public class CoreModManager { private static final Attributes.Name COREMODCONTAINSFMLMOD = new Attributes.Name("FMLCorePluginContainsFMLMod"); private static final Attributes.Name MODTYPE = new Attributes.Name("ModType"); + private static final Attributes.Name MODSIDE = new Attributes.Name("ModSide"); private static String[] rootPlugins = { "cpw.mods.fml.relauncher.FMLCorePlugin", "net.minecraftforge.classloading.FMLForgePlugin" }; private static List loadedCoremods = Lists.newArrayList(); private static List loadPlugins; @@ -250,7 +251,7 @@ public class CoreModManager { coreModList = ObjectArrays.concat(coreModList, versionedCoreMods, File.class); } - ObjectArrays.concat(coreModList, ModListHelper.additionalMods.toArray(new File[0]), File.class); + ObjectArrays.concat(coreModList, ModListHelper.additionalMods.values().toArray(new File[0]), File.class); coreModList = FileListHelper.sortFileList(coreModList); @@ -307,6 +308,13 @@ public class CoreModManager { loadedCoremods.add(coreMod.getName()); continue; } + String modSide = mfAttributes.containsKey(MODSIDE) ? mfAttributes.getValue(MODSIDE) : "BOTH"; + if (! ("BOTH".equals(modSide) || FMLLaunchHandler.side.name().equals(modSide))) + { + FMLRelaunchLog.fine("Mod %s has ModSide meta-inf value %s, and we're %s. It will be ignored", coreMod.getName(), modSide, FMLLaunchHandler.side.name()); + loadedCoremods.add(coreMod.getName()); + continue; + } String fmlCorePlugin = mfAttributes.getValue("FMLCorePlugin"); if (fmlCorePlugin == null) { diff --git a/fml/src/main/java/cpw/mods/fml/relauncher/ModListHelper.java b/fml/src/main/java/cpw/mods/fml/relauncher/ModListHelper.java index 953b6faa4c..1afb9d2b37 100644 --- a/fml/src/main/java/cpw/mods/fml/relauncher/ModListHelper.java +++ b/fml/src/main/java/cpw/mods/fml/relauncher/ModListHelper.java @@ -5,11 +5,14 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.logging.log4j.Level; import com.google.common.base.Charsets; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.google.common.io.Files; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; @@ -20,8 +23,10 @@ public class ModListHelper { public static class JsonModList { public String repositoryRoot; public List modRef; + public String parentList; } - public static final ArrayList additionalMods = Lists.newArrayList(); + private static Set visitedFiles = Sets.newHashSet(); + public static final Map additionalMods = Maps.newLinkedHashMap(); static void parseModList() { FMLRelaunchLog.fine("Attempting to load commandline specified mods"); @@ -49,6 +54,11 @@ public class ModListHelper { FMLRelaunchLog.info("Failed to find modList file %s", listFile); return; } + if (visitedFiles.contains(f)) + { + FMLRelaunchLog.severe("There appears to be a loop in the modListFile hierarchy. You shouldn't do this!"); + throw new RuntimeException("Loop detected, impossible to load modlistfile"); + } String json; try { json = Files.asCharSource(f, Charsets.UTF_8).read(); @@ -64,6 +74,12 @@ public class ModListHelper { FMLRelaunchLog.log(Level.INFO, e, "Failed to parse modList json file %s.", listFile); return; } + visitedFiles.add(f); + // We visit parents before children, so the additionalMods list is sorted from parent to child + if (modList.parentList != null) + { + parseListFile(modList.parentList); + } File repoRoot = new File(modList.repositoryRoot); if (!repoRoot.exists()) { @@ -73,19 +89,23 @@ public class ModListHelper { for (String s : modList.modRef) { - StringBuilder sb = new StringBuilder(); + StringBuilder fileName = new StringBuilder(); + StringBuilder genericName = new StringBuilder(); String[] parts = s.split(":"); - sb.append(parts[0].replace('.', File.separatorChar)); - sb.append(File.separatorChar); - sb.append(parts[1]).append(File.separatorChar); - sb.append(parts[2]).append(File.separatorChar); - sb.append(parts[1]).append('-').append(parts[2]); + fileName.append(parts[0].replace('.', File.separatorChar)); + genericName.append(parts[0]); + fileName.append(File.separatorChar); + fileName.append(parts[1]).append(File.separatorChar); + genericName.append(":").append(parts[1]); + fileName.append(parts[2]).append(File.separatorChar); + fileName.append(parts[1]).append('-').append(parts[2]); if (parts.length == 4) { - sb.append('-').append(parts[3]); + fileName.append('-').append(parts[3]); + genericName.append(":").append(parts[3]); } - sb.append(".jar"); - tryAddFile(sb.toString(), repoRoot, s); + fileName.append(".jar"); + tryAddFile(fileName.toString(), repoRoot, genericName.toString()); } } private static void tryAddFile(String modFileName, File repoRoot, String descriptor) { @@ -96,8 +116,8 @@ public class ModListHelper { } else { - FMLRelaunchLog.fine("Adding ;%s (%s) to the mod list", descriptor, modFile.getAbsolutePath()); - additionalMods.add(modFile); + FMLRelaunchLog.fine("Adding %s (%s) to the mod list", descriptor, modFile.getAbsolutePath()); + additionalMods.put(descriptor, modFile); } } }