diff --git a/src/main/java/emu/grasscutter/plugin/PluginManager.java b/src/main/java/emu/grasscutter/plugin/PluginManager.java index 2c6b9f23d..f63e2381d 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginManager.java +++ b/src/main/java/emu/grasscutter/plugin/PluginManager.java @@ -3,9 +3,8 @@ package emu.grasscutter.plugin; import emu.grasscutter.Grasscutter; import emu.grasscutter.server.event.Event; import emu.grasscutter.server.event.EventHandler; -import emu.grasscutter.server.event.Listener; +import emu.grasscutter.server.event.HandlerPriority; import emu.grasscutter.utils.Utils; -import org.reflections.Reflections; import java.io.File; import java.io.InputStreamReader; @@ -15,13 +14,14 @@ import java.net.URLClassLoader; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.stream.Stream; /** * Manages the server's plugins & the event system. */ public final class PluginManager { private final Map plugins = new HashMap<>(); - private final Map> listeners = new HashMap<>(); + private final List> listeners = new LinkedList<>(); public PluginManager() { this.loadPlugins(); // Load all plugins from the plugins directory. @@ -68,7 +68,7 @@ public final class PluginManager { JarEntry entry = entries.nextElement(); if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue; String className = entry.getName().replace(".class", "").replace("/", "."); - Class clazz = loader.loadClass(className); + loader.loadClass(className); } Class pluginClass = loader.loadClass(pluginConfig.mainClass); @@ -129,11 +129,10 @@ public final class PluginManager { /** * Registers a plugin's event listener. - * @param plugin The plugin instance. * @param listener The event listener. */ - public void registerListener(Plugin plugin, Listener listener) { - this.listeners.computeIfAbsent(plugin, k -> new ArrayList<>()).add(listener); + public void registerListener(EventHandler listener) { + this.listeners.add(listener); } /** @@ -141,23 +140,24 @@ public final class PluginManager { * @param event The event to invoke. */ public void invokeEvent(Event event) { - this.listeners.values().stream() - .flatMap(Collection::stream) - .forEach(listener -> this.invokeOnListener(listener, event)); + Stream> handlers = this.listeners.stream() + .filter(handler -> event.getClass().isInstance(event)); + handlers.filter(handler -> handler.getPriority() == HandlerPriority.HIGH) + .toList().forEach(handler -> this.invokeHandler(event, handler)); + handlers.filter(handler -> handler.getPriority() == HandlerPriority.NORMAL) + .toList().forEach(handler -> this.invokeHandler(event, handler)); + handlers.filter(handler -> handler.getPriority() == HandlerPriority.LOW) + .toList().forEach(handler -> this.invokeHandler(event, handler)); } - + /** - * Attempts to invoke the event on the provided listener. + * Performs logic checks then invokes the provided event handler. + * @param event The event passed through to the handler. + * @param handler The handler to invoke. */ - private void invokeOnListener(Listener listener, Event event) { - try { - Class listenerClass = listener.getClass(); - Method[] methods = listenerClass.getMethods(); - for (Method method : methods) { - if(!method.isAnnotationPresent(EventHandler.class)) return; - if(!method.getParameterTypes()[0].isAssignableFrom(event.getClass())) return; - method.invoke(listener, event); - } - } catch (Exception ignored) { } + private void invokeHandler(Event event, EventHandler handler) { + if(!event.isCanceled() || + (event.isCanceled() && handler.ignoresCanceled()) + ) handler.getCallback().accept(event); } } \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/event/EventHandler.java b/src/main/java/emu/grasscutter/server/event/EventHandler.java index d924933f2..ec0eaffe5 100644 --- a/src/main/java/emu/grasscutter/server/event/EventHandler.java +++ b/src/main/java/emu/grasscutter/server/event/EventHandler.java @@ -1,11 +1,79 @@ package emu.grasscutter.server.event; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; +import emu.grasscutter.Grasscutter; -/** - * Declares a class as an event listener/handler. - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface EventHandler { +import java.util.function.Consumer; + +public final class EventHandler { + private E event; + + private Consumer listener; + private HandlerPriority priority; + private boolean handleCanceled; + + /** + * Gets which event this handler is handling. + * @return An event class. + */ + public Event handles() { + return this.event; + } + + /** + * Returns the callback for the handler. + * @return A consumer callback. + */ + public Consumer getCallback() { + return this.listener; + } + + /** + * Returns the handler's priority. + * @return The priority of the handler. + */ + public HandlerPriority getPriority() { + return this.priority; + } + + /** + * Returns if the handler will ignore cancelled events. + * @return The ignore cancelled state. + */ + public boolean ignoresCanceled() { + return this.handleCanceled; + } + + /** + * Sets the callback method for when the event is invoked. + * @param listener An event handler method. + * @return Method chaining. + */ + public EventHandler listener(Consumer listener) { + this.listener = listener; return this; + } + + /** + * Changes the handler's priority in handling events. + * @param priority The priority of the handler. + * @return Method chaining. + */ + public EventHandler priority(HandlerPriority priority) { + this.priority = priority; return this; + } + + /** + * Sets if the handler will ignore cancelled events. + * @param ignore If the handler should ignore cancelled events. + * @return Method chaining. + */ + public EventHandler ignore(boolean ignore) { + this.handleCanceled = ignore; return this; + } + + /** + * Registers the handler into the PluginManager. + */ + public void register() { + Grasscutter.getPluginManager().registerListener(this); + } } \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/event/HandlerPriority.java b/src/main/java/emu/grasscutter/server/event/HandlerPriority.java new file mode 100644 index 000000000..18891879f --- /dev/null +++ b/src/main/java/emu/grasscutter/server/event/HandlerPriority.java @@ -0,0 +1,18 @@ +package emu.grasscutter.server.event; + +public enum HandlerPriority { + /** + * The handler will be called before every other handler. + */ + HIGH, + + /** + * The handler will be called the same time as other handlers. + */ + NORMAL, + + /** + * The handler will be called after every other handler. + */ + LOW +} diff --git a/src/main/java/emu/grasscutter/server/event/Listener.java b/src/main/java/emu/grasscutter/server/event/Listener.java deleted file mode 100644 index 2949cfe4a..000000000 --- a/src/main/java/emu/grasscutter/server/event/Listener.java +++ /dev/null @@ -1,7 +0,0 @@ -package emu.grasscutter.server.event; - -/** - * Implementing this interface declares a class as an event listener. - */ -public interface Listener { -}