diff --git a/fml/common/cpw/mods/fml/common/discovery/JarDiscoverer.java b/fml/common/cpw/mods/fml/common/discovery/JarDiscoverer.java index 136e6ae72..f7b33fc63 100644 --- a/fml/common/cpw/mods/fml/common/discovery/JarDiscoverer.java +++ b/fml/common/cpw/mods/fml/common/discovery/JarDiscoverer.java @@ -40,9 +40,9 @@ public class JarDiscoverer implements ITypeDiscoverer { jar = new JarFile(candidate.getModContainer()); - if (jar.getManifest()!=null && jar.getManifest().getMainAttributes().get("FMLCorePlugin") != null) + if (jar.getManifest()!=null && (jar.getManifest().getMainAttributes().get("FMLCorePlugin") != null || jar.getManifest().getMainAttributes().get("TweakClass") != null)) { - FMLLog.finest("Ignoring coremod %s", candidate.getModContainer()); + FMLLog.finest("Ignoring coremod or tweak system %s", candidate.getModContainer()); return foundMods; } ZipEntry modInfo = jar.getEntry("mcmod.info"); diff --git a/fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java b/fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java index f478ee27c..6cb4e3ef6 100644 --- a/fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java +++ b/fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java @@ -75,6 +75,7 @@ public class FMLTweaker implements ITweaker { classLoader.addClassLoaderExclusion("LZMA."); FMLLaunchHandler.configureForClientLaunch(classLoader, this); runAdditionalTweaks(classLoader); + FMLLaunchHandler.appendCoreMods(); } void computeCascadedTweaks(LaunchClassLoader classLoader) @@ -158,4 +159,9 @@ public class FMLTweaker implements ITweaker { return jarLocation; } + public void injectCascadingTweak(ITweaker tweaker) + { + cascadedTweaks.add(tweaker); + } + } diff --git a/fml/common/cpw/mods/fml/common/patcher/ClassPatchManager.java b/fml/common/cpw/mods/fml/common/patcher/ClassPatchManager.java index 0eef9b53e..580e86160 100644 --- a/fml/common/cpw/mods/fml/common/patcher/ClassPatchManager.java +++ b/fml/common/cpw/mods/fml/common/patcher/ClassPatchManager.java @@ -141,7 +141,7 @@ public class ClassPatchManager { InputStream binpatchesCompressed = getClass().getResourceAsStream("/binpatches.pack.lzma"); if (binpatchesCompressed==null) { - FMLRelaunchLog.log(Level.SEVERE, "The binary patch set is missing. Things are probably about to go very wrong."); + FMLRelaunchLog.log(Level.SEVERE, "The binary patch set is missing. Either you are in a development environment, or things are not going to work!"); return; } LzmaInputStream binpatchesDecompressed = new LzmaInputStream(binpatchesCompressed); @@ -152,7 +152,7 @@ public class ClassPatchManager { } catch (Exception e) { - FMLRelaunchLog.log(Level.SEVERE, e, "Error occurred reading binary patches. Problems may occur"); + FMLRelaunchLog.log(Level.SEVERE, e, "Error occurred reading binary patches. Expect severe problems!"); throw Throwables.propagate(e); } diff --git a/fml/common/cpw/mods/fml/relauncher/CoreModManager.java b/fml/common/cpw/mods/fml/relauncher/CoreModManager.java index 994063fb4..1f3327ae8 100644 --- a/fml/common/cpw/mods/fml/relauncher/CoreModManager.java +++ b/fml/common/cpw/mods/fml/relauncher/CoreModManager.java @@ -13,21 +13,10 @@ package cpw.mods.fml.relauncher; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; import java.lang.reflect.Method; import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.FileChannel.MapMode; -import java.security.MessageDigest; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -37,24 +26,59 @@ import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.logging.Level; -import com.google.common.collect.ObjectArrays; - +import net.minecraft.launchwrapper.ITweaker; import net.minecraft.launchwrapper.LaunchClassLoader; -import cpw.mods.fml.common.CertificateHelper; +import com.google.common.base.Strings; +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.ObjectArrays; + +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.launcher.FMLTweaker; +import cpw.mods.fml.common.toposort.TopologicalSort; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.DependsOn; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.Name; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; public class CoreModManager { private static String[] rootPlugins = { "cpw.mods.fml.relauncher.FMLCorePlugin" , "net.minecraftforge.classloading.FMLForgePlugin" }; private static List loadedCoremods = new ArrayList(); - private static Map pluginLocations; - private static List loadPlugins; + private static List loadPlugins; private static boolean deobfuscatedEnvironment; + private static FMLTweaker tweaker; + private static File mcDir; - public static void handleLaunch(File mcDir, LaunchClassLoader classLoader) + private static class FMLPluginWrapper { + public final String name; + public final IFMLLoadingPlugin coreModInstance; + public final List predepends; + public final File location; + + public FMLPluginWrapper(String name, IFMLLoadingPlugin coreModInstance, File location, String... predepends) + { + super(); + this.name = name; + this.coreModInstance = coreModInstance; + this.location = location; + this.predepends = Lists.newArrayList(predepends); + } + + @Override + public String toString() + { + return String.format("%s {%s}", this.name, this.predepends); + } + } + + public static void handleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) + { + CoreModManager.mcDir = mcDir; + CoreModManager.tweaker = tweaker; try { // Are we in a 'decompiled' environment? @@ -73,20 +97,21 @@ public class CoreModManager { FMLRelaunchLog.fine("Enabling runtime deobfuscation"); } - pluginLocations = new HashMap(); - loadPlugins = new ArrayList(); - for (String s : rootPlugins) + + try { - try - { - FMLRelaunchLog.finest("Adding coremod for loading %s", s); - IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) Class.forName(s, true, classLoader).newInstance(); - loadPlugins.add(plugin); - } - catch (Exception e) - { - // HMMM - } + classLoader.registerTransformer("cpw.mods.fml.common.asm.transformers.PatchingTransformer"); + } + catch (Exception e) + { + FMLRelaunchLog.log(Level.SEVERE, e, "The patch transformer failed to load! This is critical, loading cannot continue!"); + throw Throwables.propagate(e); + } + + loadPlugins = new ArrayList(); + for (String rootPluginName : rootPlugins) + { + loadCoreMod(classLoader, rootPluginName, null); } if (loadPlugins.isEmpty()) @@ -94,111 +119,23 @@ public class CoreModManager throw new RuntimeException("A fatal error has occured - no valid fml load plugin was found - this is a completely corrupt FML installation."); } - FMLRelaunchLog.fine("All core mods are successfully located"); + FMLRelaunchLog.fine("All fundamental core mods are successfully located"); // Now that we have the root plugins loaded - lets see what else might be around String commandLineCoremods = System.getProperty("fml.coreMods.load",""); - for (String s : commandLineCoremods.split(",")) + for (String coreModClassName : commandLineCoremods.split(",")) { - if (s.isEmpty()) + if (coreModClassName.isEmpty()) { continue; } - FMLRelaunchLog.info("Found a command line coremod : %s", s); - try - { - classLoader.addTransformerExclusion(s); - Class coreModClass = Class.forName(s, true, classLoader); - TransformerExclusions trExclusions = coreModClass.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class); - if (trExclusions!=null) - { - for (String st : trExclusions.value()) - { - classLoader.addTransformerExclusion(st); - } - } - IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClass.newInstance(); - loadPlugins.add(plugin); - } - catch (Throwable e) - { - FMLRelaunchLog.log(Level.SEVERE,e,"Exception occured trying to load coremod %s",s); - throw new RuntimeException(e); - } + FMLRelaunchLog.info("Found a command line coremod : %s", coreModClassName); + loadCoreMod(classLoader, coreModClassName, null); } - discoverCoreMods(mcDir, classLoader, loadPlugins); + discoverCoreMods(mcDir, classLoader); - for (IFMLLoadingPlugin plug : loadPlugins) - { - if (plug.getASMTransformerClass()!=null) - { - for (String xformClass : plug.getASMTransformerClass()) - { - FMLRelaunchLog.finest("Registering transformer %s", xformClass); - classLoader.registerTransformer(xformClass); - } - } - } - // Deobfuscation transformer, always last - if (!deobfuscatedEnvironment) - { - classLoader.registerTransformer("cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer"); - } - FMLRelaunchLog.fine("Running coremod plugins"); - Map data = new HashMap(); - data.put("mcLocation", mcDir); - data.put("coremodList", loadPlugins); - data.put("runtimeDeobfuscationEnabled", !deobfuscatedEnvironment); - for (IFMLLoadingPlugin plugin : loadPlugins) - { - FMLRelaunchLog.fine("Running coremod plugin %s", plugin.getClass().getSimpleName()); - data.put("coremodLocation", pluginLocations.get(plugin)); - plugin.injectData(data); - String setupClass = plugin.getSetupClass(); - if (setupClass != null) - { - try - { - IFMLCallHook call = (IFMLCallHook) Class.forName(setupClass, true, classLoader).newInstance(); - Map callData = new HashMap(); - callData.put("mcLocation", mcDir); - callData.put("classLoader", classLoader); - callData.put("coremodLocation", pluginLocations.get(plugin)); - callData.put("deobfuscationFileName", FMLInjectionData.debfuscationDataName()); - call.injectData(callData); - call.call(); - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } - FMLRelaunchLog.fine("Coremod plugin %s run successfully", plugin.getClass().getSimpleName()); - - String modContainer = plugin.getModContainerClass(); - if (modContainer != null) - { - FMLInjectionData.containers.add(modContainer); - } - } - try - { - FMLRelaunchLog.fine("Validating minecraft"); - Class loaderClazz = Class.forName("cpw.mods.fml.common.Loader", true, classLoader); - Method m = loaderClazz.getMethod("injectData", Object[].class); - m.invoke(null, (Object)FMLInjectionData.data()); - m = loaderClazz.getMethod("instance"); - m.invoke(null); - FMLRelaunchLog.fine("Minecraft validated, launching..."); - } - catch (Exception e) - { - // Load in the Loader, make sure he's ready to roll - this will initialize most of the rest of minecraft here - System.out.println("A CRITICAL PROBLEM OCCURED INITIALIZING MINECRAFT - LIKELY YOU HAVE AN INCORRECT VERSION FOR THIS FML"); - throw new RuntimeException(e); - } } - private static void discoverCoreMods(File mcDir, LaunchClassLoader classLoader, List loadPlugins) + private static void discoverCoreMods(File mcDir, LaunchClassLoader classLoader) { FMLRelaunchLog.fine("Discovering coremods"); File coreMods = setupCoreModDir(mcDir); @@ -241,6 +178,14 @@ public class CoreModManager continue; } + String cascadedTweaker = mfAttributes.getValue("TweakClass"); + if (cascadedTweaker != null) + { + handleCascadingTweak(coreMod, jar, cascadedTweaker, classLoader); + loadedCoremods.add(coreMod.getName()); + continue; + } + String fmlCorePlugin = mfAttributes.getValue("FMLCorePlugin"); if (fmlCorePlugin == null) { @@ -258,59 +203,22 @@ public class CoreModManager FMLRelaunchLog.log(Level.SEVERE, e, "Unable to convert file into a URL. weird"); continue; } - try - { - FMLRelaunchLog.fine("Loading coremod %s", coreMod.getName()); - classLoader.addTransformerExclusion(fmlCorePlugin); - Class coreModClass = Class.forName(fmlCorePlugin, true, classLoader); - MCVersion requiredMCVersion = coreModClass.getAnnotation(IFMLLoadingPlugin.MCVersion.class); - String version = ""; - if (requiredMCVersion == null) - { - FMLRelaunchLog.log(Level.WARNING, "The coremod %s does not have a MCVersion annotation, it may cause issues with this version of Minecraft", fmlCorePlugin); - } - else - { - version = requiredMCVersion.value(); - } - if (!"".equals(version) && !FMLInjectionData.mccversion.equals(version)) - { - FMLRelaunchLog.log(Level.SEVERE, "The coremod %s is requesting minecraft version %s and minecraft is %s. It will be ignored.", fmlCorePlugin, version, FMLInjectionData.mccversion); - continue; - } - else if (!"".equals(version)) - { - FMLRelaunchLog.log(Level.FINE, "The coremod %s requested minecraft version %s and minecraft is %s. It will be loaded.", fmlCorePlugin, version, FMLInjectionData.mccversion); - } - TransformerExclusions trExclusions = coreModClass.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class); - if (trExclusions!=null) - { - for (String st : trExclusions.value()) - { - classLoader.addTransformerExclusion(st); - } - } - IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClass.newInstance(); - loadPlugins.add(plugin); - pluginLocations .put(plugin, coreMod); - FMLRelaunchLog.fine("Loaded coremod %s", coreMod.getName()); - } - catch (ClassNotFoundException cnfe) - { - FMLRelaunchLog.log(Level.SEVERE, cnfe, "Coremod %s: Unable to class load the plugin %s", coreMod.getName(), fmlCorePlugin); - } - catch (ClassCastException cce) - { - FMLRelaunchLog.log(Level.SEVERE, cce, "Coremod %s: The plugin %s is not an implementor of IFMLLoadingPlugin", coreMod.getName(), fmlCorePlugin); - } - catch (InstantiationException ie) - { - FMLRelaunchLog.log(Level.SEVERE, ie, "Coremod %s: The plugin class %s was not instantiable", coreMod.getName(), fmlCorePlugin); - } - catch (IllegalAccessException iae) - { - FMLRelaunchLog.log(Level.SEVERE, iae, "Coremod %s: The plugin class %s was not accessible", coreMod.getName(), fmlCorePlugin); - } + loadCoreMod(classLoader, fmlCorePlugin, coreMod); + } + } + + private static void handleCascadingTweak(File coreMod, JarFile jar, String cascadedTweaker, LaunchClassLoader classLoader) + { + try + { + classLoader.addURL(coreMod.toURI().toURL()); + Class newTweakClass = (Class) Class.forName(cascadedTweaker, true, classLoader); + ITweaker newTweak = newTweakClass.newInstance(); + CoreModManager.tweaker.injectCascadingTweak(tweaker); + } + catch (Exception e) + { + FMLRelaunchLog.log(Level.INFO, e, "There was a problem trying to load the mod dir tweaker %s", coreMod.getAbsolutePath()); } } @@ -344,4 +252,184 @@ public class CoreModManager { return loadedCoremods; } + + private static FMLPluginWrapper loadCoreMod(LaunchClassLoader classLoader, String coreModClass, File location) + { + String coreModName = coreModClass.substring(coreModClass.lastIndexOf('.')+1); + try + { + FMLRelaunchLog.fine("Instantiating coremod class %s", coreModName); + classLoader.addTransformerExclusion(coreModClass); + Class coreModClazz = Class.forName(coreModClass, true, classLoader); + Name coreModNameAnn = coreModClazz.getAnnotation(IFMLLoadingPlugin.Name.class); + if (coreModNameAnn!=null && !Strings.isNullOrEmpty(coreModNameAnn.value())) + { + coreModName = coreModNameAnn.value(); + FMLRelaunchLog.finest("coremod named %s is loading", coreModName); + } + MCVersion requiredMCVersion = coreModClazz.getAnnotation(IFMLLoadingPlugin.MCVersion.class); + if (!Arrays.asList(rootPlugins).contains(coreModClass) && (requiredMCVersion == null || Strings.isNullOrEmpty(requiredMCVersion.value()))) + { + FMLRelaunchLog.log(Level.WARNING, "The coremod %s does not have a MCVersion annotation, it may cause issues with this version of Minecraft", coreModClass); + } + else if (requiredMCVersion!=null && !FMLInjectionData.mccversion.equals(requiredMCVersion.value())) + { + FMLRelaunchLog.log(Level.SEVERE, "The coremod %s is requesting minecraft version %s and minecraft is %s. It will be ignored.", coreModClass, requiredMCVersion.value(), FMLInjectionData.mccversion); + return null; + } + else if (requiredMCVersion!=null) + { + FMLRelaunchLog.log(Level.FINE, "The coremod %s requested minecraft version %s and minecraft is %s. It will be loaded.", coreModClass, requiredMCVersion.value(), FMLInjectionData.mccversion); + } + TransformerExclusions trExclusions = coreModClazz.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class); + if (trExclusions!=null) + { + for (String st : trExclusions.value()) + { + classLoader.addTransformerExclusion(st); + } + } + DependsOn deplist = coreModClazz.getAnnotation(IFMLLoadingPlugin.DependsOn.class); + String[] dependencies = new String[0]; + if (deplist != null) + { + dependencies = deplist.value(); + } + IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClazz.newInstance(); + FMLPluginWrapper wrap = new FMLPluginWrapper(coreModName, plugin, location, dependencies); + + loadPlugins.add(wrap); + FMLRelaunchLog.fine("Loaded coremod %s", coreModName); + return wrap; + } + catch (ClassNotFoundException cnfe) + { + if (!Lists.newArrayList(rootPlugins).contains(coreModClass)) + FMLRelaunchLog.log(Level.SEVERE, cnfe, "Coremod %s: Unable to class load the plugin %s", coreModName, coreModClass); + else + FMLRelaunchLog.fine("Skipping root plugin %s", coreModClass); + } + catch (ClassCastException cce) + { + FMLRelaunchLog.log(Level.SEVERE, cce, "Coremod %s: The plugin %s is not an implementor of IFMLLoadingPlugin", coreModName, coreModClass); + } + catch (InstantiationException ie) + { + FMLRelaunchLog.log(Level.SEVERE, ie, "Coremod %s: The plugin class %s was not instantiable", coreModName, coreModClass); + } + catch (IllegalAccessException iae) + { + FMLRelaunchLog.log(Level.SEVERE, iae, "Coremod %s: The plugin class %s was not accessible", coreModName, coreModClass); + } + return null; + } + + private static void sortCoreMods() + { + TopologicalSort.DirectedGraph sortGraph = new TopologicalSort.DirectedGraph(); + Map pluginMap = Maps.newHashMap(); + for (FMLPluginWrapper plug : loadPlugins) + { + sortGraph.addNode(plug); + pluginMap.put(plug.name, plug); + } + + for (FMLPluginWrapper plug : loadPlugins) + { + for (String dep : plug.predepends) + { + if (!pluginMap.containsKey(dep)) + { + FMLRelaunchLog.log(Level.SEVERE, "Missing coremod dependency - the coremod %s depends on coremod %s which isn't present.", plug.name, dep); + throw new RuntimeException(); + } + sortGraph.addEdge(plug, pluginMap.get(dep)); + } + } + try + { + loadPlugins = TopologicalSort.topologicalSort(sortGraph); + FMLRelaunchLog.fine("Sorted coremod list %s", loadPlugins); + } + catch (Exception e) + { + FMLLog.log(Level.SEVERE, e, "There was a problem performing the coremod sort"); + throw Throwables.propagate(e); + } + } + public static void injectTransformers(LaunchClassLoader classLoader) + { + + for (FMLPluginWrapper wrap : loadPlugins) + { + IFMLLoadingPlugin plug = wrap.coreModInstance; + if (plug.getASMTransformerClass()!=null) + { + for (String xformClass : plug.getASMTransformerClass()) + { + FMLRelaunchLog.finest("Registering transformer %s", xformClass); + classLoader.registerTransformer(xformClass); + } + } + } + FMLRelaunchLog.fine("Running coremod plugins"); + Map data = new HashMap(); + data.put("mcLocation", mcDir); + data.put("coremodList", loadPlugins); + data.put("runtimeDeobfuscationEnabled", !deobfuscatedEnvironment); + for (FMLPluginWrapper pluginWrapper : loadPlugins) + { + IFMLLoadingPlugin plugin = pluginWrapper.coreModInstance; + FMLRelaunchLog.fine("Running coremod plugin %s", pluginWrapper.name); + data.put("coremodLocation", pluginWrapper.location); + plugin.injectData(data); + String setupClass = plugin.getSetupClass(); + if (setupClass != null) + { + try + { + IFMLCallHook call = (IFMLCallHook) Class.forName(setupClass, true, classLoader).newInstance(); + Map callData = new HashMap(); + callData.put("mcLocation", mcDir); + callData.put("classLoader", classLoader); + callData.put("coremodLocation", pluginWrapper.location); + callData.put("deobfuscationFileName", FMLInjectionData.debfuscationDataName()); + call.injectData(callData); + call.call(); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + FMLRelaunchLog.fine("Coremod plugin %s run successfully", plugin.getClass().getSimpleName()); + + String modContainer = plugin.getModContainerClass(); + if (modContainer != null) + { + FMLInjectionData.containers.add(modContainer); + } + } + // Deobfuscation transformer, always last + if (!deobfuscatedEnvironment) + { + classLoader.registerTransformer("cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer"); + } + try + { + FMLRelaunchLog.fine("Validating minecraft"); + Class loaderClazz = Class.forName("cpw.mods.fml.common.Loader", true, classLoader); + Method m = loaderClazz.getMethod("injectData", Object[].class); + m.invoke(null, (Object)FMLInjectionData.data()); + m = loaderClazz.getMethod("instance"); + m.invoke(null); + FMLRelaunchLog.fine("Minecraft validated, launching..."); + } + catch (Exception e) + { + // Load in the Loader, make sure he's ready to roll - this will initialize most of the rest of minecraft here + System.out.println("A CRITICAL PROBLEM OCCURED INITIALIZING MINECRAFT - LIKELY YOU HAVE AN INCORRECT VERSION FOR THIS FML"); + throw new RuntimeException(e); + } + } } diff --git a/fml/common/cpw/mods/fml/relauncher/FMLCorePlugin.java b/fml/common/cpw/mods/fml/relauncher/FMLCorePlugin.java index d5267314a..f522e8143 100644 --- a/fml/common/cpw/mods/fml/relauncher/FMLCorePlugin.java +++ b/fml/common/cpw/mods/fml/relauncher/FMLCorePlugin.java @@ -27,7 +27,6 @@ public class FMLCorePlugin implements IFMLLoadingPlugin public String[] getASMTransformerClass() { return new String[] { - "cpw.mods.fml.common.asm.transformers.PatchingTransformer", "cpw.mods.fml.common.asm.transformers.AccessTransformer", "cpw.mods.fml.common.asm.transformers.MarkerTransformer", "cpw.mods.fml.common.asm.transformers.SideTransformer", diff --git a/fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java b/fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java index 9aacce89e..7b86918d6 100644 --- a/fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java +++ b/fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java @@ -87,7 +87,7 @@ public class FMLLaunchHandler try { - CoreModManager.handleLaunch(minecraftHome, classLoader); + CoreModManager.handleLaunch(minecraftHome, classLoader, tweaker); } catch (Throwable t) { @@ -101,4 +101,15 @@ public class FMLLaunchHandler { return side; } + + + private void injectPostfixTransformers() + { + CoreModManager.injectTransformers(classLoader); + } + + public static void appendCoreMods() + { + INSTANCE.injectPostfixTransformers(); + } } diff --git a/fml/common/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java b/fml/common/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java index e0bbd669f..cc36db681 100644 --- a/fml/common/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java +++ b/fml/common/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java @@ -102,4 +102,24 @@ public interface IFMLLoadingPlugin { public String value() default ""; } + + /** + * Name this coremod something other than the "short class name" + * @author cpw + * + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface Name + { + public String value() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface DependsOn + { + public String[] value() default {}; + } + }