From 1cf77452df89ed242d0edf05c1647bad2b4a7dce Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Sun, 18 Jul 2021 13:36:26 +0200 Subject: [PATCH] Add special event handler that ensure this is the last listener of the event --- .../pandacube/lib/paper/util/BukkitEvent.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/Paper/src/main/java/fr/pandacube/lib/paper/util/BukkitEvent.java b/Paper/src/main/java/fr/pandacube/lib/paper/util/BukkitEvent.java index e0dec4a..b99e233 100644 --- a/Paper/src/main/java/fr/pandacube/lib/paper/util/BukkitEvent.java +++ b/Paper/src/main/java/fr/pandacube/lib/paper/util/BukkitEvent.java @@ -2,6 +2,7 @@ package fr.pandacube.lib.paper.util; import java.lang.reflect.Method; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import org.bukkit.Bukkit; import org.bukkit.event.Event; @@ -11,6 +12,8 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.plugin.EventExecutor; import org.bukkit.plugin.IllegalPluginAccessException; +import org.bukkit.plugin.RegisteredListener; +import org.bukkit.scheduler.BukkitTask; import fr.pandacube.lib.core.util.ReflexionUtil; import fr.pandacube.lib.paper.PandaLibPaper; @@ -93,5 +96,51 @@ public class BukkitEvent { } } + /** + * Abstract implementation of {@link EventListener} that ensure as best as it can, + * that it is the last listener called to handle the event. + * + * @param the type of the event + */ + public static abstract class EnforcedLastListener implements EventListener { + private final Class eventClass; + private final boolean ignoreCancelled; + + public EnforcedLastListener(Class eventClass, boolean ignoreCancelled) { + this.eventClass = eventClass; + this.ignoreCancelled = ignoreCancelled; + register(); + } + + private void register() { + BukkitEvent.register(eventClass, this, EventPriority.MONITOR, ignoreCancelled); + } + + @Override + public void execute(Listener var1, Event var2) throws EventException { + EventListener.super.execute(var1, var2); + checkIfListenerIsLast(); + } + + + private AtomicReference listenerCheckTask = new AtomicReference<>(); + + private void checkIfListenerIsLast() { + synchronized (listenerCheckTask) { + if (listenerCheckTask.get() != null) + return; + RegisteredListener[] listeners = BukkitEvent.getHandlerList(eventClass).getRegisteredListeners(); + if (listeners[listeners.length - 1].getListener() != this) { + listenerCheckTask.set(Bukkit.getScheduler().runTask(PandaLibPaper.getPlugin(), () -> { + // need to re-register the event so we are last + BukkitEvent.unregister(this); + register(); + listenerCheckTask.set(null); + })); + } + } + } + } + }