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:
cpw 2016-01-02 17:28:35 -05:00
parent 1a31ff9f06
commit dc4dc55dcd

View file

@ -14,6 +14,7 @@ package net.minecraftforge.fml.relauncher;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Method;
@ -29,8 +30,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import com.google.common.io.ByteStreams;
import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.Launch;
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 MODTYPE = new Attributes.Name("ModType");
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 List<String> ignoredModFiles = Lists.newArrayList();
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> accessTransformers = Lists.newArrayList();
private static Set<String> rootNames = Sets.newHashSet();
private static final List<String> skipContainedDeps = Arrays.asList(System.getProperty("fml.skipContainedDeps","").split(","));
static
{
@ -322,6 +327,7 @@ public class CoreModManager {
FMLRelaunchLog.fine("Examining for coremod candidacy %s", coreMod.getName());
JarFile jar = null;
Attributes mfAttributes;
String fmlCorePlugin;
try
{
jar = new JarFile(coreMod);
@ -332,26 +338,6 @@ public class CoreModManager {
}
ModAccessTransformer.addJar(jar);
mfAttributes = jar.getManifest().getMainAttributes();
}
catch (IOException ioe)
{
FMLRelaunchLog.log(Level.ERROR, ioe, "Unable to read the jar file %s - ignoring", coreMod.getName());
continue;
}
finally
{
if (jar != null)
{
try
{
jar.close();
}
catch (IOException e)
{
// Noise
}
}
}
String cascadedTweaker = mfAttributes.getValue("TweakClass");
if (cascadedTweaker != null)
{
@ -377,13 +363,34 @@ public class CoreModManager {
ignoredModFiles.add(coreMod.getName());
continue;
}
String fmlCorePlugin = mfAttributes.getValue("FMLCorePlugin");
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)
{
FMLRelaunchLog.log(Level.ERROR, ioe, "Unable to read the jar file %s - ignoring", coreMod.getName());
continue;
}
finally
{
if (jar != null)
{
try
{
jar.close();
}
catch (IOException e)
{
// Noise
}
}
}
// Support things that are mod jars, but not FML mod jars
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 void handleCascadingTweak(File coreMod, JarFile jar, String cascadedTweaker, LaunchClassLoader classLoader, Integer sortingOrder)