mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-25 18:47:40 +01:00
Local node support (#688)
This commit is contained in:
parent
7c874bb588
commit
0cb2600929
@ -15,9 +15,13 @@ import net.minestom.server.coordinate.Pos;
|
|||||||
import net.minestom.server.coordinate.Vec;
|
import net.minestom.server.coordinate.Vec;
|
||||||
import net.minestom.server.entity.metadata.EntityMeta;
|
import net.minestom.server.entity.metadata.EntityMeta;
|
||||||
import net.minestom.server.event.EventDispatcher;
|
import net.minestom.server.event.EventDispatcher;
|
||||||
|
import net.minestom.server.event.EventFilter;
|
||||||
|
import net.minestom.server.event.EventHandler;
|
||||||
|
import net.minestom.server.event.EventNode;
|
||||||
import net.minestom.server.event.entity.*;
|
import net.minestom.server.event.entity.*;
|
||||||
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
|
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
|
||||||
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
|
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
|
||||||
|
import net.minestom.server.event.trait.EntityEvent;
|
||||||
import net.minestom.server.instance.Chunk;
|
import net.minestom.server.instance.Chunk;
|
||||||
import net.minestom.server.instance.EntityTracker;
|
import net.minestom.server.instance.EntityTracker;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
@ -77,7 +81,7 @@ import java.util.function.UnaryOperator;
|
|||||||
* <p>
|
* <p>
|
||||||
* To create your own entity you probably want to extends {@link LivingEntity} or {@link EntityCreature} instead.
|
* To create your own entity you probably want to extends {@link LivingEntity} or {@link EntityCreature} instead.
|
||||||
*/
|
*/
|
||||||
public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, TagHandler, PermissionHandler, HoverEventSource<ShowEntity>, Sound.Emitter {
|
public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, EventHandler<EntityEvent>, TagHandler, PermissionHandler, HoverEventSource<ShowEntity>, Sound.Emitter {
|
||||||
|
|
||||||
private static final Int2ObjectSyncMap<Entity> ENTITY_BY_ID = Int2ObjectSyncMap.hashmap();
|
private static final Int2ObjectSyncMap<Entity> ENTITY_BY_ID = Int2ObjectSyncMap.hashmap();
|
||||||
private static final Map<UUID, Entity> ENTITY_BY_UUID = new ConcurrentHashMap<>();
|
private static final Map<UUID, Entity> ENTITY_BY_UUID = new ConcurrentHashMap<>();
|
||||||
@ -143,6 +147,7 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ta
|
|||||||
protected final Set<Player> viewers = viewEngine.set;
|
protected final Set<Player> viewers = viewEngine.set;
|
||||||
private final MutableNBTCompound nbtCompound = new MutableNBTCompound();
|
private final MutableNBTCompound nbtCompound = new MutableNBTCompound();
|
||||||
private final Scheduler scheduler = Scheduler.newScheduler();
|
private final Scheduler scheduler = Scheduler.newScheduler();
|
||||||
|
private final EventNode<EntityEvent> eventNode = EventNode.type(toString(), EventFilter.ENTITY);
|
||||||
private final Set<Permission> permissions = new CopyOnWriteArraySet<>();
|
private final Set<Permission> permissions = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
protected UUID uuid;
|
protected UUID uuid;
|
||||||
@ -1543,6 +1548,12 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ta
|
|||||||
TagReadable.fromCompound(nbtCompound.toCompound()));
|
TagReadable.fromCompound(nbtCompound.toCompound()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
public @NotNull EventNode<EntityEvent> eventNode() {
|
||||||
|
return eventNode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies knockback to the entity
|
* Applies knockback to the entity
|
||||||
*
|
*
|
||||||
|
13
src/main/java/net/minestom/server/event/EventHandler.java
Normal file
13
src/main/java/net/minestom/server/event/EventHandler.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package net.minestom.server.event;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an element which can have {@link Event} listeners assigned to it.
|
||||||
|
*/
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface EventHandler<T extends Event> {
|
||||||
|
@NotNull EventNode<T> eventNode();
|
||||||
|
}
|
@ -20,11 +20,11 @@ import java.util.function.Consumer;
|
|||||||
non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||||
private static final Object GLOBAL_CHILD_LOCK = new Object();
|
private static final Object GLOBAL_CHILD_LOCK = new Object();
|
||||||
|
|
||||||
private final ClassValue<Handle<T>> handleMap = new ClassValue<>() {
|
private final ClassValue<ListenerHandle<T>> handleMap = new ClassValue<>() {
|
||||||
@Override
|
@Override
|
||||||
protected Handle<T> computeValue(Class<?> type) {
|
protected ListenerHandle<T> computeValue(Class<?> type) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return new Handle<>((Class<T>) type);
|
return createHandle((Class<T>) type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final Map<Class<? extends T>, ListenerEntry<T>> listenerMap = new ConcurrentHashMap<>();
|
private final Map<Class<? extends T>, ListenerEntry<T>> listenerMap = new ConcurrentHashMap<>();
|
||||||
@ -47,6 +47,10 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
this.eventType = filter.eventType();
|
this.eventType = filter.eventType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected @NotNull ListenerHandle<T> createHandle(@NotNull Class<T> listenerType) {
|
||||||
|
return new Handle<>(listenerType);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <E extends T> @NotNull ListenerHandle<E> getHandle(@NotNull Class<E> handleType) {
|
public <E extends T> @NotNull ListenerHandle<E> getHandle(@NotNull Class<E> handleType) {
|
||||||
@ -307,7 +311,7 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final class Handle<E extends Event> implements ListenerHandle<E> {
|
non-sealed class Handle<E extends Event> implements ListenerHandle<E> {
|
||||||
private static final VarHandle UPDATED;
|
private static final VarHandle UPDATED;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -2,7 +2,7 @@ package net.minestom.server.event;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object containing all the global event listeners.
|
* Object containing all the global event listeners.
|
||||||
@ -12,12 +12,34 @@ public final class GlobalEventHandler extends EventNodeImpl<Event> {
|
|||||||
super("global", EventFilter.ALL, null);
|
super("global", EventFilter.ALL, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @deprecated use {@link #addListener(Class, Consumer)}
|
protected @NotNull ListenerHandle<Event> createHandle(@NotNull Class<Event> listenerType) {
|
||||||
*/
|
return new GlobalHandle<>(listenerType);
|
||||||
@Deprecated
|
}
|
||||||
public <V extends Event> boolean addEventCallback(@NotNull Class<V> eventClass, @NotNull EventCallback<V> eventCallback) {
|
|
||||||
addListener(eventClass, eventCallback::run);
|
@SuppressWarnings("unchecked")
|
||||||
return true;
|
final class GlobalHandle<E extends Event> extends Handle<E> {
|
||||||
|
// Represents the filters where the handler has a node
|
||||||
|
private static final List<EventFilter<?, ?>> HANDLER_FILTERS = List.of(EventFilter.ENTITY);
|
||||||
|
// Local nodes handling
|
||||||
|
private final EventFilter<E, EventHandler<? super E>>[] localFilters;
|
||||||
|
|
||||||
|
GlobalHandle(Class<E> eventType) {
|
||||||
|
super(eventType);
|
||||||
|
// Filters with EventHandler support
|
||||||
|
this.localFilters = (EventFilter<E, EventHandler<? super E>>[]) HANDLER_FILTERS.stream()
|
||||||
|
.filter(filter -> filter.eventType().isAssignableFrom(eventType)).toArray(EventFilter[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(@NotNull E event) {
|
||||||
|
// Per-handler listeners
|
||||||
|
for (var filter : localFilters) {
|
||||||
|
var handle = filter.getHandler(event);
|
||||||
|
if (handle != null) handle.eventNode().call(event);
|
||||||
|
}
|
||||||
|
// Global listeners
|
||||||
|
super.call(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
package net.minestom.server.event.handler;
|
|
||||||
|
|
||||||
import net.minestom.server.event.Event;
|
|
||||||
import net.minestom.server.event.EventCallback;
|
|
||||||
import net.minestom.server.event.EventNode;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an element which can have {@link Event} listeners assigned to it.
|
|
||||||
* <p>
|
|
||||||
* Use {@link EventNode} directly.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface EventHandler<T extends Event> {
|
|
||||||
|
|
||||||
@ApiStatus.Internal
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
@NotNull EventNode<T> getEventNode();
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
default <V extends T> boolean addEventCallback(@NotNull Class<V> eventClass, @NotNull EventCallback<V> eventCallback) {
|
|
||||||
var node = getEventNode();
|
|
||||||
node.addListener(eventClass, eventCallback::run);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,9 @@
|
|||||||
package net.minestom.server.event;
|
package net.minestom.server.event;
|
||||||
|
|
||||||
|
import net.minestom.server.entity.Entity;
|
||||||
|
import net.minestom.server.entity.EntityType;
|
||||||
import net.minestom.server.event.trait.CancellableEvent;
|
import net.minestom.server.event.trait.CancellableEvent;
|
||||||
|
import net.minestom.server.event.trait.EntityEvent;
|
||||||
import net.minestom.server.event.trait.ItemEvent;
|
import net.minestom.server.event.trait.ItemEvent;
|
||||||
import net.minestom.server.event.trait.RecursiveEvent;
|
import net.minestom.server.event.trait.RecursiveEvent;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
@ -45,6 +48,13 @@ public class EventNodeTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record EntityTestEvent(Entity entity) implements EntityEvent {
|
||||||
|
@Override
|
||||||
|
public @NotNull Entity getEntity() {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCall() {
|
public void testCall() {
|
||||||
var node = EventNode.all("main");
|
var node = EventNode.all("main");
|
||||||
@ -234,4 +244,25 @@ public class EventNodeTest {
|
|||||||
node.call(new ItemTestEvent(item));
|
node.call(new ItemTestEvent(item));
|
||||||
assertFalse(result.get());
|
assertFalse(result.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void entityLocal() {
|
||||||
|
var node = new GlobalEventHandler();
|
||||||
|
var entity = new Entity(EntityType.ZOMBIE);
|
||||||
|
|
||||||
|
AtomicBoolean result = new AtomicBoolean(false);
|
||||||
|
var listener = EventListener.of(EntityTestEvent.class, event -> result.set(true));
|
||||||
|
entity.eventNode().addListener(listener);
|
||||||
|
|
||||||
|
assertFalse(result.get());
|
||||||
|
|
||||||
|
node.call(new EntityTestEvent(entity));
|
||||||
|
assertTrue(result.get());
|
||||||
|
|
||||||
|
result.set(false);
|
||||||
|
entity.eventNode().removeListener(listener);
|
||||||
|
|
||||||
|
node.call(new EntityTestEvent(entity));
|
||||||
|
assertFalse(result.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user