Add Env#listen

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2022-01-29 08:37:17 +01:00
parent f05b4baa8a
commit d45ce9dab4
6 changed files with 89 additions and 6 deletions

View File

@ -24,6 +24,8 @@ public interface Env {
<E extends Event, H> @NotNull Collector<E> trackEvent(@NotNull Class<E> eventType, @NotNull EventFilter<? super E, H> filter, @NotNull H actor);
<E extends Event> @NotNull FlexibleListener<E> listen(@NotNull Class<E> eventType);
default void tick() {
process().ticker().tick(System.nanoTime());
}

View File

@ -0,0 +1,16 @@
package net.minestom.server.api;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
import java.lang.reflect.Method;
final class EnvCleaner implements InvocationInterceptor {
@Override
public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
invocation.proceed();
EnvImpl env = (EnvImpl) invocationContext.getArguments().get(0);
env.cleanup();
}
}

View File

@ -3,14 +3,19 @@ package net.minestom.server.api;
import net.minestom.server.ServerProcess;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventFilter;
import net.minestom.server.event.EventListener;
import net.minestom.server.event.EventNode;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import static org.junit.jupiter.api.Assertions.assertTrue;
final class EnvImpl implements Env {
private final ServerProcess process;
private final List<FlexibleListenerImpl<?>> listeners = new CopyOnWriteArrayList<>();
public EnvImpl(ServerProcess process) {
this.process = process;
@ -34,6 +39,20 @@ final class EnvImpl implements Env {
return tracker;
}
@Override
public @NotNull <E extends Event> FlexibleListener<E> listen(@NotNull Class<E> eventType) {
var handler = process.eventHandler();
var flexible = new FlexibleListenerImpl<>(eventType);
var listener = EventListener.of(eventType, e -> flexible.handler.accept(e));
handler.addListener(listener);
this.listeners.add(flexible);
return flexible;
}
void cleanup() {
this.listeners.forEach(FlexibleListenerImpl::check);
}
final class EventCollector<E extends Event> implements Collector<E> {
private final Object handler;
private final List<E> events = new CopyOnWriteArrayList<>();
@ -48,4 +67,36 @@ final class EnvImpl implements Env {
return List.copyOf(events);
}
}
static final class FlexibleListenerImpl<E extends Event> implements FlexibleListener<E> {
private final Class<E> eventType;
private Consumer<E> handler = e -> {
};
private boolean initialized;
private boolean called;
FlexibleListenerImpl(Class<E> eventType) {
this.eventType = eventType;
}
@Override
public void setHandler(@NotNull Consumer<E> handler) {
this.initialized = true;
this.called = false;
this.handler = e -> {
handler.accept(e);
this.called = true;
};
}
@Override
public void followup(@NotNull Consumer<E> handler) {
check();
setHandler(handler);
}
void check() {
assertTrue(!initialized || called, "Last listener has not been called: " + eventType.getSimpleName());
}
}
}

View File

@ -9,6 +9,7 @@ import java.lang.annotation.Target;
@ExtendWith(EnvParameterResolver.class)
@ExtendWith(EnvBefore.class)
@ExtendWith(EnvCleaner.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EnvTest {

View File

@ -0,0 +1,16 @@
package net.minestom.server.api;
import net.minestom.server.event.Event;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
public interface FlexibleListener<E extends Event> {
void setHandler(@NotNull Consumer<E> handler);
/**
* Updates the handler. Fails if the previous followup has not been called.
*/
void followup(@NotNull Consumer<E> handler);
}

View File

@ -3,7 +3,6 @@ package net.minestom.server.entity;
import net.minestom.server.api.Env;
import net.minestom.server.api.EnvTest;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.event.EventFilter;
import net.minestom.server.event.player.PlayerChangeHeldSlotEvent;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
@ -43,14 +42,12 @@ public class PlayerHeldIntegrationTest {
assertEquals(0, player.getHeldSlot());
player.addPacketToQueue(new ClientHeldItemChangePacket((short) 1));
var tracker = env.trackEvent(PlayerChangeHeldSlotEvent.class, EventFilter.PLAYER, player);
env.tick();
tracker.assertSingle(event -> {
var listener = env.listen(PlayerChangeHeldSlotEvent.class);
listener.followup(event -> {
assertEquals(player, event.getPlayer());
assertEquals(1, event.getSlot());
});
player.interpretPacketQueue();
assertEquals(ItemStack.of(Material.STONE), player.getItemInMainHand());
assertEquals(1, player.getHeldSlot());
}