From 88a411550ae00aed1b0e9982e23ceb588a61c274 Mon Sep 17 00:00:00 2001 From: cpw Date: Tue, 24 Jun 2014 21:34:07 -0400 Subject: [PATCH] Add support for mod access transformers without a coremod requirement. Use the "FMLAT" manifest attribute, with a space separate list of files that live in the 'META-INF' directory. They should conform to standard AT formatting. --- fml/jsons/1.7.10-pre4.json | 2 +- .../asm/transformers/AccessTransformer.java | 72 ++++++++++++++++--- .../transformers/ModAccessTransformer.java | 34 +++++++++ .../fml/common/launcher/FMLDeobfTweaker.java | 1 + .../mods/fml/relauncher/CoreModManager.java | 8 +-- 5 files changed, 101 insertions(+), 16 deletions(-) create mode 100644 fml/src/main/java/cpw/mods/fml/common/asm/transformers/ModAccessTransformer.java diff --git a/fml/jsons/1.7.10-pre4.json b/fml/jsons/1.7.10-pre4.json index e74b924cc..effba14a0 100644 --- a/fml/jsons/1.7.10-pre4.json +++ b/fml/jsons/1.7.10-pre4.json @@ -8,7 +8,7 @@ "assets": "1.7.10", "libraries": [ { - "name": "com.mojang:realms:1.2.3" + "name": "com.mojang:realms:1.2.4" }, { "name": "org.apache.commons:commons-compress:1.8.1" diff --git a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/AccessTransformer.java b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/AccessTransformer.java index 76120c1a4..65319be39 100644 --- a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/AccessTransformer.java +++ b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/AccessTransformer.java @@ -27,10 +27,14 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; @@ -51,6 +55,8 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; +import com.google.common.io.ByteSource; +import com.google.common.io.CharSource; import com.google.common.io.LineProcessor; import com.google.common.io.Resources; @@ -59,7 +65,7 @@ import cpw.mods.fml.relauncher.FMLRelaunchLog; public class AccessTransformer implements IClassTransformer { private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("fml.debugAccessTransformer", "false")); - private class Modifier + class Modifier { public String name = ""; public String desc = ""; @@ -100,7 +106,41 @@ public class AccessTransformer implements IClassTransformer readMapFile(rulesFile); } - private void readMapFile(String rulesFile) throws IOException + AccessTransformer(JarFile jar) throws IOException + { + Manifest manifest = jar.getManifest(); + String atList = manifest.getMainAttributes().getValue("FMLAT"); + for (String at : atList.split(" ")) + { + JarEntry jarEntry = jar.getJarEntry("META-INF/"+at); + if (jarEntry != null) + { + processATFile(new JarByteSource(jar,jarEntry).asCharSource(Charsets.UTF_8)); + } + } + FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer mod jar file %s\n", modifiers.size(), jar.getName()); + } + + AccessTransformer(Class dummyClazz) + { + // This is a noop + } + private class JarByteSource extends ByteSource { + private JarFile jar; + private JarEntry entry; + public JarByteSource(JarFile jar, JarEntry entry) + { + this.jar = jar; + this.entry = entry; + } + @Override + public InputStream openStream() throws IOException + { + return jar.getInputStream(entry); + } + + } + void readMapFile(String rulesFile) throws IOException { File file = new File(rulesFile); URL rulesResource; @@ -112,7 +152,12 @@ public class AccessTransformer implements IClassTransformer { rulesResource = Resources.getResource(rulesFile); } - Resources.readLines(rulesResource, Charsets.UTF_8, new LineProcessor() + processATFile(Resources.asCharSource(rulesResource, Charsets.UTF_8)); + FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer config file %s\n", modifiers.size(), rulesFile); + } + private void processATFile(CharSource rulesResource) throws IOException + { + rulesResource.readLines(new LineProcessor() { @Override public Void getResult() @@ -160,7 +205,6 @@ public class AccessTransformer implements IClassTransformer return true; } }); - FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer config file %s\n", modifiers.size(), rulesFile); } @Override @@ -217,7 +261,7 @@ public class AccessTransformer implements IClassTransformer if ((n.name.equals(m.name) && n.desc.equals(m.desc)) || m.name.equals("*")) { n.access = getFixedAccess(n.access, m); - + // constructors always use INVOKESPECIAL if (!n.name.equals("")) { @@ -225,14 +269,14 @@ public class AccessTransformer implements IClassTransformer // so that overridden methods will be called. Only need to scan this class, because obviously the method was private. boolean wasPrivate = (m.oldAccess & ACC_PRIVATE) == ACC_PRIVATE; boolean isNowPrivate = (m.newAccess & ACC_PRIVATE) == ACC_PRIVATE; - + if (wasPrivate && !isNowPrivate) { nowOverridable.add(n); } - + } - + if (DEBUG) { System.out.println(String.format("Method: %s.%s%s %s -> %s", name, n.name, n.desc, toBinary(m.oldAccess), toBinary(m.newAccess))); @@ -244,7 +288,7 @@ public class AccessTransformer implements IClassTransformer } } } - + replaceInvokeSpecial(classNode, nowOverridable); } } @@ -253,7 +297,7 @@ public class AccessTransformer implements IClassTransformer classNode.accept(writer); return writer.toByteArray(); } - + private void replaceInvokeSpecial(ClassNode clazz, List toReplace) { for (MethodNode method : clazz.methods) @@ -477,4 +521,12 @@ public class AccessTransformer implements IClassTransformer } } } + Multimap getModifiers() + { + return modifiers; + } + boolean isEmpty() + { + return modifiers.isEmpty(); + } } diff --git a/fml/src/main/java/cpw/mods/fml/common/asm/transformers/ModAccessTransformer.java b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/ModAccessTransformer.java new file mode 100644 index 000000000..a98d624d5 --- /dev/null +++ b/fml/src/main/java/cpw/mods/fml/common/asm/transformers/ModAccessTransformer.java @@ -0,0 +1,34 @@ +package cpw.mods.fml.common.asm.transformers; + +import java.io.IOException; +import java.util.List; +import java.util.jar.JarFile; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; + +public class ModAccessTransformer extends AccessTransformer { + private static List embedded = Lists.newArrayList(); + public ModAccessTransformer() throws IOException + { + super(ModAccessTransformer.class); + for (AccessTransformer at : embedded) + { + mergeModifiers(at.getModifiers()); + } + } + + private void mergeModifiers(Multimap modifiers) + { + getModifiers().putAll(modifiers); + } + + public static void addJar(JarFile jar) throws IOException + { + AccessTransformer at = new AccessTransformer(jar); + if (!at.isEmpty()) + { + embedded.add(at); + } + } + +} diff --git a/fml/src/main/java/cpw/mods/fml/common/launcher/FMLDeobfTweaker.java b/fml/src/main/java/cpw/mods/fml/common/launcher/FMLDeobfTweaker.java index c5e6be955..12b18a3d5 100644 --- a/fml/src/main/java/cpw/mods/fml/common/launcher/FMLDeobfTweaker.java +++ b/fml/src/main/java/cpw/mods/fml/common/launcher/FMLDeobfTweaker.java @@ -31,6 +31,7 @@ public class FMLDeobfTweaker implements ITweaker { { classLoader.registerTransformer(transformer); } + classLoader.registerTransformer("cpw.mods.fml.common.asm.transformers.ModAccessTransformer"); try { FMLRelaunchLog.fine("Validating minecraft"); 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 42c0b69e6..2a7d6b62f 100644 --- a/fml/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java +++ b/fml/src/main/java/cpw/mods/fml/relauncher/CoreModManager.java @@ -28,21 +28,18 @@ import java.util.List; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.JarFile; - -import org.apache.logging.log4j.Level; - import net.minecraft.launchwrapper.ITweaker; import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; - +import org.apache.logging.log4j.Level; 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 com.google.common.primitives.Ints; - import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.asm.transformers.ModAccessTransformer; import cpw.mods.fml.common.launcher.FMLInjectionAndSortingTweaker; import cpw.mods.fml.common.launcher.FMLTweaker; import cpw.mods.fml.common.toposort.TopologicalSort; @@ -249,6 +246,7 @@ public class CoreModManager { // Not a coremod continue; } + ModAccessTransformer.addJar(jar); mfAttributes = jar.getManifest().getMainAttributes(); } catch (IOException ioe)