diff --git a/src/main/java/net/minecraftforge/fml/common/eventhandler/ASMEventHandler.java b/src/main/java/net/minecraftforge/fml/common/eventhandler/ASMEventHandler.java index 7f277eb2e..a0088666e 100644 --- a/src/main/java/net/minecraftforge/fml/common/eventhandler/ASMEventHandler.java +++ b/src/main/java/net/minecraftforge/fml/common/eventhandler/ASMEventHandler.java @@ -22,6 +22,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; +import java.util.function.Consumer; import net.minecraftforge.fml.common.ModContainer; @@ -32,10 +33,10 @@ public class ASMEventHandler implements IEventListener { private static final boolean GETCONTEXT = Boolean.parseBoolean(System.getProperty("fml.LogContext", "false")); - private final IEventListener handler; + private final Consumer handler; private final SubscribeEvent subInfo; - private ModContainer owner; - private String readable; + private final ModContainer owner; + private final String readable; @Deprecated public ASMEventHandler(Object target, Method method, ModContainer owner) throws Exception @@ -58,7 +59,7 @@ public ASMEventHandler(Object target, Method method, ModContainer owner, boolean var filter = parameterized.getActualTypeArguments()[0]; this.handler = event -> { if (filter == ((IGenericEvent) event).getGenericType()) { - rawHandler.invoke(event); + rawHandler.accept(event); } }; } else { @@ -75,7 +76,7 @@ public void invoke(Event event) { if (!event.isCancelable() || !event.isCanceled() || subInfo.receiveCanceled()) { - handler.invoke(event); + handler.accept(event); } } if (GETCONTEXT) diff --git a/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java b/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java index 4e8781e23..3ef4936d8 100644 --- a/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java +++ b/src/main/java/net/minecraftforge/fml/common/eventhandler/EventBus.java @@ -152,6 +152,7 @@ public void register(Object target) } } + /// Some mods will intentionally call this method with illegal `method` object (whose param type is `Object` instead of subclass of `Event`), and we have to allow this stupid move private void register(Class eventType, Object target, Method method, final ModContainer owner) { try diff --git a/src/main/java/net/minecraftforge/fml/common/eventhandler/EventListenerFactory.java b/src/main/java/net/minecraftforge/fml/common/eventhandler/EventListenerFactory.java index 4e86248b7..a7bfd2a43 100644 --- a/src/main/java/net/minecraftforge/fml/common/eventhandler/EventListenerFactory.java +++ b/src/main/java/net/minecraftforge/fml/common/eventhandler/EventListenerFactory.java @@ -5,8 +5,10 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; /** * @author ZZZank @@ -14,16 +16,18 @@ class EventListenerFactory { private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - public static IEventListener createRawListener(Method method, boolean isStatic, Object instance) { + public static Consumer createRawListener(Method method, boolean isStatic, Object instance) { // no caching is applied here because in EventBus scenario, caching will only be useful // when two instance-based listeners of the same class are registered, which is an // incredibly rare usage in 1.12 Forge environment var listenerFactory = createListenerFactory(method, isStatic, instance); try { - return isStatic - ? (IEventListener) listenerFactory.invokeExact() - : (IEventListener) listenerFactory.invokeExact(instance); + @SuppressWarnings("unchecked") + var rawListener = isStatic + ? (Consumer) listenerFactory.invokeExact() + : (Consumer) listenerFactory.invokeExact(instance); + return rawListener; } catch (Throwable t) { throw new RuntimeException(t); } @@ -60,8 +64,11 @@ private static MethodHandle createListenerFactory( } interface Constants { - Class CLAZZ = IEventListener.class; - Method METHOD = CLAZZ.getMethods()[0]; + Class CLAZZ = Consumer.class; + Method METHOD = Arrays.stream(CLAZZ.getMethods()) + .filter(m -> "accept".equals(m.getName())) + .findFirst() + .orElseThrow(); String METHOD_NAME = METHOD.getName(); MethodType METHOD_TYPE = MethodType.methodType(METHOD.getReturnType(), METHOD.getParameterTypes()); MethodType RETURNS_IT = MethodType.methodType(CLAZZ); diff --git a/src/test/java/net/minecraftforge/fml/common/eventhandler/EventBusTest.java b/src/test/java/net/minecraftforge/fml/common/eventhandler/EventBusTest.java index 46f4f4c7d..ab87f10f8 100644 --- a/src/test/java/net/minecraftforge/fml/common/eventhandler/EventBusTest.java +++ b/src/test/java/net/minecraftforge/fml/common/eventhandler/EventBusTest.java @@ -1,5 +1,7 @@ package net.minecraftforge.fml.common.eventhandler; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.fml.common.eventhandler.impl.AbnormalListeners; import net.minecraftforge.fml.common.eventhandler.impl.ExampleEvent; import net.minecraftforge.fml.common.eventhandler.impl.InstanceListeners; @@ -7,6 +9,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.lang.reflect.Method; import java.util.List; /** @@ -58,4 +61,29 @@ public void registerAbnormal() { Assertions.assertTrue(AbnormalListeners.nonVoid, "listener with non-void return type is valid"); } + + @Test + public void registerIllegalParamType() throws Exception { + var bus = new EventBus(); + + var listener = new AbnormalListeners.IllegalParamType(); + + var method = EventBus.class.getDeclaredMethod( + "register", + Class.class, Object.class, Method.class, ModContainer.class + ); + method.setAccessible(true); + method.invoke( + bus, + ExampleEvent.class, + listener, + AbnormalListeners.IllegalParamType.class.getMethod("onEvent", Object.class), + Loader.instance().getMinecraftModContainer() + ); + + var event = new ExampleEvent(); + bus.post(event); + + Assertions.assertEquals(event.id, listener.captured); + } } diff --git a/src/test/java/net/minecraftforge/fml/common/eventhandler/impl/AbnormalListeners.java b/src/test/java/net/minecraftforge/fml/common/eventhandler/impl/AbnormalListeners.java index e0a26b125..25faaff5b 100644 --- a/src/test/java/net/minecraftforge/fml/common/eventhandler/impl/AbnormalListeners.java +++ b/src/test/java/net/minecraftforge/fml/common/eventhandler/impl/AbnormalListeners.java @@ -37,4 +37,14 @@ public static Object nonVoidReturn(ExampleEvent event) { return null; } } + + public static class IllegalParamType { + public Integer captured = null; + + @SubscribeEvent + public void onEvent(Object event) { + var casted = (ExampleEvent) event; + captured = casted.id; + } + } }