Added support for using static methods as event listeners, Register the .class instead of an instance.

And added an improvement to calltime listener rebuilding.
This commit is contained in:
LexManos 2016-07-13 12:08:13 -07:00
parent 57ed697cab
commit 5f234fdcf8
4 changed files with 60 additions and 15 deletions

View file

@ -22,6 +22,7 @@ package net.minecraftforge.fml.common.eventhandler;
import static org.objectweb.asm.Opcodes.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import net.minecraftforge.fml.common.ModContainer;
@ -51,7 +52,10 @@ public class ASMEventHandler implements IEventListener
public ASMEventHandler(Object target, Method method, ModContainer owner) throws Exception
{
this.owner = owner;
handler = (IEventListener)createWrapper(method).getConstructor(Object.class).newInstance(target);
if (Modifier.isStatic(method.getModifiers()))
handler = (IEventListener)createWrapper(method).newInstance();
else
handler = (IEventListener)createWrapper(method).getConstructor(Object.class).newInstance(target);
subInfo = method.getAnnotation(SubscribeEvent.class);
readable = "ASM: " + target + " " + method.getName() + Type.getMethodDescriptor(method);
}
@ -87,6 +91,7 @@ public class ASMEventHandler implements IEventListener
ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
boolean isStatic = Modifier.isStatic(callback.getModifiers());
String name = getUniqueName(callback);
String desc = name.replace('.', '/');
String instType = Type.getInternalName(callback.getDeclaringClass());
@ -104,16 +109,20 @@ public class ASMEventHandler implements IEventListener
cw.visitSource(".dynamic", null);
{
cw.visitField(ACC_PUBLIC, "instance", "Ljava/lang/Object;", null, null).visitEnd();
if (!isStatic)
cw.visitField(ACC_PUBLIC, "instance", "Ljava/lang/Object;", null, null).visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/Object;)V", null, null);
mv = cw.visitMethod(ACC_PUBLIC, "<init>", isStatic ? "()V" : "(Ljava/lang/Object;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, desc, "instance", "Ljava/lang/Object;");
if (!isStatic)
{
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, desc, "instance", "Ljava/lang/Object;");
}
mv.visitInsn(RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
@ -122,11 +131,14 @@ public class ASMEventHandler implements IEventListener
mv = cw.visitMethod(ACC_PUBLIC, "invoke", HANDLER_FUNC_DESC, null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, desc, "instance", "Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, instType);
if (!isStatic)
{
mv.visitFieldInsn(GETFIELD, desc, "instance", "Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, instType);
}
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, eventType);
mv.visitMethodInsn(INVOKEVIRTUAL, instType, callback.getName(), Type.getMethodDescriptor(callback), false);
mv.visitMethodInsn(isStatic ? INVOKESTATIC : INVOKEVIRTUAL, instType, callback.getName(), Type.getMethodDescriptor(callback), false);
mv.visitInsn(RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();

View file

@ -21,6 +21,7 @@ package net.minecraftforge.fml.common.eventhandler;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
@ -37,6 +38,7 @@ import org.apache.logging.log4j.Level;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Sets;
import com.google.common.reflect.TypeToken;
public class EventBus implements IEventExceptionHandler
@ -75,9 +77,16 @@ public class EventBus implements IEventExceptionHandler
activeModContainer = Loader.instance().getMinecraftModContainer();
}
listenerOwners.put(target, activeModContainer);
Set<? extends Class<?>> supers = TypeToken.of(target.getClass()).getTypes().rawTypes();
for (Method method : target.getClass().getMethods())
boolean isStatic = target.getClass() == Class.class;
@SuppressWarnings("unchecked")
Set<? extends Class<?>> supers = isStatic ? Sets.newHashSet((Class<?>)target) : TypeToken.of(target.getClass()).getTypes().rawTypes();
for (Method method : (isStatic ? (Class<?>)target : target.getClass()).getMethods())
{
if (isStatic && !Modifier.isStatic(method.getModifiers()))
continue;
else if (!isStatic && Modifier.isStatic(method.getModifiers()))
continue;
for (Class<?> cls : supers)
{
try

View file

@ -21,6 +21,7 @@ package net.minecraftforge.fml.common.eventhandler;
import java.util.*;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
public class ListenerList
@ -139,6 +140,8 @@ public class ListenerList
private IEventListener[] listeners;
private ArrayList<ArrayList<IEventListener>> priorities;
private ListenerListInst parent;
private List<ListenerListInst> children;
private ListenerListInst()
{
@ -160,12 +163,15 @@ public class ListenerList
priorities.clear();
parent = null;
listeners = null;
if (children != null)
children.clear();
}
private ListenerListInst(ListenerListInst parent)
{
this();
this.parent = parent;
this.parent.addChild(this);
}
/**
@ -205,7 +211,24 @@ public class ListenerList
protected boolean shouldRebuild()
{
return rebuild || (parent != null && parent.shouldRebuild());
return rebuild;// || (parent != null && parent.shouldRebuild());
}
protected void forceRebuild()
{
this.rebuild = true;
if (this.children != null)
{
for (ListenerListInst child : this.children)
child.forceRebuild();
}
}
private void addChild(ListenerListInst child)
{
if (this.children == null)
this.children = Lists.newArrayList();
this.children.add(child);
}
/**
@ -235,7 +258,7 @@ public class ListenerList
public void register(EventPriority priority, IEventListener listener)
{
priorities.get(priority.ordinal()).add(listener);
rebuild = true;
this.forceRebuild();
}
public void unregister(IEventListener listener)
@ -244,7 +267,7 @@ public class ListenerList
{
if (list.remove(listener))
{
rebuild = true;
this.forceRebuild();
}
}
}

View file

@ -32,6 +32,7 @@ public class PlayerInteractEventTest
{
logger = event.getModLog();
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(PlayerInteractEventTest.class); // Test Static event listeners
}
@SubscribeEvent(receiveCanceled = true) // this triggers after the subclasses below, and we'd like to log them all
@ -142,7 +143,7 @@ public class PlayerInteractEventTest
}
@SubscribeEvent
public void interactNormal(PlayerInteractEvent.EntityInteract evt)
public static void interactNormal(PlayerInteractEvent.EntityInteract evt)
{
if (!ENABLE) return;