Support old EventHandler API

This commit is contained in:
TheMode 2021-06-04 04:05:57 +02:00
parent 8b255651ab
commit d81df24132
5 changed files with 32 additions and 159 deletions

View File

@ -125,8 +125,8 @@ public final class MinecraftServer {
private static ExtensionManager extensionManager;
private static final GlobalEventHandler GLOBAL_EVENT_HANDLER = new GlobalEventHandler();
private static final EventNode<Event> GLOBAL_EVENT_NODE = EventNode.all();
private static final GlobalEventHandler GLOBAL_EVENT_HANDLER = new GlobalEventHandler();
private static UpdateManager updateManager;
private static MinecraftServer minecraftServer;

View File

@ -16,11 +16,12 @@ import net.minestom.server.collision.CollisionUtils;
import net.minestom.server.data.Data;
import net.minestom.server.data.DataContainer;
import net.minestom.server.entity.metadata.EntityMeta;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventCallback;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.EventFilter;
import net.minestom.server.event.EventNode;
import net.minestom.server.event.entity.*;
import net.minestom.server.event.handler.EventHandler;
import net.minestom.server.event.trait.EntityEvent;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.InstanceManager;
@ -62,7 +63,7 @@ import java.util.function.UnaryOperator;
* <p>
* To create your own entity you probably want to extends {@link LivingEntity} or {@link EntityCreature} instead.
*/
public class Entity implements Viewable, Tickable, EventHandler, DataContainer, PermissionHandler, HoverEventSource<ShowEntity> {
public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, DataContainer, PermissionHandler, HoverEventSource<ShowEntity> {
private static final Map<Integer, Entity> ENTITY_BY_ID = new ConcurrentHashMap<>();
private static final Map<UUID, Entity> ENTITY_BY_UUID = new ConcurrentHashMap<>();
@ -117,8 +118,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
private long lastAbsoluteSynchronizationTime;
// Events
private final Map<Class<? extends Event>, Collection<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
private final Map<String, Collection<EventCallback<?>>> extensionCallbacks = new ConcurrentHashMap<>();
private final EventNode<EntityEvent> eventNode = EventNode.type(EventFilter.ENTITY);
protected Metadata metadata = new Metadata(this);
protected EntityMeta entityMeta;
@ -155,6 +155,8 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
Entity.ENTITY_BY_ID.put(id, this);
Entity.ENTITY_BY_UUID.put(uuid, this);
MinecraftServer.getGlobalEventNode().map(this, eventNode);
}
public Entity(@NotNull EntityType entityType) {
@ -769,16 +771,9 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
}
}
@NotNull
@Override
public Map<Class<? extends Event>, Collection<EventCallback>> getEventCallbacksMap() {
return eventCallbacks;
}
@NotNull
@Override
public Collection<EventCallback<?>> getExtensionCallbacks(String extension) {
return extensionCallbacks.computeIfAbsent(extension, e -> new CopyOnWriteArrayList<>());
public @NotNull EventNode<EntityEvent> getEventNode() {
return eventNode;
}
/**

View File

@ -1,31 +1,22 @@
package net.minestom.server.event;
import net.minestom.server.MinecraftServer;
import net.minestom.server.event.handler.EventHandler;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Object containing all the global event listeners.
*/
public final class GlobalEventHandler implements EventHandler {
public final class GlobalEventHandler implements EventHandler<Event> {
// Events
private final Map<Class<? extends Event>, Collection<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
private final Map<String, Collection<EventCallback<?>>> extensionCallbacks = new ConcurrentHashMap<>();
private final EventNode<Event> node = EventNode.all();
@NotNull
@Override
public Map<Class<? extends Event>, Collection<EventCallback>> getEventCallbacksMap() {
return eventCallbacks;
{
MinecraftServer.getGlobalEventNode().addChild(node);
}
@NotNull
@Override
public Collection<EventCallback<?>> getExtensionCallbacks(String extension) {
return extensionCallbacks.computeIfAbsent(extension, e -> new CopyOnWriteArrayList<>());
public @NotNull EventNode<Event> getEventNode() {
return node;
}
}

View File

@ -1,126 +1,20 @@
package net.minestom.server.event.handler;
import net.minestom.server.MinecraftServer;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventCallback;
import net.minestom.server.extensions.IExtensionObserver;
import net.minestom.server.extras.selfmodification.MinestomRootClassLoader;
import net.minestom.server.event.EventNode;
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 Event} listeners assigned to it.
*/
public interface EventHandler extends IExtensionObserver {
public interface EventHandler<T extends Event> {
/**
* Gets a {@link Map} containing all the listeners assigned to a specific {@link Event} type.
*
* @return a {@link Map} with all the listeners
*/
@NotNull
Map<Class<? extends Event>, Collection<EventCallback>> getEventCallbacksMap();
@NotNull EventNode<T> getEventNode();
/**
* Gets a {@link Collection} containing all the listeners assigned to a specific extension (represented by its name).
* Used to unload all callbacks when the extension is unloaded
*
* @return a {@link Collection} with all the listeners
*/
@NotNull
Collection<EventCallback<?>> getExtensionCallbacks(String extension);
/**
* Adds a new event callback for the specified type {@code eventClass}.
*
* @param eventClass the event class
* @param eventCallback the event callback
* @param <E> the event type
* @return true if the callback collection changed as a result of the call
*/
default <E extends Event> boolean addEventCallback(@NotNull Class<E> eventClass, @NotNull EventCallback<E> eventCallback) {
String extensionSource = MinestomRootClassLoader.findExtensionObjectOwner(eventCallback);
if (extensionSource != null) {
MinecraftServer.getExtensionManager().getExtension(extensionSource).observe(this);
getExtensionCallbacks(extensionSource).add(eventCallback);
}
Collection<EventCallback> callbacks = getEventCallbacks(eventClass);
return callbacks.add(eventCallback);
default <V extends T> boolean addEventCallback(@NotNull Class<V> eventClass, @NotNull EventCallback<V> eventCallback) {
var node = getEventNode();
node.addListener(eventClass, eventCallback::run);
return true;
}
/**
* Removes an event callback.
*
* @param eventClass the event class
* @param eventCallback the event callback
* @param <E> the event type
* @return true if the callback was removed as a result of this call
*/
default <E extends Event> boolean removeEventCallback(@NotNull Class<E> eventClass, @NotNull EventCallback<E> eventCallback) {
Collection<EventCallback> callbacks = getEventCallbacks(eventClass);
String extensionSource = MinestomRootClassLoader.findExtensionObjectOwner(eventCallback);
if (extensionSource != null) {
getExtensionCallbacks(extensionSource).remove(eventCallback);
}
return callbacks.remove(eventCallback);
}
/**
* Gets the event callbacks of a specific event type.
*
* @param eventClass the event class
* @param <E> the event type
* @return all event callbacks for the specified type {@code eventClass}
*/
@NotNull
default <E extends Event> Collection<EventCallback> getEventCallbacks(@NotNull Class<E> eventClass) {
return getEventCallbacksMap().computeIfAbsent(eventClass, clazz -> new CopyOnWriteArraySet<>());
}
/**
* Gets a {@link Stream} containing all the {@link EventCallback}, no matter to which {@link Event} they are linked.
*
* @return a {@link Stream} containing all the callbacks
*/
@NotNull
default Stream<EventCallback> getEventCallbacks() {
return getEventCallbacksMap().values().stream().flatMap(Collection::stream);
}
/**
* Remove all event callbacks owned by the given extension
*
* @param extension the extension to remove callbacks from
*/
default void removeCallbacksOwnedByExtension(String extension) {
Collection<EventCallback<?>> extensionCallbacks = getExtensionCallbacks(extension);
for (EventCallback<?> callback : extensionCallbacks) {
// try to remove this callback from all callback collections
// we do this because we do not have information about the event class at this point
for (Collection<EventCallback> eventCallbacks : getEventCallbacksMap().values()) {
eventCallbacks.remove(callback);
}
}
extensionCallbacks.clear();
}
private <E extends Event> void runEvent(@NotNull Collection<EventCallback> eventCallbacks, @NotNull E event) {
for (EventCallback<E> eventCallback : eventCallbacks) {
eventCallback.run(event);
}
}
@Override
default void onExtensionUnload(String extensionName) {
removeCallbacksOwnedByExtension(extensionName);
}
}

View File

@ -12,13 +12,14 @@ import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.ExperienceOrb;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.pathfinding.PFInstanceSpace;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventCallback;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.EventFilter;
import net.minestom.server.event.EventNode;
import net.minestom.server.event.handler.EventHandler;
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
import net.minestom.server.event.instance.InstanceTickEvent;
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
import net.minestom.server.event.trait.InstanceEvent;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.CustomBlock;
@ -43,7 +44,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
/**
@ -57,7 +57,7 @@ import java.util.function.Consumer;
* you need to be sure to signal the {@link UpdateManager} of the changes using
* {@link UpdateManager#signalChunkLoad(Chunk)} and {@link UpdateManager#signalChunkUnload(Chunk)}.
*/
public abstract class Instance implements BlockModifier, Tickable, EventHandler, DataContainer, PacketGroupingAudience {
public abstract class Instance implements BlockModifier, Tickable, EventHandler<InstanceEvent>, DataContainer, PacketGroupingAudience {
protected static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
protected static final UpdateManager UPDATE_MANAGER = MinecraftServer.getUpdateManager();
@ -80,8 +80,7 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
// Field for tick events
private long lastTickAge = System.currentTimeMillis();
private final Map<Class<? extends Event>, Collection<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
private final Map<String, Collection<EventCallback<?>>> extensionCallbacks = new ConcurrentHashMap<>();
private final EventNode<InstanceEvent> eventNode = EventNode.type(EventFilter.INSTANCE);
// Entities present in this instance
protected final Set<Entity> entities = ConcurrentHashMap.newKeySet();
@ -120,6 +119,7 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
this.dimensionType = dimensionType;
this.worldBorder = new WorldBorder(this);
MinecraftServer.getGlobalEventNode().map(this, eventNode);
}
/**
@ -834,16 +834,9 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
this.data = data;
}
@NotNull
@Override
public Map<Class<? extends Event>, Collection<EventCallback>> getEventCallbacksMap() {
return eventCallbacks;
}
@NotNull
@Override
public Collection<EventCallback<?>> getExtensionCallbacks(String extension) {
return extensionCallbacks.computeIfAbsent(extension, e -> new CopyOnWriteArrayList<>());
public @NotNull EventNode<InstanceEvent> getEventNode() {
return eventNode;
}
// UNSAFE METHODS (need most of time to be synchronized)