diff --git a/pom.xml b/pom.xml
index 5576082..aad9dfc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
dev.unlegitdqrk
unlegitlibrary
- 1.7.8
+ 1.7.9
https://unlegitdqrk.dev/
Just a big library
diff --git a/src/main/java/dev/unlegitdqrk/unlegitlibrary/event/EventManager.java b/src/main/java/dev/unlegitdqrk/unlegitlibrary/event/EventManager.java
index 6417439..12859b3 100644
--- a/src/main/java/dev/unlegitdqrk/unlegitlibrary/event/EventManager.java
+++ b/src/main/java/dev/unlegitdqrk/unlegitlibrary/event/EventManager.java
@@ -1,96 +1,120 @@
package dev.unlegitdqrk.unlegitlibrary.event;
import dev.unlegitdqrk.unlegitlibrary.event.impl.Event;
-import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
-public final class EventManager extends DefaultMethodsOverrider {
+public final class EventManager {
- private final Map, Map>> registeredListener = new HashMap<>();
- private final Map, Object> eventListeners = new HashMap<>();
+ // eventClass -> priority -> listenerInstance -> method
+ private final Map, Map>> registeredListener =
+ new ConcurrentHashMap<>();
- public void registerListener(Class extends EventListener> listenerClass) throws Exception {
- if (isListenerRegistered(listenerClass)) return;
+ // listenerClass -> set of listener instances (identity-based)
+ private final Map, Set> eventListeners =
+ new ConcurrentHashMap<>();
- EventListener instance = listenerClass.getDeclaredConstructor().newInstance();
- registerListenerInstance(instance);
+ public EventManager() {
}
- public void registerListener(EventListener listenerInstance) {
- if (listenerInstance == null) throw new IllegalArgumentException("Listener instance cannot be null");
- Class extends EventListener> listenerClass = listenerInstance.getClass();
- if (isListenerRegistered(listenerClass)) return;
-
- registerListenerInstance(listenerInstance);
+ public void registerListener(Class extends EventListener> clazz) throws Exception {
+ if (clazz == null) throw new IllegalArgumentException("Listener class cannot be null");
+ EventListener instance = clazz.getDeclaredConstructor().newInstance();
+ registerListener(instance);
}
- private void registerListenerInstance(Object instance) {
- for (Method method : instance.getClass().getDeclaredMethods()) {
- Listener listenerAnnotation = method.getAnnotation(Listener.class);
+ public void registerListener(EventListener listener) {
+ if (listener == null) throw new IllegalArgumentException("Listener instance cannot be null");
- if (listenerAnnotation == null || method.getParameterCount() != 1) continue;
+ // Track instance set for class (identity-based)
+ eventListeners
+ .computeIfAbsent(listener.getClass(), k -> Collections.newSetFromMap(new IdentityHashMap<>()))
+ .add(listener);
- Class> paramType = method.getParameterTypes()[0];
- if (!Event.class.isAssignableFrom(paramType)) continue;
+ registerListenerInstance(listener);
+ }
- @SuppressWarnings("unchecked")
- Class extends Event> eventClass = (Class extends Event>) paramType;
+ private void registerListenerInstance(Object listener) {
+ // Walk up class hierarchy so superclass @Listener methods are registered too
+ for (Class> c = listener.getClass(); c != null && c != Object.class; c = c.getSuperclass()) {
+ Method[] methods = c.getDeclaredMethods();
- registeredListener
- .computeIfAbsent(eventClass, k -> new EnumMap<>(EventPriority.class))
- .computeIfAbsent(listenerAnnotation.priority(), k -> new HashMap<>())
- .put(instance, method);
+ for (Method method : methods) {
+ Listener annotation = method.getAnnotation(Listener.class);
+ if (annotation == null) continue;
+
+ if (method.getParameterCount() != 1) continue;
+
+ Class> param = method.getParameterTypes()[0];
+ if (!Event.class.isAssignableFrom(param)) continue;
+
+ @SuppressWarnings("unchecked")
+ Class extends Event> eventClass = (Class extends Event>) param;
+
+ registeredListener
+ .computeIfAbsent(eventClass, k -> new EnumMap<>(EventPriority.class))
+ .computeIfAbsent(annotation.priority(), k -> Collections.synchronizedMap(new IdentityHashMap<>()))
+ .put(listener, method);
+ }
+ }
+ }
+
+ public synchronized void unregisterListener(Class extends EventListener> clazz) {
+ if (clazz == null) return;
+
+ Set instances = eventListeners.remove(clazz);
+ if (instances == null || instances.isEmpty()) return;
+
+ for (EventListener instance : instances) {
+ unregisterListener(instance);
+ }
+ }
+
+ public synchronized void unregisterListener(EventListener listener) {
+ if (listener == null) return;
+
+ Set instances = eventListeners.get(listener.getClass());
+ if (instances != null) {
+ instances.remove(listener);
+ if (instances.isEmpty()) eventListeners.remove(listener.getClass());
}
- eventListeners.put((Class extends EventListener>) instance.getClass(), instance);
- }
-
- public synchronized void unregisterListener(Class extends EventListener> listenerClass) {
- if (!isListenerRegistered(listenerClass)) return;
-
- Object instance = eventListeners.get(listenerClass);
-
- for (Map> priorityMap : registeredListener.values()) {
- for (Map