From 43fc7ad6247400a352f5d0e35daab21c0095096e Mon Sep 17 00:00:00 2001 From: TheMode Date: Thu, 19 Aug 2021 07:12:53 +0200 Subject: [PATCH] Add support for EventBinding --- .../minestom/server/event/EventNodeImpl.java | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/minestom/server/event/EventNodeImpl.java b/src/main/java/net/minestom/server/event/EventNodeImpl.java index 0cc36ba86..502b587d1 100644 --- a/src/main/java/net/minestom/server/event/EventNodeImpl.java +++ b/src/main/java/net/minestom/server/event/EventNodeImpl.java @@ -41,11 +41,14 @@ class EventNodeImpl implements EventNode { public void call(@NotNull E event, ListenerHandle handle) { var castedHandle = (Handle) handle; Check.stateCondition(castedHandle.node != this, "Invalid handle owner"); + List> listeners = castedHandle.listeners; if (!castedHandle.updated) { - handle(castedHandle); + listeners.clear(); + synchronized (GLOBAL_CHILD_LOCK) { + handle(castedHandle); + } castedHandle.updated = true; } - List> listeners = castedHandle.listeners; if (listeners.isEmpty()) return; for (Consumer listener : listeners) { listener.accept(event); @@ -61,9 +64,13 @@ class EventNodeImpl implements EventNode { private void handle(Handle handle) { ListenerEntry entry = listenerMap.get(handle.eventType); if (entry != null) { + // Add normal listeners for (var listener : entry.listeners) { handle.listeners.add(listener::run); } + // Add bindings + handle.listeners.addAll(entry.bindingConsumers); + // TODO mapped node } // Add children if (children.isEmpty()) return; @@ -189,12 +196,25 @@ class EventNodeImpl implements EventNode { @Override public void register(@NotNull EventBinding binding) { - // TODO + synchronized (GLOBAL_CHILD_LOCK) { + for (var eventType : binding.eventTypes()) { + ListenerEntry entry = getEntry((Class) eventType); + final boolean added = entry.bindingConsumers.add((Consumer) binding.consumer(eventType)); + if (added) propagateEvent((Class) eventType); + } + } } @Override public void unregister(@NotNull EventBinding binding) { - // TODO + synchronized (GLOBAL_CHILD_LOCK) { + for (var eventType : binding.eventTypes()) { + ListenerEntry entry = listenerMap.get(eventType); + if (entry == null) return; + final boolean removed = entry.bindingConsumers.remove(binding.consumer(eventType)); + if (removed) propagateEvent((Class) eventType); + } + } } @Override @@ -224,15 +244,15 @@ class EventNodeImpl implements EventNode { } private void propagateEvents() { - this.listenerMap.forEach((eventClass, eventListeners) -> propagateEvent(eventClass)); + this.listenerMap.keySet().forEach(this::propagateEvent); } private void propagateEvent(Class eventClass) { final var parent = this.parent; if (parent == null) return; - var handle = parent.handleMap.get(eventClass); - if (handle == null) return; - handle.updated = false; + Handle parentHandle = parent.handleMap.get(eventClass); + if (parentHandle == null) return; + parentHandle.updated = false; parent.propagateEvent(eventClass); } @@ -248,13 +268,13 @@ class EventNodeImpl implements EventNode { private static class ListenerEntry { final List> listeners = new CopyOnWriteArrayList<>(); + final Set> bindingConsumers = new CopyOnWriteArraySet<>(); } private static final class Handle implements ListenerHandle { private final EventNode node; private final Class eventType; private final List> listeners = new CopyOnWriteArrayList<>(); - private volatile boolean updated; Handle(EventNode node, Class eventType) {