diff --git a/src/main/java/net/minestom/server/event/CancellableEvent.java b/src/main/java/net/minestom/server/event/CancellableEvent.java
index ef821f834..aae8df57d 100644
--- a/src/main/java/net/minestom/server/event/CancellableEvent.java
+++ b/src/main/java/net/minestom/server/event/CancellableEvent.java
@@ -2,6 +2,7 @@ package net.minestom.server.event;
/**
* Represents an {@link Event} which can be cancelled.
+ * Called using {@link EventDispatcher#callCancellable(CancellableEvent, Runnable)}.
*/
public interface CancellableEvent extends Event {
diff --git a/src/main/java/net/minestom/server/event/Event.java b/src/main/java/net/minestom/server/event/Event.java
index 6253a2cd4..7c2408b1a 100644
--- a/src/main/java/net/minestom/server/event/Event.java
+++ b/src/main/java/net/minestom/server/event/Event.java
@@ -5,7 +5,7 @@ import net.minestom.server.event.handler.EventHandler;
/**
* Event which can be listened to by an {@link EventHandler}.
*
- * Called using {@link EventHandler#callEvent(Class, Event)}.
+ * Called using {@link EventDispatcher#call(Event)}.
*/
public interface Event {
}
diff --git a/src/main/java/net/minestom/server/event/EventFilter.java b/src/main/java/net/minestom/server/event/EventFilter.java
index 3bdda0dea..4a7740266 100644
--- a/src/main/java/net/minestom/server/event/EventFilter.java
+++ b/src/main/java/net/minestom/server/event/EventFilter.java
@@ -11,6 +11,20 @@ import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
+/**
+ * Represents a filter for a specific {@link Event} type.
+ *
+ * The handler represents a "target" of the event. This can be used
+ * to create filters for all events of a specific type using information
+ * about the target.
+ *
+ * For example, the target of a {@link PlayerEvent} is a {@link Player} so
+ * you could create a player event filter which checks if the target player
+ * is in creative mode.
+ *
+ * @param The event type to filter
+ * @param The handler type to filter on.
+ */
public interface EventFilter {
EventFilter ALL = from(Event.class, null);
@@ -35,7 +49,19 @@ public interface EventFilter {
};
}
+ /**
+ * Gets the handler for the given event instance, or null if the event
+ * type has no handler.
+ *
+ * @param event The event instance
+ * @return The handler, if it exists for the given event
+ */
@Nullable H getHandler(@NotNull E event);
+ /**
+ * The event type to filter on.
+ *
+ * @return The event type.
+ */
@NotNull Class getEventType();
}
diff --git a/src/main/java/net/minestom/server/event/EventListener.java b/src/main/java/net/minestom/server/event/EventListener.java
index 63c100c43..3d2c41036 100644
--- a/src/main/java/net/minestom/server/event/EventListener.java
+++ b/src/main/java/net/minestom/server/event/EventListener.java
@@ -9,6 +9,13 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Predicate;
+/**
+ * Represents an event listener (handler) in an event graph.
+ *
+ * A listener is responsible for executing some action based on an event triggering.
+ *
+ * @param The event type being handled.
+ */
public interface EventListener {
@NotNull Class getEventType();
@@ -20,6 +27,15 @@ public interface EventListener {
return new EventListener.Builder<>(eventType);
}
+ /**
+ * Create an event listener without any special options. The given listener will be executed
+ * if the event passes all parent filtering.
+ *
+ * @param eventType The event type to handle
+ * @param listener The handler function
+ * @param The event type to handle
+ * @return An event listener with the given properties
+ */
@Contract(pure = true)
static @NotNull EventListener of(@NotNull Class eventType, @NotNull Consumer<@NotNull T> listener) {
return new EventListener<>() {
@@ -47,24 +63,43 @@ public interface EventListener {
this.eventType = eventType;
}
+ /**
+ * Adds a filter to the executor of this listener. The executor will only
+ * be called if this condition passes on the given event.
+ */
@Contract(value = "_ -> this")
public @NotNull EventListener.Builder filter(Predicate filter) {
this.filters.add(filter);
return this;
}
+ /**
+ * Removes this listener after it has been executed the given number of times.
+ *
+ * @param expireCount The number of times to execute
+ */
@Contract(value = "_ -> this")
public @NotNull EventListener.Builder expireCount(int expireCount) {
this.expireCount = expireCount;
return this;
}
+ /**
+ * Expires this listener when it passes the given condition. The expiration will
+ * happen before the event is executed.
+ *
+ * @param expireWhen The condition to test
+ */
@Contract(value = "_ -> this")
public @NotNull EventListener.Builder expireWhen(Predicate expireWhen) {
this.expireWhen = expireWhen;
return this;
}
+ /**
+ * Sets the handler for this event listener. This will be executed if the listener passes
+ * all conditions.
+ */
@Contract(value = "_ -> this")
public @NotNull EventListener.Builder handler(Consumer handler) {
this.handler = handler;
diff --git a/src/main/java/net/minestom/server/event/EventNode.java b/src/main/java/net/minestom/server/event/EventNode.java
index fd6e2dbd0..6b02e7f19 100644
--- a/src/main/java/net/minestom/server/event/EventNode.java
+++ b/src/main/java/net/minestom/server/event/EventNode.java
@@ -16,26 +16,67 @@ import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Predicate;
+/**
+ * Represents a single node in an event graph.
+ *
+ * A node may contain any number of children and/or listeners. When an event is called,
+ * the node will filter it based on the parameters given at creation and then propagate
+ * it down to child nodes and listeners if it passes.
+ *
+ * @param The event type accepted by this node
+ */
public class EventNode {
+ /**
+ * Creates an event node which accepts any event type with no filtering.
+ *
+ * @param name The name of the node
+ * @return An event node with no filtering
+ */
@Contract(value = "_ -> new", pure = true)
public static @NotNull EventNode all(@NotNull String name) {
return type(name, EventFilter.ALL);
}
- @Contract(value = "_, _, _ -> new", pure = true)
- public static @NotNull EventNode type(@NotNull String name,
- @NotNull EventFilter filter,
- @NotNull BiPredicate predicate) {
- return create(name, filter, predicate);
- }
-
+ /**
+ * Creates an event node which accepts any event of the given type. The type is provided
+ * by the {@link EventFilter}.
+ *
+ * For example, you could create an event filter which only accepts player events with the following
+ *
+ * var playerEventNode = EventNode.type("demo", EventFilter.PLAYER);
+ *
+ *
+ * @param name The name of the event node
+ * @param filter The event type filter to apply
+ * @param The resulting event type of the node
+ * @return A node with just an event type filter
+ */
@Contract(value = "_, _ -> new", pure = true)
public static @NotNull EventNode type(@NotNull String name,
@NotNull EventFilter filter) {
return create(name, filter, null);
}
+ /**
+ * Creates an event node which accepts any event of the given type which passes
+ * the provided condition. The condition is based on the event object itself.
+ *
+ * For example, you could create an event filter which only accepts player events
+ * where the player is in the pos x/z quadrant of the world.
+ *
+ * var playerInPosXZNode = EventNode.event("abc", EventFilter.PLAYER, event -> {
+ * var position = event.getPlayer().getPosition();
+ * return position.getX() > 0 && position.getZ() > 0;
+ * });
+ *
+ *
+ * @param name The name of the event node
+ * @param filter The event type filter to apply
+ * @param predicate The event condition
+ * @param The resulting event type of the node
+ * @return A node with an event type filter as well as a condition on the event.
+ */
@Contract(value = "_, _, _ -> new", pure = true)
public static @NotNull EventNode event(@NotNull String name,
@NotNull EventFilter filter,
@@ -43,6 +84,52 @@ public class EventNode {
return create(name, filter, (e, h) -> predicate.test(e));
}
+ /**
+ * Creates an event node which accepts any event of the given type which passes
+ * the provided condition. The condition is based on the event object as well as
+ * the event handler type defined in the {@link EventFilter}.
+ *
+ * For example, you could create an event filter which only accepts player events
+ * where the player is in the pos x/z quadrant of the world.
+ *
+ * var playerInPosXZNode = EventNode.type("abc", EventFilter.PLAYER, (event, player) -> {
+ * var position = player.getPosition();
+ * return position.getX() > 0 && position.getZ() > 0;
+ * });
+ *
+ *
+ * @param name The name of the event node
+ * @param filter The event type filter to apply
+ * @param predicate The event condition
+ * @param The resulting event type of the node
+ * @param The handler type of the event filter
+ * @return A node with an event type filter as well as a condition on the event.
+ */
+ @Contract(value = "_, _, _ -> new", pure = true)
+ public static @NotNull EventNode type(@NotNull String name,
+ @NotNull EventFilter filter,
+ @NotNull BiPredicate predicate) {
+ return create(name, filter, predicate);
+ }
+
+ /**
+ * Creates an event node which accepts any event of the given type which passes
+ * the provided condition. The condition is based on the event handler defined
+ * by the {@link EventFilter}.
+ *
+ * For example, you could create an event filter which only accepts player events
+ * where the player is in creative mode.
+ *
+ * var playerIsCreative = EventNode.value("abc", EventFilter.PLAYER, Player::isCreative);
+ *
+ *
+ * @param name The name of the event node
+ * @param filter The event type filter to apply
+ * @param predicate The event condition
+ * @param The resulting event type of the node
+ * @param The handler type of the event filter
+ * @return A node with an event type filter as well as a condition on the event.
+ */
@Contract(value = "_, _, _ -> new", pure = true)
public static @NotNull EventNode value(@NotNull String name,
@NotNull EventFilter filter,
@@ -50,6 +137,18 @@ public class EventNode {
return create(name, filter, (e, h) -> predicate.test(h));
}
+ /**
+ * Creates an event node which accepts any event of the given type which has a handler who
+ * has the given tag.
+ *
+ * The {@link EventFilter}'s resulting event type must be {@link TagReadable}.
+ *
+ * @param name The name of the event node
+ * @param filter The event type filter to apply
+ * @param tag The tag which must be contained on the event handler
+ * @param The resulting event type of the node
+ * @return A node with an event type filter as well as a handler with the provided tag
+ */
@Contract(value = "_, _, _ -> new", pure = true)
public static @NotNull EventNode tag(@NotNull String name,
@NotNull EventFilter filter,
@@ -57,6 +156,17 @@ public class EventNode {
return create(name, filter, (e, h) -> h.hasTag(tag));
}
+ /**
+ * Creates an event node which accepts any event of the given type which has a handler who
+ * has an applicable tag. An applicable tag means that it passes the given condition.
+ *
+ * @param name The name of the event node
+ * @param filter The event type filter to apply
+ * @param tag The tag which must be contained on the event handler
+ * @param consumer The condition to test against the tag, if it exists.
+ * @param The resulting event type of the node
+ * @return A node with an event type filter as well as a handler with the provided tag
+ */
@Contract(value = "_, _, _, _ -> new", pure = true)
public static @NotNull EventNode tag(@NotNull String name,
@NotNull EventFilter filter,
@@ -106,6 +216,15 @@ public class EventNode {
return predicate.test(event, value);
}
+ /**
+ * Executes the given event on this node. The event must pass all conditions before
+ * it will be forwarded to the listeners.
+ *
+ * Calling an event on a node will execute all child nodes, however, an event may be
+ * called anywhere on the event graph and it will propagate down from there only.
+ *
+ * @param event the event to execute
+ */
public void call(@NotNull T event) {
final var eventClass = event.getClass();
if (!eventType.isAssignableFrom(eventClass)) {
@@ -140,6 +259,13 @@ public class EventNode {
}
}
+ /**
+ * 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)}.
+ *
+ * @param event The event to execute
+ * @param successCallback A callback if the event is not cancelled
+ */
public void callCancellable(@NotNull T event, @NotNull Runnable successCallback) {
call(event);
if (!(event instanceof CancellableEvent) || !((CancellableEvent) event).isCancelled()) {
@@ -168,11 +294,24 @@ public class EventNode {
return parent;
}
+ /**
+ * Returns an unmodifiable view of the children in this node.
+ *
+ * @see #addChild(EventNode)
+ * @see #removeChild(EventNode)
+ */
@Contract(pure = true)
public @NotNull Set<@NotNull EventNode> getChildren() {
return Collections.unmodifiableSet(children);
}
+ /**
+ * Locates all child nodes with the given name and event type recursively starting at this node.
+ *
+ * @param name The event node name to filter for
+ * @param eventType The event node type to filter for
+ * @return All matching event nodes
+ */
@Contract(pure = true)
public @NotNull List> findChildren(@NotNull String name, Class eventType) {
if (children.isEmpty()) {
@@ -190,11 +329,26 @@ public class EventNode {
}
}
+ /**
+ * Locates all child nodes with the given name and event type recursively starting at this node.
+ *
+ * @param name The event name to filter for
+ * @return All matching event nodes
+ */
@Contract(pure = true)
public @NotNull List> findChildren(@NotNull String name) {
return findChildren(name, eventType);
}
+ /**
+ * Replaces all children matching the given name and type recursively starting from this node.
+ *
+ * Node: The callee may not be replaced by this call.
+ *
+ * @param name The event name to filter for
+ * @param eventType The event node type to filter for
+ * @param eventNode The replacement node
+ */
public void replaceChildren(@NotNull String name, @NotNull Class eventType, @NotNull EventNode eventNode) {
if (children.isEmpty()) {
return;
@@ -211,10 +365,24 @@ public class EventNode {
}
}
+ /**
+ * Replaces all children matching the given name and type recursively starting from this node.
+ *
+ * Node: The callee may not be replaced by this call.
+ *
+ * @param name The node name to filter for
+ * @param eventNode The replacement node
+ */
public void replaceChildren(@NotNull String name, @NotNull EventNode eventNode) {
replaceChildren(name, eventType, eventNode);
}
+ /**
+ * Recursively removes children with the given name and type starting at this node.
+ *
+ * @param name The node name to filter for
+ * @param eventType The node type to filter for
+ */
public void removeChildren(@NotNull String name, @NotNull Class eventType) {
if (children.isEmpty()) {
return;
@@ -230,10 +398,21 @@ public class EventNode {
}
}
+ /**
+ * Recursively removes children with the given name starting at this node.
+ *
+ * @param name The node name to filter for
+ */
public void removeChildren(@NotNull String name) {
removeChildren(name, eventType);
}
+ /**
+ * Directly adds a child node to this node.
+ *
+ * @param child The child to add
+ * @return this, can be used for chaining
+ */
@Contract(value = "_ -> this")
public @NotNull EventNode addChild(@NotNull EventNode extends T> child) {
synchronized (GLOBAL_CHILD_LOCK) {
@@ -257,6 +436,12 @@ public class EventNode {
return this;
}
+ /**
+ * Directly removes the given child from this node.
+ *
+ * @param child The child to remove
+ * @return this, can be used for chaining
+ */
@Contract(value = "_ -> this")
public @NotNull EventNode removeChild(@NotNull EventNode extends T> child) {
synchronized (GLOBAL_CHILD_LOCK) {
diff --git a/src/main/java/net/minestom/server/event/trait/EntityEvent.java b/src/main/java/net/minestom/server/event/trait/EntityEvent.java
index 44469d44f..dd78a2027 100644
--- a/src/main/java/net/minestom/server/event/trait/EntityEvent.java
+++ b/src/main/java/net/minestom/server/event/trait/EntityEvent.java
@@ -4,6 +4,9 @@ import net.minestom.server.entity.Entity;
import net.minestom.server.event.Event;
import org.jetbrains.annotations.NotNull;
+/**
+ * Represents any event called on an {@link Entity}.
+ */
public interface EntityEvent extends Event {
/**
diff --git a/src/main/java/net/minestom/server/event/trait/InstanceEvent.java b/src/main/java/net/minestom/server/event/trait/InstanceEvent.java
index d122c290a..7defc9b03 100644
--- a/src/main/java/net/minestom/server/event/trait/InstanceEvent.java
+++ b/src/main/java/net/minestom/server/event/trait/InstanceEvent.java
@@ -4,6 +4,9 @@ import net.minestom.server.event.Event;
import net.minestom.server.instance.Instance;
import org.jetbrains.annotations.NotNull;
+/**
+ * Represents any event targeting an {@link Instance}.
+ */
public interface InstanceEvent extends Event {
/**
diff --git a/src/main/java/net/minestom/server/event/trait/InventoryEvent.java b/src/main/java/net/minestom/server/event/trait/InventoryEvent.java
index 25d26d4ad..726741531 100644
--- a/src/main/java/net/minestom/server/event/trait/InventoryEvent.java
+++ b/src/main/java/net/minestom/server/event/trait/InventoryEvent.java
@@ -4,6 +4,9 @@ import net.minestom.server.event.Event;
import net.minestom.server.inventory.Inventory;
import org.jetbrains.annotations.Nullable;
+/**
+ * Represents any event inside an {@link Inventory}.
+ */
public interface InventoryEvent extends Event {
/**
diff --git a/src/main/java/net/minestom/server/event/trait/ItemEvent.java b/src/main/java/net/minestom/server/event/trait/ItemEvent.java
index 5ccecded4..fc30a769d 100644
--- a/src/main/java/net/minestom/server/event/trait/ItemEvent.java
+++ b/src/main/java/net/minestom/server/event/trait/ItemEvent.java
@@ -4,6 +4,9 @@ import net.minestom.server.event.Event;
import net.minestom.server.item.ItemStack;
import org.jetbrains.annotations.NotNull;
+/**
+ * Represents any event called about an {@link ItemStack}.
+ */
public interface ItemEvent extends Event {
@NotNull ItemStack getItemStack();
}
diff --git a/src/main/java/net/minestom/server/event/trait/PlayerEvent.java b/src/main/java/net/minestom/server/event/trait/PlayerEvent.java
index 2fb8834fd..8ca030995 100644
--- a/src/main/java/net/minestom/server/event/trait/PlayerEvent.java
+++ b/src/main/java/net/minestom/server/event/trait/PlayerEvent.java
@@ -3,6 +3,9 @@ package net.minestom.server.event.trait;
import net.minestom.server.entity.Player;
import org.jetbrains.annotations.NotNull;
+/**
+ * Represents any event called on a {@link Player}.
+ */
public interface PlayerEvent extends EntityEvent {
/**