From ccffcf60f83198690c563372c4fe0c1b66efc783 Mon Sep 17 00:00:00 2001 From: Zot201 Date: Thu, 27 Nov 2014 16:02:30 +0900 Subject: [PATCH] Fix Event Bus Access Issues 1) Allow overriding methods in subclass without extra SubscribeEvent annotations 2) Transform event subscribers to have public method/class --- .../EventSubscriberTransformer.java | 74 +++++++++++++++++++ .../fml/common/eventhandler/EventBus.java | 2 +- .../fml/relauncher/FMLCorePlugin.java | 1 + 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 fml/src/main/java/net/minecraftforge/fml/common/asm/transformers/EventSubscriberTransformer.java diff --git a/fml/src/main/java/net/minecraftforge/fml/common/asm/transformers/EventSubscriberTransformer.java b/fml/src/main/java/net/minecraftforge/fml/common/asm/transformers/EventSubscriberTransformer.java new file mode 100644 index 000000000..c910b2402 --- /dev/null +++ b/fml/src/main/java/net/minecraftforge/fml/common/asm/transformers/EventSubscriberTransformer.java @@ -0,0 +1,74 @@ +package net.minecraftforge.fml.common.asm.transformers; + +import java.lang.reflect.Modifier; +import java.util.List; + +import net.minecraft.launchwrapper.IClassTransformer; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; + +public class EventSubscriberTransformer implements IClassTransformer +{ + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) + { + if (basicClass == null) return null; + + ClassNode classNode = new ClassNode(); + new ClassReader(basicClass).accept(classNode, 0); + + boolean isSubscriber = false; + + for (MethodNode methodNode : classNode.methods) + { + List anns = methodNode.visibleAnnotations; + + if (anns != null && Iterables.any(anns, SubscribeEventPredicate.INSTANCE)) + { + if (Modifier.isPrivate(methodNode.access)) + { + String msg = "Cannot apply @SubsribeEvent to private method %s/%s%s"; + throw new RuntimeException(String.format(msg, classNode.name, methodNode.name, methodNode.desc)); + } + + methodNode.access = toPublic(methodNode.access); + isSubscriber = true; + } + } + + if (isSubscriber) + { + classNode.access = toPublic(classNode.access); + + ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); + classNode.accept(writer); + return writer.toByteArray(); + } + + return basicClass; + } + + private static int toPublic(int access) + { + return access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED) | Opcodes.ACC_PUBLIC; + } + + private static class SubscribeEventPredicate implements Predicate + { + static final SubscribeEventPredicate INSTANCE = new SubscribeEventPredicate(); + + @Override + public boolean apply(AnnotationNode input) + { + return input.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/SubscribeEvent;"); + } + } +} diff --git a/fml/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java b/fml/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java index 400c19097..391810d1e 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java @@ -82,7 +82,7 @@ public class EventBus implements IEventExceptionHandler throw new IllegalArgumentException("Method " + method + " has @SubscribeEvent annotation, but takes a argument that is not an Event " + eventType); } - register(eventType, target, method, activeModContainer); + register(eventType, target, real, activeModContainer); break; } } diff --git a/fml/src/main/java/net/minecraftforge/fml/relauncher/FMLCorePlugin.java b/fml/src/main/java/net/minecraftforge/fml/relauncher/FMLCorePlugin.java index f41e74ac1..63e61788c 100644 --- a/fml/src/main/java/net/minecraftforge/fml/relauncher/FMLCorePlugin.java +++ b/fml/src/main/java/net/minecraftforge/fml/relauncher/FMLCorePlugin.java @@ -23,6 +23,7 @@ public class FMLCorePlugin implements IFMLLoadingPlugin "net.minecraftforge.fml.common.asm.transformers.MarkerTransformer", "net.minecraftforge.fml.common.asm.transformers.SideTransformer", "net.minecraftforge.fml.common.asm.transformers.EventSubscriptionTransformer", + "net.minecraftforge.fml.common.asm.transformers.EventSubscriberTransformer", }; }