Implement an event handler

This commit is contained in:
KingRainbow44 2022-04-23 01:58:37 -04:00
parent 7a3fbcdcf7
commit 6056e962d6
6 changed files with 116 additions and 4 deletions

View File

@ -1,23 +1,25 @@
package emu.grasscutter.plugin; package emu.grasscutter.plugin;
import emu.grasscutter.Grasscutter; 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.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;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.Arrays; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* 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<>();
public PluginManager() { public PluginManager() {
this.loadPlugins(); // Load all plugins from the plugins directory. this.loadPlugins(); // Load all plugins from the plugins directory.
@ -113,4 +115,38 @@ public final class PluginManager {
plugin.onDisable(); plugin.onDisable();
}); });
} }
/**
* 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);
}
/**
* Invoke the provided event on all registered event listeners.
* @param event The event to invoke.
*/
public void invokeEvent(Event event) {
this.listeners.values().stream()
.flatMap(Collection::stream)
.forEach(listener -> this.invokeOnListener(listener, event));
}
/**
* Attempts to invoke the event on the provided listener.
*/
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) { }
}
} }

View File

@ -0,0 +1,8 @@
package emu.grasscutter.server.event;
/**
* Implementing this interface marks an event as cancellable.
*/
public interface Cancellable {
void cancel();
}

View File

@ -0,0 +1,33 @@
package emu.grasscutter.server.event;
import emu.grasscutter.Grasscutter;
/**
* A generic server event.
*/
public abstract class Event {
private boolean cancelled = false;
/**
* Return the cancelled state of the event.
*/
public boolean isCanceled() {
return this.cancelled;
}
/**
* Cancels the event if possible.
*/
public void cancel() throws IllegalAccessException {
if(!(this instanceof Cancellable))
throw new IllegalAccessException("Event is not cancellable.");
this.cancelled = true;
}
/**
* Pushes this event to all listeners.
*/
public void call() {
Grasscutter.getPluginManager().invokeEvent(this);
}
}

View File

@ -0,0 +1,11 @@
package emu.grasscutter.server.event;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Declares a class as an event listener/handler.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface EventHandler {
}

View File

@ -0,0 +1,7 @@
package emu.grasscutter.server.event;
/**
* Implementing this interface declares a class as an event listener.
*/
public interface Listener {
}

View File

@ -0,0 +1,17 @@
package emu.grasscutter.server.event;
/**
* An event that is related to the internals of the server.
*/
public abstract class ServerEvent extends Event {
protected final Type type;
public ServerEvent(Type type) {
this.type = type;
}
public enum Type {
DISPATCH,
GAME
}
}