Do not prevent entity gc if a local listener is added

This commit is contained in:
themode 2022-03-05 17:38:27 +01:00
parent bd533fc2f2
commit cccbd98a3a
2 changed files with 25 additions and 2 deletions

View File

@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.ref.WeakReference;
import java.util.function.Consumer;
final class EventNodeLazyImpl<E extends Event> extends EventNodeImpl<E> {
@ -18,13 +19,13 @@ final class EventNodeLazyImpl<E extends Event> extends EventNodeImpl<E> {
}
}
private final Object owner;
private final WeakReference<Object> owner;
@SuppressWarnings("unused")
private boolean mapped;
EventNodeLazyImpl(@NotNull Object owner, @NotNull EventFilter<E, ?> filter) {
super(owner.toString(), filter, null);
this.owner = owner;
this.owner = new WeakReference<>(owner);
}
@Override
@ -59,6 +60,10 @@ final class EventNodeLazyImpl<E extends Event> extends EventNodeImpl<E> {
private void ensureMap() {
if (MAPPED.compareAndSet(this, false, true)) {
final Object owner = this.owner.get();
if (owner == null) {
throw new IllegalStateException("Node handle is null. Be sure to never cache a local node.");
}
MinecraftServer.getGlobalEventHandler().map(this, owner);
}
}

View File

@ -3,6 +3,7 @@ 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.entity.EntityTickEvent;
import net.minestom.server.network.packet.server.play.DestroyEntitiesPacket;
import net.minestom.server.utils.time.TimeUnit;
import org.junit.jupiter.api.Test;
@ -78,6 +79,23 @@ public class EntityRemovalIntegrationTest {
waitUntilCleared(ref);
}
@Test
public void entityNodeGC(Env env) {
// Ensure that the entities GCed when a local listener is present
var node = env.process().eventHandler();
var entity = new Entity(EntityType.ZOMBIE);
entity.eventNode().addListener(EntityTickEvent.class, event -> {
});
node.call(new EntityTickEvent(entity));
var ref = new WeakReference<>(entity);
entity.remove();
//noinspection UnusedAssignment
entity = null;
env.tick();
waitUntilCleared(ref);
}
static final class TestEntity extends Entity {
public TestEntity(long delay, TemporalUnit unit) {
super(EntityType.ZOMBIE);