{
@NotNull Logger getLogger();
/**
- * Gets the event bus for the platform.
- * WARNING: If you have {@link APIConfig#shouldUseAsyncEvents()} set to true, cast this to {@link EventBus.Async} when handling cancelled events.
+ * Gets the event handler for the platform.
* @return
*/
- @NotNull EventBus getEventBus();
+ @NotNull EventHandler getEventHandler();
/**
* Sets up the API for the platform. This method should be called automatically by the platform. Don't call it yourself.
diff --git a/api/src/main/java/me/tofaa/entitylib/event/EventBus.java b/api/src/main/java/me/tofaa/entitylib/event/EventBus.java
deleted file mode 100644
index 0cbd3eb..0000000
--- a/api/src/main/java/me/tofaa/entitylib/event/EventBus.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package me.tofaa.entitylib.event;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.util.function.Consumer;
-
-/**
- * A basic EventBus for scheduling and handling {@link EntityLibEvent}
- * Async event busses are not thread safe, and should be handled with care. This means theres no guarantee that the event will be cancelled in time.
- */
-public interface EventBus {
-
- static @NotNull EventBus newBus(boolean async) {
- return async ? new EventBusAsync() : new EventBusSync();
- }
-
- /**
- * Adds a listener to the EventBus.
- * @param listener The listener object
- * @param The type of {@link EntityLibEvent}
- */
- void addListener(@NotNull EventListener listener);
-
- /**
- * Adds a listener to the EventBus.
- * @param eventClass The events class
- * @param consumer The consumer for the event.
- * @param The type of {@link EntityLibEvent}
- */
- void addListener(@NotNull Class eventClass, @NotNull Consumer consumer);
-
- /**
- * Removes a listener from the EventBus.
- * @param listener the listener object.
- * @param The type of {@link EntityLibEvent}
- */
- void removeListener(@NotNull EventListener listener);
-
- /**
- * Calls the event and processes all the attached {@link EventListener} for the event.
- * If your bus is async, rather than using this, use {@link Async#call(EntityLibEvent, Consumer)} to avoid any race conditions.
- * @param event the event object to process handlers for.
- * @return the same event object, but already modified.
- * @param The type of {@link EntityLibEvent}
- */
- @NotNull T call(@NotNull T event);
-
-
- interface Async extends EventBus {
-
- /**
- * A safer way to handle and process an event. Does exactly what {@link EventBus#call(EntityLibEvent)} does but allows you to attach a callback, rather than working with it yourself,
- * the callback is executed on the thread this is called, and not the main thread.
- * @param event the event object to process handlers for.
- * @param completionCallback the callback handled after the event is consumed async
- * @param The type of {@link EntityLibEvent}
- */
- void call(@NotNull T event, @NotNull Consumer completionCallback);
-
- }
-
-}
diff --git a/api/src/main/java/me/tofaa/entitylib/event/EventBusAsync.java b/api/src/main/java/me/tofaa/entitylib/event/EventBusAsync.java
deleted file mode 100644
index 60608d5..0000000
--- a/api/src/main/java/me/tofaa/entitylib/event/EventBusAsync.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package me.tofaa.entitylib.event;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-
-final class EventBusAsync implements EventBus.Async {
-
- private final Map listeners = new ConcurrentHashMap();
- private final ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
-
- @Override
- public void addListener(@NotNull EventListener listener) {
- if (listeners.containsKey(listener.getEventClass())) {
- listeners.put(listener.getEventClass(), new HashSet<>());
- }
- ((HashSet) listeners.get(listener.getEventClass())).add(listener);
- }
-
- @Override
- public void addListener(@NotNull Class eventClass, @NotNull Consumer consumer) {
- addListener(EventListener.generateListener(eventClass, consumer));
-
- }
-
- @Override
- public void removeListener(@NotNull EventListener listener) {
- if (listeners.containsKey(listener.getEventClass())) {
- ((HashSet) listeners.get(listener.getEventClass())).remove(listener);
- }
- }
-
- @Override
- public @NotNull T call(@NotNull T event) {
- executor.execute(() -> dispatchEvent(event));
- return event;
- }
-
-
- private void dispatchEvent(T event) {
- if (!listeners.containsKey(event.getClass())) return;
- HashSet> consumers = (HashSet>) listeners.get(event.getClass());
- consumers.forEach(consumer -> consumer.handle(event));
- }
-
-
- @Override
- public void call(@NotNull T event, @NotNull Consumer completionCallback) {
- executor.execute(() -> {
- dispatchEvent(event);
- completionCallback.accept(event);
- });
- }
-}
diff --git a/api/src/main/java/me/tofaa/entitylib/event/EventBusSync.java b/api/src/main/java/me/tofaa/entitylib/event/EventBusSync.java
deleted file mode 100644
index 4ca6b53..0000000
--- a/api/src/main/java/me/tofaa/entitylib/event/EventBusSync.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package me.tofaa.entitylib.event;
-
-
-import org.jetbrains.annotations.NotNull;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Consumer;
-
-@SuppressWarnings("unchecked")
-class EventBusSync implements EventBus {
-
- private final Map listeners = new ConcurrentHashMap();
-
- @Override
- public void addListener(@NotNull EventListener listener) {
- if (listeners.containsKey(listener.getEventClass())) {
- listeners.put(listener.getEventClass(), new HashSet<>());
- }
- ((HashSet) listeners.get(listener.getEventClass())).add(listener);
- }
-
- @Override
- public void addListener(@NotNull Class eventClass, @NotNull Consumer consumer) {
- addListener(EventListener.generateListener(eventClass, consumer));
- }
-
- @Override
- public void removeListener(@NotNull EventListener listener) {
- if (listeners.containsKey(listener.getEventClass())) {
- ((HashSet) listeners.get(listener.getEventClass())).remove(listener);
- }
- }
-
- @Override
- public @NotNull T call(@NotNull T event) {
- if (!listeners.containsKey(event.getClass())) return event;
- HashSet> consumers = (HashSet>) listeners.get(event.getClass());
- consumers.forEach(consumer -> consumer.handle(event));
- return event;
- }
-}
diff --git a/api/src/main/java/me/tofaa/entitylib/event/EventCallback.java b/api/src/main/java/me/tofaa/entitylib/event/EventCallback.java
new file mode 100644
index 0000000..a03ac27
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/event/EventCallback.java
@@ -0,0 +1,10 @@
+package me.tofaa.entitylib.event;
+
+import org.jetbrains.annotations.NotNull;
+
+@FunctionalInterface
+public interface EventCallback {
+
+ void run(@NotNull E event);
+
+}
\ No newline at end of file
diff --git a/api/src/main/java/me/tofaa/entitylib/event/EventHandler.java b/api/src/main/java/me/tofaa/entitylib/event/EventHandler.java
new file mode 100644
index 0000000..86c6bfc
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/event/EventHandler.java
@@ -0,0 +1,115 @@
+package me.tofaa.entitylib.event;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.stream.Stream;
+
+/**
+ * Represents an element which can have {@link EntityLibEvent} listeners assigned to it.
+ */
+public interface EventHandler {
+
+ static @NotNull EventHandler create() {
+ return new EventHandlerImpl();
+ }
+
+ /**
+ * Gets a {@link Map} containing all the listeners assigned to a specific {@link EntityLibEvent} type.
+ *
+ * @return a {@link Map} with all the listeners
+ */
+ @NotNull
+ Map, Collection> getEventCallbacksMap();
+
+ /**
+ * Adds a new event callback for the specified type {@code eventClass}.
+ *
+ * @param eventClass the event class
+ * @param eventCallback the event callback
+ * @param the event type
+ * @return true if the callback collection changed as a result of the call
+ */
+ default boolean addEventCallback(@NotNull Class eventClass, @NotNull EventCallback eventCallback) {
+ Collection callbacks = getEventCallbacks(eventClass);
+ return callbacks.add(eventCallback);
+ }
+
+ /**
+ * Removes an event callback.
+ *
+ * @param eventClass the event class
+ * @param eventCallback the event callback
+ * @param the event type
+ * @return true if the callback was removed as a result of this call
+ */
+ default boolean removeEventCallback(@NotNull Class eventClass, @NotNull EventCallback eventCallback) {
+ Collection callbacks = getEventCallbacks(eventClass);
+ return callbacks.remove(eventCallback);
+ }
+
+ /**
+ * Gets the event callbacks of a specific event type.
+ *
+ * @param eventClass the event class
+ * @param the event type
+ * @return all event callbacks for the specified type {@code eventClass}
+ */
+ @NotNull
+ default Collection getEventCallbacks(@NotNull Class eventClass) {
+ return getEventCallbacksMap().computeIfAbsent(eventClass, clazz -> new CopyOnWriteArraySet<>());
+ }
+
+ /**
+ * Gets a {@link Stream} containing all the {@link EventCallback}, no matter to which {@link EntityLibEvent} they are linked.
+ *
+ * @return a {@link Stream} containing all the callbacks
+ */
+ @NotNull
+ default Stream getEventCallbacks() {
+ return getEventCallbacksMap().values().stream().flatMap(Collection::stream);
+ }
+
+ /**
+ * Calls the specified {@link EntityLibEvent} with all the assigned {@link EventCallback}.
+ *
+ * Events are always called in the current thread.
+ *
+ * @param eventClass the event class
+ * @param event the event object
+ * @param the event type
+ */
+ default void callEvent(@NotNull Class eventClass, @NotNull E event) {
+ final Collection eventCallbacks = getEventCallbacks(eventClass);
+ runEvent(eventCallbacks, event);
+ }
+
+ /**
+ * Calls a {@link CancellableEntityLibEvent} and execute {@code successCallback} if the {@link EntityLibEvent} is not cancelled.
+ *
+ * Does call {@link #callEvent(Class, EntityLibEvent)} internally.
+ *
+ * @param eventClass the event class
+ * @param event the event object
+ * @param successCallback the callback called when the event is not cancelled
+ * @param the event type
+ * @see #callEvent(Class, EntityLibEvent)
+ */
+ default void callCancellableEvent(@NotNull Class eventClass,
+ @NotNull E event,
+ @NotNull Runnable successCallback) {
+ callEvent(eventClass, event);
+ if (!event.isCancelled()) {
+ successCallback.run();
+ }
+ }
+
+ default void runEvent(@NotNull Collection eventCallbacks, @NotNull E event) {
+ for (EventCallback eventCallback : eventCallbacks) {
+ eventCallback.run(event);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/api/src/main/java/me/tofaa/entitylib/event/EventHandlerImpl.java b/api/src/main/java/me/tofaa/entitylib/event/EventHandlerImpl.java
new file mode 100644
index 0000000..bcfa2f0
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/event/EventHandlerImpl.java
@@ -0,0 +1,27 @@
+package me.tofaa.entitylib.event;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+final class EventHandlerImpl implements EventHandler {
+
+ // Events
+ private final Map, Collection> eventCallbacks = new ConcurrentHashMap<>();
+
+ EventHandlerImpl() {
+ }
+
+ public void registerListener(EventListener listener) {
+ addEventCallback(listener.getEventClass(), EventListener.createEventCallback(listener));
+ }
+
+ @NotNull
+ @Override
+ public Map, Collection> getEventCallbacksMap() {
+ return eventCallbacks;
+ }
+
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/event/EventListener.java b/api/src/main/java/me/tofaa/entitylib/event/EventListener.java
index f58dddc..73ad4b8 100644
--- a/api/src/main/java/me/tofaa/entitylib/event/EventListener.java
+++ b/api/src/main/java/me/tofaa/entitylib/event/EventListener.java
@@ -10,6 +10,10 @@ public interface EventListener {
void handle(@NotNull E event);
+ static EventCallback createEventCallback(@NotNull EventListener listener) {
+ return listener::handle;
+ }
+
static EventListener generateListener(Class eventClass, Consumer consumer) {
return new EventListener() {
@Override
diff --git a/api/src/main/java/me/tofaa/entitylib/event/types/tracking/GeneralTrackingEvent.java b/api/src/main/java/me/tofaa/entitylib/event/types/GeneralTrackingEvent.java
similarity index 92%
rename from api/src/main/java/me/tofaa/entitylib/event/types/tracking/GeneralTrackingEvent.java
rename to api/src/main/java/me/tofaa/entitylib/event/types/GeneralTrackingEvent.java
index b45f5dd..cb082b6 100644
--- a/api/src/main/java/me/tofaa/entitylib/event/types/tracking/GeneralTrackingEvent.java
+++ b/api/src/main/java/me/tofaa/entitylib/event/types/GeneralTrackingEvent.java
@@ -1,4 +1,4 @@
-package me.tofaa.entitylib.event.types.tracking;
+package me.tofaa.entitylib.event.types;
import com.github.retrooper.packetevents.protocol.player.User;
import me.tofaa.entitylib.TrackedEntity;
diff --git a/api/src/main/java/me/tofaa/entitylib/event/types/UserReceiveMetaUpdateEvent.java b/api/src/main/java/me/tofaa/entitylib/event/types/UserReceiveMetaUpdateEvent.java
deleted file mode 100644
index 9d232a3..0000000
--- a/api/src/main/java/me/tofaa/entitylib/event/types/UserReceiveMetaUpdateEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package me.tofaa.entitylib.event.types;
-
-import com.github.retrooper.packetevents.protocol.player.User;
-import me.tofaa.entitylib.event.CancellableEntityLibEvent;
-import me.tofaa.entitylib.event.EntityLibEvent;
-import me.tofaa.entitylib.meta.EntityMeta;
-
-public final class UserReceiveMetaUpdateEvent implements CancellableEntityLibEvent {
-
- private final User user;
- private boolean cancelled;
- private EntityMeta meta;
-
- public UserReceiveMetaUpdateEvent(User user) {
- this.user = user;
- }
-
- public User getUser() {
- return user;
- }
-
- @Override
- public boolean isCancelled() {
- return cancelled;
- }
-
- @Override
- public void setCancelled(boolean cancelled) {
- this.cancelled = cancelled;
- }
-}
diff --git a/api/src/main/java/me/tofaa/entitylib/event/types/UserRefreshEntityEvent.java b/api/src/main/java/me/tofaa/entitylib/event/types/UserRefreshEntityEvent.java
deleted file mode 100644
index 20d7e3a..0000000
--- a/api/src/main/java/me/tofaa/entitylib/event/types/UserRefreshEntityEvent.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package me.tofaa.entitylib.event.types;
-
-import com.github.retrooper.packetevents.protocol.player.User;
-import me.tofaa.entitylib.event.CancellableEntityLibEvent;
-import me.tofaa.entitylib.event.EntityLibEvent;
-import me.tofaa.entitylib.wrapper.WrapperEntity;
-
-public class UserRefreshEntityEvent implements CancellableEntityLibEvent {
-
- private final User user;
- private final WrapperEntity entity;
- private boolean cancelled;
-
- public UserRefreshEntityEvent(User user, WrapperEntity entity) {
- this.user = user;
- this.entity = entity;
- }
-
- public User getUser() {
- return user;
- }
-
-
- public WrapperEntity getEntity() {
- return entity;
- }
-
- @Override
- public boolean isCancelled() {
- return cancelled;
- }
-
- @Override
- public void setCancelled(boolean cancelled) {
- this.cancelled = cancelled;
- }
-}
diff --git a/api/src/main/java/me/tofaa/entitylib/event/types/tracking/UserStopTrackingEntityEvent.java b/api/src/main/java/me/tofaa/entitylib/event/types/UserStopTrackingEntityEvent.java
similarity index 73%
rename from api/src/main/java/me/tofaa/entitylib/event/types/tracking/UserStopTrackingEntityEvent.java
rename to api/src/main/java/me/tofaa/entitylib/event/types/UserStopTrackingEntityEvent.java
index fa2ab7c..5e550ef 100644
--- a/api/src/main/java/me/tofaa/entitylib/event/types/tracking/UserStopTrackingEntityEvent.java
+++ b/api/src/main/java/me/tofaa/entitylib/event/types/UserStopTrackingEntityEvent.java
@@ -1,11 +1,12 @@
-package me.tofaa.entitylib.event.types.tracking;
+package me.tofaa.entitylib.event.types;
import com.github.retrooper.packetevents.protocol.player.User;
import me.tofaa.entitylib.TrackedEntity;
+import me.tofaa.entitylib.event.EntityLibEvent;
import org.jetbrains.annotations.NotNull;
-public class UserStopTrackingEntityEvent extends GeneralTrackingEvent {
+public class UserStopTrackingEntityEvent extends GeneralTrackingEvent implements EntityLibEvent {
public UserStopTrackingEntityEvent(@NotNull User user, @NotNull TrackedEntity entity) {
diff --git a/api/src/main/java/me/tofaa/entitylib/event/types/tracking/UserTrackingEntityEvent.java b/api/src/main/java/me/tofaa/entitylib/event/types/UserTrackingEntityEvent.java
similarity index 73%
rename from api/src/main/java/me/tofaa/entitylib/event/types/tracking/UserTrackingEntityEvent.java
rename to api/src/main/java/me/tofaa/entitylib/event/types/UserTrackingEntityEvent.java
index 26e946f..59b6ada 100644
--- a/api/src/main/java/me/tofaa/entitylib/event/types/tracking/UserTrackingEntityEvent.java
+++ b/api/src/main/java/me/tofaa/entitylib/event/types/UserTrackingEntityEvent.java
@@ -1,10 +1,11 @@
-package me.tofaa.entitylib.event.types.tracking;
+package me.tofaa.entitylib.event.types;
import com.github.retrooper.packetevents.protocol.player.User;
import me.tofaa.entitylib.TrackedEntity;
+import me.tofaa.entitylib.event.EntityLibEvent;
import org.jetbrains.annotations.NotNull;
-public final class UserTrackingEntityEvent extends GeneralTrackingEvent {
+public final class UserTrackingEntityEvent extends GeneralTrackingEvent implements EntityLibEvent {
public UserTrackingEntityEvent(@NotNull User user, @NotNull TrackedEntity entity) {
diff --git a/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java b/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java
index 141228d..1c32de9 100644
--- a/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java
+++ b/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java
@@ -1,11 +1,10 @@
package me.tofaa.entitylib.common;
import me.tofaa.entitylib.*;
-import me.tofaa.entitylib.event.EventBus;
+import me.tofaa.entitylib.event.EventHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
import java.util.stream.Stream;
@@ -14,7 +13,7 @@ public abstract class AbstractPlatform
implements Platform
{
protected final P handle;
protected Logger logger;
- private EventBus eventBus;
+ private EventHandler eventHandler;
private EntityIdProvider entityIdProvider;
private EntityUuidProvider entityUuidProvider;
@@ -36,11 +35,9 @@ public abstract class AbstractPlatform
implements Platform
{
@Override
public void setupApi(@NotNull APIConfig settings) {
- this.eventBus = EventBus.newBus(settings.shouldUseAsyncEvents());
+ this.eventHandler = EventHandler.create();
this.entityIdProvider = new EntityIdProvider.DefaultEntityIdProvider();
this.entityUuidProvider = new EntityUuidProvider.DefaultEntityUuidProvider();
-
-
}
@NotNull
@@ -73,8 +70,8 @@ public abstract class AbstractPlatform