package codechicken.core.launch; import codechicken.core.asm.CodeChickenCoreModContainer; import codechicken.core.asm.DelegatedTransformer; import codechicken.core.asm.MCPDeobfuscationTransformer; import codechicken.core.asm.TweakTransformer; import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion; import net.minecraftforge.fml.common.versioning.VersionParser; import net.minecraftforge.fml.relauncher.CoreModManager; import net.minecraftforge.fml.relauncher.FMLInjectionData; import net.minecraftforge.fml.relauncher.IFMLCallHook; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import java.awt.*; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.List; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; @TransformerExclusions(value = { "codechicken.core.asm", "codechicken.obfuscator" }) public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.8.9]"; public static final String version = "${mod_version}"; public static File minecraftDir; public static String currentMcVersion; public static Logger logger = LogManager.getLogger("CodeChickenCore"); public CodeChickenCorePlugin() { if (minecraftDir != null) { return;//get called twice, once for IFMLCallHook } minecraftDir = (File) FMLInjectionData.data()[6]; currentMcVersion = (String) FMLInjectionData.data()[4]; DepLoader.load(); injectDeobfPlugin(); } private void injectDeobfPlugin() { try { Class<?> wrapperClass = Class.forName("net.minecraftforge.fml.relauncher.CoreModManager$FMLPluginWrapper"); Constructor wrapperConstructor = wrapperClass.getConstructor(String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class); Field f_loadPlugins = CoreModManager.class.getDeclaredField("loadPlugins"); wrapperConstructor.setAccessible(true); f_loadPlugins.setAccessible(true); ((List) f_loadPlugins.get(null)).add(2, wrapperConstructor.newInstance("CCCDeobfPlugin", new MCPDeobfuscationTransformer.LoadPlugin(), null, 0, new String[0])); } catch (Exception e) { logger.error("Failed to inject MCPDeobfuscation Transformer", e); } } public static void versionCheck(String reqVersion, String mod) { String mcVersion = (String) FMLInjectionData.data()[4]; if (!VersionParser.parseRange(reqVersion).containsVersion(new DefaultArtifactVersion(mcVersion))) { String err = "This version of " + mod + " does not support minecraft version " + mcVersion; logger.error(err); JEditorPane ep = new JEditorPane("text/html", "<html>" + err + "<br>Remove it from your coremods folder and check <a href=\"http://www.minecraftforum.net/topic/909223-\">here</a> for updates" + "</html>"); ep.setEditable(false); ep.setOpaque(false); ep.addHyperlinkListener(new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent event) { try { if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { Desktop.getDesktop().browse(event.getURL().toURI()); } } catch (Exception ignored) { } } }); JOptionPane.showMessageDialog(null, ep, "Fatal error", JOptionPane.ERROR_MESSAGE); System.exit(1); } } @Override public String[] getASMTransformerClass() { versionCheck(mcVersion, "CodeChickenCore"); return new String[] { "codechicken.core.asm.InterfaceDependancyTransformer", "codechicken.core.asm.TweakTransformer", "codechicken.core.asm.DelegatedTransformer", "codechicken.core.asm.DefaultImplementationTransformer" }; } @Override public String getAccessTransformerClass() { return "codechicken.core.asm.CodeChickenAccessTransformer"; } @Override public String getModContainerClass() { return "codechicken.core.asm.CodeChickenCoreModContainer"; } @Override public String getSetupClass() { return getClass().getName(); } @Override public void injectData(Map<String, Object> data) { } @Override public Void call() { CodeChickenCoreModContainer.loadConfig(); TweakTransformer.load(); scanCodeChickenMods(); return null; } private void scanCodeChickenMods() { File modsDir = new File(minecraftDir, "mods"); for (File file : modsDir.listFiles()) { scanMod(file); } File versionModsDir = new File(minecraftDir, "mods/" + currentMcVersion); if (versionModsDir.exists()) { for (File file : versionModsDir.listFiles()) { scanMod(file); } } } private void scanMod(File file) { if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) { return; } try { JarFile jar = new JarFile(file); try { Manifest manifest = jar.getManifest(); if (manifest == null) { return; } Attributes attr = manifest.getMainAttributes(); if (attr == null) { return; } String transformer = attr.getValue("CCTransformer"); if (transformer != null) { DelegatedTransformer.addTransformer(transformer, jar, file); } } finally { jar.close(); } } catch (Exception e) { logger.error("CodeChickenCore: Failed to read jar file: " + file.getName(), e); } } }