mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-06 16:37:38 +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);
|
<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.
|
* 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)}.
|
* 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");
|
Check.argCondition(castedHandle.node != this, "Invalid handle owner");
|
||||||
List<Consumer<T>> listeners = castedHandle.listeners;
|
List<Consumer<T>> listeners = castedHandle.listeners;
|
||||||
if (!castedHandle.updated) {
|
if (!castedHandle.updated) {
|
||||||
synchronized (GLOBAL_CHILD_LOCK) {
|
castedHandle.update();
|
||||||
listeners.clear();
|
|
||||||
castedHandle.update(this);
|
|
||||||
castedHandle.updated = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (listeners.isEmpty()) return;
|
if (listeners.isEmpty()) return;
|
||||||
for (Consumer<T> listener : listeners) {
|
for (Consumer<T> listener : listeners) {
|
||||||
@ -62,6 +58,16 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
aClass -> new Handle<>(this, (Class<T>) aClass));
|
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
|
@Override
|
||||||
public <E extends T> @NotNull List<EventNode<E>> findChildren(@NotNull String name, Class<E> eventType) {
|
public <E extends T> @NotNull List<EventNode<E>> findChildren(@NotNull String name, Class<E> eventType) {
|
||||||
synchronized (GLOBAL_CHILD_LOCK) {
|
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 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 Class<E> eventType;
|
||||||
private final List<Consumer<E>> listeners = new CopyOnWriteArrayList<>();
|
private final List<Consumer<E>> listeners = new CopyOnWriteArrayList<>();
|
||||||
private volatile boolean updated;
|
private volatile boolean updated;
|
||||||
|
|
||||||
Handle(EventNode<E> node, Class<E> eventType) {
|
Handle(EventNodeImpl<E> node, Class<E> eventType) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.eventType = eventType;
|
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;
|
final var handleType = eventType;
|
||||||
ListenerEntry<E> entry = targetNode.listenerMap.get(handleType);
|
ListenerEntry<E> entry = targetNode.listenerMap.get(handleType);
|
||||||
if (entry != null) appendEntry(listeners, entry, targetNode);
|
if (entry != null) appendEntry(listeners, entry, targetNode);
|
||||||
@ -275,7 +289,7 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
children.stream()
|
children.stream()
|
||||||
.filter(child -> child.eventType.isAssignableFrom(handleType)) // Invalid event type
|
.filter(child -> child.eventType.isAssignableFrom(handleType)) // Invalid event type
|
||||||
.sorted(Comparator.comparing(EventNode::getPriority))
|
.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) {
|
static <E extends Event> void appendEntry(List<Consumer<E>> handleListeners, ListenerEntry<E> entry, EventNodeImpl<E> targetNode) {
|
||||||
|
Loading…
Reference in New Issue
Block a user