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:
parent
57ed697cab
commit
5f234fdcf8
4 changed files with 60 additions and 15 deletions
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue