Add a simple ContainedDep mechanic- mods can contain other mods or libs, and can specify them using a manifest tag: "ContainedDeps".
This is a space separated (manifest standard) list of jar files that are to be extracted into the version specific directory. There's also a special system property "fml.skipContainedDeps" that will allow for runtime skipping of extraction of contained deps (a comma separated list, based on the file name).
This commit is contained in:
parent
1a31ff9f06
commit
dc4dc55dcd
1 changed files with 80 additions and 32 deletions
|
@ -14,6 +14,7 @@ package net.minecraftforge.fml.relauncher;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileFilter;
|
import java.io.FileFilter;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -29,8 +30,10 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.jar.Attributes;
|
import java.util.jar.Attributes;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
import net.minecraft.launchwrapper.ITweaker;
|
import net.minecraft.launchwrapper.ITweaker;
|
||||||
import net.minecraft.launchwrapper.Launch;
|
import net.minecraft.launchwrapper.Launch;
|
||||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||||
|
@ -59,6 +62,7 @@ public class CoreModManager {
|
||||||
private static final Attributes.Name COREMODCONTAINSFMLMOD = new Attributes.Name("FMLCorePluginContainsFMLMod");
|
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 MODTYPE = new Attributes.Name("ModType");
|
||||||
private static final Attributes.Name MODSIDE = new Attributes.Name("ModSide");
|
private static final Attributes.Name MODSIDE = new Attributes.Name("ModSide");
|
||||||
|
private static final Attributes.Name MODCONTAINSDEPS = new Attributes.Name("ContainedDeps");
|
||||||
private static String[] rootPlugins = { "net.minecraftforge.fml.relauncher.FMLCorePlugin", "net.minecraftforge.classloading.FMLForgePlugin" };
|
private static String[] rootPlugins = { "net.minecraftforge.fml.relauncher.FMLCorePlugin", "net.minecraftforge.classloading.FMLForgePlugin" };
|
||||||
private static List<String> ignoredModFiles = Lists.newArrayList();
|
private static List<String> ignoredModFiles = Lists.newArrayList();
|
||||||
private static Map<String, List<String>> transformers = Maps.newHashMap();
|
private static Map<String, List<String>> transformers = Maps.newHashMap();
|
||||||
|
@ -69,6 +73,7 @@ public class CoreModManager {
|
||||||
private static List<String> candidateModFiles = Lists.newArrayList();
|
private static List<String> candidateModFiles = Lists.newArrayList();
|
||||||
private static List<String> accessTransformers = Lists.newArrayList();
|
private static List<String> accessTransformers = Lists.newArrayList();
|
||||||
private static Set<String> rootNames = Sets.newHashSet();
|
private static Set<String> rootNames = Sets.newHashSet();
|
||||||
|
private static final List<String> skipContainedDeps = Arrays.asList(System.getProperty("fml.skipContainedDeps","").split(","));
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
|
@ -322,6 +327,7 @@ public class CoreModManager {
|
||||||
FMLRelaunchLog.fine("Examining for coremod candidacy %s", coreMod.getName());
|
FMLRelaunchLog.fine("Examining for coremod candidacy %s", coreMod.getName());
|
||||||
JarFile jar = null;
|
JarFile jar = null;
|
||||||
Attributes mfAttributes;
|
Attributes mfAttributes;
|
||||||
|
String fmlCorePlugin;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
jar = new JarFile(coreMod);
|
jar = new JarFile(coreMod);
|
||||||
|
@ -332,6 +338,39 @@ public class CoreModManager {
|
||||||
}
|
}
|
||||||
ModAccessTransformer.addJar(jar);
|
ModAccessTransformer.addJar(jar);
|
||||||
mfAttributes = jar.getManifest().getMainAttributes();
|
mfAttributes = jar.getManifest().getMainAttributes();
|
||||||
|
String cascadedTweaker = mfAttributes.getValue("TweakClass");
|
||||||
|
if (cascadedTweaker != null)
|
||||||
|
{
|
||||||
|
FMLRelaunchLog.info("Loading tweaker %s from %s", cascadedTweaker, coreMod.getName());
|
||||||
|
Integer sortOrder = Ints.tryParse(Strings.nullToEmpty(mfAttributes.getValue("TweakOrder")));
|
||||||
|
sortOrder = (sortOrder == null ? Integer.valueOf(0) : sortOrder);
|
||||||
|
handleCascadingTweak(coreMod, jar, cascadedTweaker, classLoader, sortOrder);
|
||||||
|
ignoredModFiles.add(coreMod.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<String> modTypes = mfAttributes.containsKey(MODTYPE) ? Arrays.asList(mfAttributes.getValue(MODTYPE).split(",")) : ImmutableList.of("FML");
|
||||||
|
|
||||||
|
if (!modTypes.contains("FML"))
|
||||||
|
{
|
||||||
|
FMLRelaunchLog.fine("Adding %s to the list of things to skip. It is not an FML mod, it has types %s", coreMod.getName(), modTypes);
|
||||||
|
ignoredModFiles.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());
|
||||||
|
ignoredModFiles.add(coreMod.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ModListHelper.additionalMods.putAll(extractContainedDepJars(jar, versionedModDir));
|
||||||
|
fmlCorePlugin = mfAttributes.getValue("FMLCorePlugin");
|
||||||
|
if (fmlCorePlugin == null)
|
||||||
|
{
|
||||||
|
// Not a coremod
|
||||||
|
FMLRelaunchLog.fine("Not found coremod data in %s", coreMod.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (IOException ioe)
|
catch (IOException ioe)
|
||||||
{
|
{
|
||||||
|
@ -352,38 +391,6 @@ public class CoreModManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String cascadedTweaker = mfAttributes.getValue("TweakClass");
|
|
||||||
if (cascadedTweaker != null)
|
|
||||||
{
|
|
||||||
FMLRelaunchLog.info("Loading tweaker %s from %s", cascadedTweaker, coreMod.getName());
|
|
||||||
Integer sortOrder = Ints.tryParse(Strings.nullToEmpty(mfAttributes.getValue("TweakOrder")));
|
|
||||||
sortOrder = (sortOrder == null ? Integer.valueOf(0) : sortOrder);
|
|
||||||
handleCascadingTweak(coreMod, jar, cascadedTweaker, classLoader, sortOrder);
|
|
||||||
ignoredModFiles.add(coreMod.getName());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
List<String> modTypes = mfAttributes.containsKey(MODTYPE) ? Arrays.asList(mfAttributes.getValue(MODTYPE).split(",")) : ImmutableList.of("FML");
|
|
||||||
|
|
||||||
if (!modTypes.contains("FML"))
|
|
||||||
{
|
|
||||||
FMLRelaunchLog.fine("Adding %s to the list of things to skip. It is not an FML mod, it has types %s", coreMod.getName(), modTypes);
|
|
||||||
ignoredModFiles.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());
|
|
||||||
ignoredModFiles.add(coreMod.getName());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String fmlCorePlugin = mfAttributes.getValue("FMLCorePlugin");
|
|
||||||
if (fmlCorePlugin == null)
|
|
||||||
{
|
|
||||||
// Not a coremod
|
|
||||||
FMLRelaunchLog.fine("Not found coremod data in %s", coreMod.getName());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Support things that are mod jars, but not FML mod jars
|
// Support things that are mod jars, but not FML mod jars
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -409,6 +416,47 @@ public class CoreModManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<String,File> extractContainedDepJars(JarFile jar, File versionedModsDir) throws IOException
|
||||||
|
{
|
||||||
|
Map<String,File> result = Maps.newHashMap();
|
||||||
|
if (!jar.getManifest().getMainAttributes().containsKey(MODCONTAINSDEPS)) return result;
|
||||||
|
|
||||||
|
String deps = jar.getManifest().getMainAttributes().getValue(MODCONTAINSDEPS);
|
||||||
|
String[] depList = deps.split(" ");
|
||||||
|
for (String dep : depList)
|
||||||
|
{
|
||||||
|
if (skipContainedDeps.contains(dep))
|
||||||
|
{
|
||||||
|
FMLRelaunchLog.log(Level.ERROR, "Skipping dep at request: %s", dep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final JarEntry jarEntry = jar.getJarEntry(dep);
|
||||||
|
if (jarEntry == null)
|
||||||
|
{
|
||||||
|
FMLRelaunchLog.log(Level.ERROR, "Found invalid ContainsDeps declaration %s in %s", dep, jar.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
File target = new File(versionedModsDir, dep);
|
||||||
|
if (target.exists())
|
||||||
|
{
|
||||||
|
FMLRelaunchLog.log(Level.DEBUG, "Found existing ContainsDep extracted to %s, skipping extraction", target.getCanonicalPath());
|
||||||
|
result.put(dep,target);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FMLRelaunchLog.log(Level.DEBUG, "Extracted ContainedDep %s from %s to %s", dep, jar.getName(), target.getCanonicalPath());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ByteStreams.copy(jar.getInputStream(jarEntry), new FileOutputStream(target));
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
FMLRelaunchLog.log(Level.ERROR, e, "An error occurred extracting dependency");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.put(dep,target);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static Method ADDURL;
|
private static Method ADDURL;
|
||||||
|
|
||||||
private static void handleCascadingTweak(File coreMod, JarFile jar, String cascadedTweaker, LaunchClassLoader classLoader, Integer sortingOrder)
|
private static void handleCascadingTweak(File coreMod, JarFile jar, String cascadedTweaker, LaunchClassLoader classLoader, Integer sortingOrder)
|
||||||
|
|
Loading…
Reference in a new issue