mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-27 21:10:54 +00:00
Overhaul event handling (designed by WetABQ#3417)
This commit is contained in:
parent
7e48bd1e65
commit
727fa8a67d
@ -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<String, Plugin> plugins = new HashMap<>();
|
||||
private final Map<Plugin, List<Listener>> listeners = new HashMap<>();
|
||||
private final List<EventHandler<?>> 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<EventHandler<?>> 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);
|
||||
}
|
||||
}
|
@ -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<E extends Event> {
|
||||
private E event;
|
||||
|
||||
private Consumer<Event> 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<Event> 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<E> listener(Consumer<Event> 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<E> 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<E> ignore(boolean ignore) {
|
||||
this.handleCanceled = ignore; return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the handler into the PluginManager.
|
||||
*/
|
||||
public void register() {
|
||||
Grasscutter.getPluginManager().registerListener(this);
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package emu.grasscutter.server.event;
|
||||
|
||||
/**
|
||||
* Implementing this interface declares a class as an event listener.
|
||||
*/
|
||||
public interface Listener {
|
||||
}
|
Loading…
Reference in New Issue
Block a user