diff --git a/paper-api/src/main/java/co/aikar/timings/TimedEventExecutor.java b/paper-api/src/main/java/co/aikar/timings/TimedEventExecutor.java index a3ad690691..157617933a 100644 --- a/paper-api/src/main/java/co/aikar/timings/TimedEventExecutor.java +++ b/paper-api/src/main/java/co/aikar/timings/TimedEventExecutor.java @@ -84,4 +84,10 @@ public class TimedEventExecutor implements EventExecutor { executor.execute(listener, event); } } + + @Override + @NotNull + public String toString() { + return "TimedEventExecutor['" + this.executor.toString() + "']"; + } } diff --git a/paper-api/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/paper-api/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java index 5a702481d2..2a169d2f6f 100644 --- a/paper-api/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java +++ b/paper-api/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java @@ -18,10 +18,12 @@ public class MethodHandleEventExecutor implements EventExecutor { private final Class eventClass; private final MethodHandle handle; + private final @Nullable Method method; public MethodHandleEventExecutor(final Class eventClass, final MethodHandle handle) { this.eventClass = eventClass; this.handle = handle; + this.method = null; } public MethodHandleEventExecutor(final Class eventClass, final Method m) { @@ -32,6 +34,7 @@ public class MethodHandleEventExecutor implements EventExecutor { } catch (final IllegalAccessException e) { throw new AssertionError("Unable to set accessible", e); } + this.method = m; } @Override @@ -43,4 +46,9 @@ public class MethodHandleEventExecutor implements EventExecutor { SneakyThrow.sneaky(t); } } + + @Override + public String toString() { + return "MethodHandleEventExecutor['" + this.method + "']"; + } } diff --git a/paper-api/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/paper-api/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java index bbdb5b472d..e98962b6c6 100644 --- a/paper-api/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java +++ b/paper-api/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java @@ -19,6 +19,7 @@ public class StaticMethodHandleEventExecutor implements EventExecutor { private final Class eventClass; private final MethodHandle handle; + private final Method method; public StaticMethodHandleEventExecutor(final Class eventClass, final Method m) { Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m); @@ -30,6 +31,7 @@ public class StaticMethodHandleEventExecutor implements EventExecutor { } catch (final IllegalAccessException e) { throw new AssertionError("Unable to set accessible", e); } + this.method = m; } @Override @@ -41,4 +43,9 @@ public class StaticMethodHandleEventExecutor implements EventExecutor { SneakyThrow.sneaky(throwable); } } + + @Override + public String toString() { + return "StaticMethodHandleEventExecutor['" + this.method + "']"; + } } diff --git a/paper-api/src/main/java/org/bukkit/event/HandlerList.java b/paper-api/src/main/java/org/bukkit/event/HandlerList.java index ed78cca71f..2292bd460c 100644 --- a/paper-api/src/main/java/org/bukkit/event/HandlerList.java +++ b/paper-api/src/main/java/org/bukkit/event/HandlerList.java @@ -33,6 +33,13 @@ public class HandlerList { */ private static ArrayList allLists = new ArrayList(); + // Paper start + /** + * Event types which have instantiated a {@link HandlerList}. + */ + private static final java.util.Set EVENT_TYPES = java.util.concurrent.ConcurrentHashMap.newKeySet(); + // Paper end + /** * Bake all handler lists. Best used just after all normal event * registration is complete, ie just after all plugins are loaded if @@ -94,6 +101,12 @@ public class HandlerList { * The HandlerList is then added to meta-list for use in bakeAll() */ public HandlerList() { + // Paper start + java.lang.StackWalker.getInstance(java.util.EnumSet.of(java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE), 4) + .walk(s -> s.filter(f -> Event.class.isAssignableFrom(f.getDeclaringClass())).findFirst()) + .map(f -> f.getDeclaringClass().getName()) + .ifPresent(EVENT_TYPES::add); + // Paper end handlerslots = new EnumMap>(EventPriority.class); for (EventPriority o : EventPriority.values()) { handlerslots.put(o, new ArrayList()); diff --git a/paper-api/src/main/java/org/bukkit/plugin/EventExecutor.java b/paper-api/src/main/java/org/bukkit/plugin/EventExecutor.java index 5fa52419f2..60e086be70 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/EventExecutor.java +++ b/paper-api/src/main/java/org/bukkit/plugin/EventExecutor.java @@ -70,9 +70,18 @@ public interface EventExecutor { try { EventExecutor asmExecutor = executorClass.newInstance(); // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception) - return (listener, event) -> { - if (!eventClass.isInstance(event)) return; - asmExecutor.execute(listener, event); + return new EventExecutor() { + @Override + public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { + if (!eventClass.isInstance(event)) return; + asmExecutor.execute(listener, event); + } + + @Override + @NotNull + public String toString() { + return "ASMEventExecutor['" + m + "']"; + } }; } catch (InstantiationException | IllegalAccessException e) { throw new AssertionError("Unable to initialize generated event executor", e); diff --git a/paper-api/src/main/java/org/bukkit/plugin/RegisteredListener.java b/paper-api/src/main/java/org/bukkit/plugin/RegisteredListener.java index 419aec56b0..3b3d9642a8 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/RegisteredListener.java +++ b/paper-api/src/main/java/org/bukkit/plugin/RegisteredListener.java @@ -78,4 +78,27 @@ public class RegisteredListener { public boolean isIgnoringCancelled() { return ignoreCancelled; } + + // Paper start + /** + * Get the executor for this registration. + * + * @return executor + */ + @NotNull + public EventExecutor getExecutor() { + return this.executor; + } + + @Override + public String toString() { + return "RegisteredListener{" + + "plugin=\"" + this.plugin.getName() + + "\", listener=\"" + this.listener + + "\", executor=\"" + this.executor + + "\", priority=\"" + this.priority.name() + " (" + this.priority.getSlot() + ")" + + "\", ignoringCancelled=" + this.ignoreCancelled + + "}"; + } + // Paper end }