Add node mapping support, for per-object listeners

This commit is contained in:
TheMode 2021-06-03 00:48:37 +02:00
parent 8f3b52a8b9
commit f8eb211d0d
3 changed files with 44 additions and 4 deletions

View File

@ -45,6 +45,10 @@ public interface EventNode<T extends Event> {
void removeListener(@NotNull EventListener<? extends T> listener);
<E extends T, V> void map(@NotNull EventFilter<E, V> filter, @NotNull V value, @NotNull EventNode<E> node);
void removeMap(@NotNull Object value);
@NotNull String getName();
@NotNull List<@NotNull EventNode<T>> getChildren();

View File

@ -13,6 +13,7 @@ class EventNodeImpl<T extends Event, H> implements EventNode<T> {
private final String name = "debug";
private final Map<Class<? extends T>, List<EventListener<T>>> listenerMap = new ConcurrentHashMap<>();
private final Map<Object, RedirectionEntry<T>> redirectionMap = new ConcurrentHashMap<>();
private final List<EventNode<T>> children = new CopyOnWriteArrayList<>();
protected final EventFilter<T, H> filter;
@ -41,6 +42,13 @@ class EventNodeImpl<T extends Event, H> implements EventNode<T> {
// Cancelled by superclass
return;
}
// Process redirection
final H handler = filter.getHandler(event);
final var entry = redirectionMap.get(handler);
if (entry != null) {
entry.node.call(event);
}
// Process listener list
final var listeners = listenerMap.get(event.getClass());
if (listeners != null && !listeners.isEmpty()) {
listeners.forEach(listener -> {
@ -50,6 +58,7 @@ class EventNodeImpl<T extends Event, H> implements EventNode<T> {
}
});
}
// Process children
this.children.forEach(eventNode -> eventNode.call(event));
}
@ -77,6 +86,19 @@ class EventNodeImpl<T extends Event, H> implements EventNode<T> {
listeners.remove(listener);
}
@Override
public <E extends T, V> void map(@NotNull EventFilter<E, V> filter, @NotNull V value, @NotNull EventNode<E> node) {
RedirectionEntry<E> entry = new RedirectionEntry<>();
entry.filter = filter;
entry.node = node;
this.redirectionMap.put(value, (RedirectionEntry<T>) entry);
}
@Override
public void removeMap(@NotNull Object value) {
this.redirectionMap.remove(value);
}
@Override
public @NotNull String getName() {
return name;
@ -86,4 +108,9 @@ class EventNodeImpl<T extends Event, H> implements EventNode<T> {
public @NotNull List<@NotNull EventNode<T>> getChildren() {
return Collections.unmodifiableList(children);
}
private static class RedirectionEntry<E extends Event> {
EventFilter<E, ?> filter;
EventNode<E> node;
}
}

View File

@ -147,13 +147,22 @@ public class PlayerInit {
empty.addListener(EventListener.of(PlayerMoveEvent.class, (event) -> {
}));
/*
* Map a node to a single element
*
* var test = EventNode.type(EventFilter.ENTITY);
* test.addListener(EventListener.of(PlayerMoveEvent.class, (event) ->
* System.out.println("creative player moved")));
* empty.map(EventFilter.ENTITY, entity, test);
*/
var conditional = EventNode.conditionalHandler(EventFilter.PLAYER, Player::isCreative);
conditional.addListener(EventListener.of(PlayerMoveEvent.class, (event) -> {
System.out.println("creative player moved");
}));
conditional.addListener(EventListener.of(PlayerMoveEvent.class, (event) ->
System.out.println("creative player moved")));
var list = EventNode.list(EventFilter.PLAYER);
list.addListener(EventListener.of(PlayerMoveEvent.class, playerMoveEvent -> System.out.println("move")));
list.addListener(EventListener.of(PlayerMoveEvent.class, event ->
System.out.println("move")));
GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
globalEventHandler.addEventCallback(EntityAttackEvent.class, event -> {