mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-28 00:34:19 +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.Grasscutter;
|
||||||
import emu.grasscutter.server.event.Event;
|
import emu.grasscutter.server.event.Event;
|
||||||
import emu.grasscutter.server.event.EventHandler;
|
import emu.grasscutter.server.event.EventHandler;
|
||||||
import emu.grasscutter.server.event.Listener;
|
import emu.grasscutter.server.event.HandlerPriority;
|
||||||
import emu.grasscutter.utils.Utils;
|
import emu.grasscutter.utils.Utils;
|
||||||
import org.reflections.Reflections;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@ -15,13 +14,14 @@ import java.net.URLClassLoader;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the server's plugins & the event system.
|
* Manages the server's plugins & the event system.
|
||||||
*/
|
*/
|
||||||
public final class PluginManager {
|
public final class PluginManager {
|
||||||
private final Map<String, Plugin> plugins = new HashMap<>();
|
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() {
|
public PluginManager() {
|
||||||
this.loadPlugins(); // Load all plugins from the plugins directory.
|
this.loadPlugins(); // Load all plugins from the plugins directory.
|
||||||
@ -68,7 +68,7 @@ public final class PluginManager {
|
|||||||
JarEntry entry = entries.nextElement();
|
JarEntry entry = entries.nextElement();
|
||||||
if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue;
|
if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue;
|
||||||
String className = entry.getName().replace(".class", "").replace("/", ".");
|
String className = entry.getName().replace(".class", "").replace("/", ".");
|
||||||
Class<?> clazz = loader.loadClass(className);
|
loader.loadClass(className);
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> pluginClass = loader.loadClass(pluginConfig.mainClass);
|
Class<?> pluginClass = loader.loadClass(pluginConfig.mainClass);
|
||||||
@ -129,11 +129,10 @@ public final class PluginManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a plugin's event listener.
|
* Registers a plugin's event listener.
|
||||||
* @param plugin The plugin instance.
|
|
||||||
* @param listener The event listener.
|
* @param listener The event listener.
|
||||||
*/
|
*/
|
||||||
public void registerListener(Plugin plugin, Listener listener) {
|
public void registerListener(EventHandler<?> listener) {
|
||||||
this.listeners.computeIfAbsent(plugin, k -> new ArrayList<>()).add(listener);
|
this.listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -141,23 +140,24 @@ public final class PluginManager {
|
|||||||
* @param event The event to invoke.
|
* @param event The event to invoke.
|
||||||
*/
|
*/
|
||||||
public void invokeEvent(Event event) {
|
public void invokeEvent(Event event) {
|
||||||
this.listeners.values().stream()
|
Stream<EventHandler<?>> handlers = this.listeners.stream()
|
||||||
.flatMap(Collection::stream)
|
.filter(handler -> event.getClass().isInstance(event));
|
||||||
.forEach(listener -> this.invokeOnListener(listener, 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) {
|
private void invokeHandler(Event event, EventHandler<?> handler) {
|
||||||
try {
|
if(!event.isCanceled() ||
|
||||||
Class<?> listenerClass = listener.getClass();
|
(event.isCanceled() && handler.ignoresCanceled())
|
||||||
Method[] methods = listenerClass.getMethods();
|
) handler.getCallback().accept(event);
|
||||||
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) { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,79 @@
|
|||||||
package emu.grasscutter.server.event;
|
package emu.grasscutter.server.event;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import emu.grasscutter.Grasscutter;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
|
|
||||||
/**
|
import java.util.function.Consumer;
|
||||||
* Declares a class as an event listener/handler.
|
|
||||||
*/
|
public final class EventHandler<E extends Event> {
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
private E event;
|
||||||
public @interface EventHandler {
|
|
||||||
|
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