diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/AnnotatedSubscriberFinder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/AnnotatedSubscriberFinder.java index f10f5277c..92ed8d557 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/AnnotatedSubscriberFinder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/AnnotatedSubscriberFinder.java @@ -22,6 +22,8 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; /** @@ -59,7 +61,14 @@ public Multimap, EventHandler> findAllSubscribers(Object listener) { ); } Class eventType = parameterTypes[0]; - EventHandler handler = new MethodEventHandler(annotation.priority(), listener, method); + MethodHandle handle; + try { + handle = MethodHandles.publicLookup().unreflect(method); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Method " + method + " failed to unreflect.", e); + } + + EventHandler handler = new MethodHandleEventHandler(annotation.priority(), listener, handle, method.getName()); methodsInListener.put(eventType, handler); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/MethodEventHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/MethodEventHandler.java index 03f69fb5b..0353103c3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/MethodEventHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/MethodEventHandler.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.util.eventbus; import java.lang.reflect.Method; +import java.util.Objects; import static com.google.common.base.Preconditions.checkNotNull; @@ -72,11 +73,8 @@ public boolean equals(Object o) { if (!method.equals(that.method)) { return false; } - if (object != null ? !object.equals(that.object) : that.object != null) { - return false; - } - return true; + return Objects.equals(object, that.object); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/MethodHandleEventHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/MethodHandleEventHandler.java new file mode 100644 index 000000000..33ca1d3b2 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/eventbus/MethodHandleEventHandler.java @@ -0,0 +1,82 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.eventbus; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.util.Objects; + +public class MethodHandleEventHandler extends EventHandler { + + private final MethodHandle methodHandle; + private final String methodName; + private final Object object; + + /** + * Create a new event handler that uses MethodHandles to dispatch. + * + * @param priority the priority + * @param object The object to invoke it on + * @param methodHandle The handle to invoke + * @param methodName The name of the method (for equality checks) + */ + protected MethodHandleEventHandler(Priority priority, Object object, MethodHandle methodHandle, String methodName) { + super(priority); + + this.object = object; + this.methodHandle = methodHandle.bindTo(object).asType(MethodType.methodType(void.class, Object.class)); + this.methodName = methodName; + } + + @Override + public void dispatch(Object event) throws Exception { + try { + this.methodHandle.invokeExact(event); + } catch (Exception | Error e) { + throw e; + } catch (Throwable t) { + // If it's not an Exception or Error, throw it wrapped. + throw new Exception(t); + } + } + + @Override + public int hashCode() { + return Objects.hash(methodName, object); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + MethodHandleEventHandler that = (MethodHandleEventHandler) o; + + if (!methodName.equals(that.methodName)) { + return false; + } + + return Objects.equals(object, that.object); + } +}