mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-02 14:38:26 +01:00
Add EventNode#hasListener
This commit is contained in:
parent
88a3a7d37c
commit
e16a662908
@ -213,6 +213,20 @@ public interface EventNode<T extends Event> {
|
||||
*/
|
||||
<E extends T> @NotNull ListenerHandle<E> getHandle(@NotNull Class<E> handleType);
|
||||
|
||||
/**
|
||||
* Gets if any listener has been registered for the given handle.
|
||||
* May trigger an update if the cached data is not correct.
|
||||
* <p>
|
||||
* Useful if you are able to avoid expensive computation in the case where
|
||||
* the event is unused. Be aware that {@link #call(Event, ListenerHandle)}
|
||||
* has similar optimization built-in.
|
||||
*
|
||||
* @param handle the listener handle
|
||||
* @param <E> the event type
|
||||
* @return true if the event has 1 or more listeners
|
||||
*/
|
||||
<E extends T> boolean hasListener(@NotNull ListenerHandle<E> handle);
|
||||
|
||||
/**
|
||||
* Execute a cancellable event with a callback to execute if the event is successful.
|
||||
* Event conditions and propagation is the same as {@link #call(Event)}.
|
||||
|
@ -43,11 +43,7 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
Check.argCondition(castedHandle.node != this, "Invalid handle owner");
|
||||
List<Consumer<T>> listeners = castedHandle.listeners;
|
||||
if (!castedHandle.updated) {
|
||||
synchronized (GLOBAL_CHILD_LOCK) {
|
||||
listeners.clear();
|
||||
castedHandle.update(this);
|
||||
castedHandle.updated = true;
|
||||
}
|
||||
castedHandle.update();
|
||||
}
|
||||
if (listeners.isEmpty()) return;
|
||||
for (Consumer<T> listener : listeners) {
|
||||
@ -62,6 +58,16 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
aClass -> new Handle<>(this, (Class<T>) aClass));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends T> boolean hasListener(@NotNull ListenerHandle<E> handle) {
|
||||
var castedHandle = (Handle<T>) handle;
|
||||
List<Consumer<T>> listeners = castedHandle.listeners;
|
||||
if (!castedHandle.updated) {
|
||||
castedHandle.update();
|
||||
}
|
||||
return !listeners.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends T> @NotNull List<EventNode<E>> findChildren(@NotNull String name, Class<E> eventType) {
|
||||
synchronized (GLOBAL_CHILD_LOCK) {
|
||||
@ -255,17 +261,25 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
}
|
||||
|
||||
private static final class Handle<E extends Event> implements ListenerHandle<E> {
|
||||
private final EventNode<E> node;
|
||||
private final EventNodeImpl<E> node;
|
||||
private final Class<E> eventType;
|
||||
private final List<Consumer<E>> listeners = new CopyOnWriteArrayList<>();
|
||||
private volatile boolean updated;
|
||||
|
||||
Handle(EventNode<E> node, Class<E> eventType) {
|
||||
Handle(EventNodeImpl<E> node, Class<E> eventType) {
|
||||
this.node = node;
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
void update(EventNodeImpl<E> targetNode) {
|
||||
void update() {
|
||||
synchronized (GLOBAL_CHILD_LOCK) {
|
||||
listeners.clear();
|
||||
recursiveUpdate(node);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void recursiveUpdate(EventNodeImpl<E> targetNode) {
|
||||
final var handleType = eventType;
|
||||
ListenerEntry<E> entry = targetNode.listenerMap.get(handleType);
|
||||
if (entry != null) appendEntry(listeners, entry, targetNode);
|
||||
@ -275,7 +289,7 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
children.stream()
|
||||
.filter(child -> child.eventType.isAssignableFrom(handleType)) // Invalid event type
|
||||
.sorted(Comparator.comparing(EventNode::getPriority))
|
||||
.forEach(this::update);
|
||||
.forEach(this::recursiveUpdate);
|
||||
}
|
||||
|
||||
static <E extends Event> void appendEntry(List<Consumer<E>> handleListeners, ListenerEntry<E> entry, EventNodeImpl<E> targetNode) {
|
||||
|
Loading…
Reference in New Issue
Block a user