mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-17 13:41:24 +01:00
Cache listener handles for mapped nodes
Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
parent
f9c67d9b2b
commit
d9c000f80a
@ -1,5 +1,6 @@
|
|||||||
package net.minestom.server.event;
|
package net.minestom.server.event;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.Pair;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.event.trait.RecursiveEvent;
|
import net.minestom.server.event.trait.RecursiveEvent;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
@ -11,6 +12,7 @@ import java.util.*;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@ -320,53 +322,43 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
final var mappedNodeCache = targetNode.mappedNodeCache;
|
final var mappedNodeCache = targetNode.mappedNodeCache;
|
||||||
if (mappedNodeCache.isEmpty()) return;
|
if (mappedNodeCache.isEmpty()) return;
|
||||||
Set<EventFilter<E, ?>> filters = new HashSet<>(mappedNodeCache.size());
|
Set<EventFilter<E, ?>> filters = new HashSet<>(mappedNodeCache.size());
|
||||||
|
Map<Object, Pair<EventNode<E>, ListenerHandle<E>>> handlers = new HashMap<>(mappedNodeCache.size());
|
||||||
// Retrieve all filters used to retrieve potential handlers
|
// Retrieve all filters used to retrieve potential handlers
|
||||||
for (var mappedEntry : mappedNodeCache.entrySet()) {
|
for (var mappedEntry : mappedNodeCache.entrySet()) {
|
||||||
final EventNodeImpl<E> mappedNode = mappedEntry.getValue();
|
final EventNodeImpl<E> mappedNode = mappedEntry.getValue();
|
||||||
if (!mappedNode.eventType.isAssignableFrom(eventType)) continue;
|
final Class<E> mappedNodeType = mappedNode.eventType;
|
||||||
final var mappedListeners = mappedNode.listenerMap;
|
if (!mappedNodeType.isAssignableFrom(eventType)) continue;
|
||||||
if (mappedListeners.isEmpty())
|
if (mappedNode.listenerMap.isEmpty())
|
||||||
continue; // The mapped node does not have any listener (perhaps throw a warning?)
|
continue; // The mapped node does not have any listener (perhaps throw a warning?)
|
||||||
forTargetEvents(eventType, type -> {
|
filters.add(mappedNode.filter);
|
||||||
if (!mappedListeners.containsKey(type)) return; // No normal listener to this handle type
|
handlers.put(mappedEntry.getKey(), Pair.of(mappedNode, mappedNode.getHandle(eventType)));
|
||||||
filters.add(mappedNode.filter);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// If at least one mapped node listen to this handle type,
|
// If at least one mapped node listen to this handle type,
|
||||||
// loop through them and forward to mapped node if there is a match
|
// loop through them and forward to mapped node if there is a match
|
||||||
if (!filters.isEmpty()) {
|
if (!filters.isEmpty()) {
|
||||||
final var filterList = List.copyOf(filters);
|
final var filterList = List.copyOf(filters);
|
||||||
final int size = filterList.size();
|
final int size = filterList.size();
|
||||||
|
final BiConsumer<EventFilter<E, ?>, E> mapper = (filter, event) -> {
|
||||||
|
final Object handler = filter.castHandler(event);
|
||||||
|
final var mapResult = handlers.get(handler);
|
||||||
|
if (mapResult != null) mapResult.first().call(event, mapResult.second());
|
||||||
|
};
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
final var firstFilter = filterList.get(0);
|
final var firstFilter = filterList.get(0);
|
||||||
this.listeners.add(event -> {
|
// Common case where there is only one filter
|
||||||
// Common case where there is only one filter
|
this.listeners.add(event -> mapper.accept(firstFilter, event));
|
||||||
final Object handler = firstFilter.castHandler(event);
|
|
||||||
final EventNode<E> mappedNode = mappedNodeCache.get(handler);
|
|
||||||
if (mappedNode != null) mappedNode.call(event);
|
|
||||||
});
|
|
||||||
} else if (size == 2) {
|
} else if (size == 2) {
|
||||||
final var firstFilter = filterList.get(0);
|
final var firstFilter = filterList.get(0);
|
||||||
final var secondFilter = filterList.get(1);
|
final var secondFilter = filterList.get(1);
|
||||||
this.listeners.add(event -> {
|
this.listeners.add(event -> {
|
||||||
// First check
|
mapper.accept(firstFilter, event);
|
||||||
final Object handler1 = firstFilter.castHandler(event);
|
mapper.accept(secondFilter, event);
|
||||||
final EventNode<E> mappedNode1 = mappedNodeCache.get(handler1);
|
|
||||||
if (mappedNode1 != null) mappedNode1.call(event);
|
|
||||||
|
|
||||||
// Second check
|
|
||||||
final Object handler2 = secondFilter.castHandler(event);
|
|
||||||
final EventNode<E> mappedNode2 = mappedNodeCache.get(handler2);
|
|
||||||
if (mappedNode2 != null) mappedNode2.call(event);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.listeners.add(event -> {
|
this.listeners.add(event -> {
|
||||||
for (var filter : filterList) {
|
for (var filter : filterList) {
|
||||||
final Object handler = filter.castHandler(event);
|
mapper.accept(filter, event);
|
||||||
final EventNode<E> mappedNode = mappedNodeCache.get(handler);
|
|
||||||
if (mappedNode != null) mappedNode.call(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user