From 50c0f01fb295a5904ab4b31c7f53c157773338b1 Mon Sep 17 00:00:00 2001 From: TheMode Date: Sat, 26 Feb 2022 00:10:26 +0100 Subject: [PATCH] View engine improvements (#715) --- .../net/minestom/server/entity/Entity.java | 33 +----- .../EntityView.java} | 102 +++++++----------- .../net/minestom/server/instance/Chunk.java | 24 +---- .../minestom/server/instance/ChunkView.java | 64 +++++++++++ .../minestom/server/utils/ViewEngineTest.java | 45 -------- 5 files changed, 111 insertions(+), 157 deletions(-) rename src/main/java/net/minestom/server/{utils/ViewEngine.java => entity/EntityView.java} (79%) create mode 100644 src/main/java/net/minestom/server/instance/ChunkView.java delete mode 100644 src/test/java/net/minestom/server/utils/ViewEngineTest.java diff --git a/src/main/java/net/minestom/server/entity/Entity.java b/src/main/java/net/minestom/server/entity/Entity.java index bf3ec3fbf..4b8ee7b45 100644 --- a/src/main/java/net/minestom/server/entity/Entity.java +++ b/src/main/java/net/minestom/server/entity/Entity.java @@ -40,7 +40,6 @@ import net.minestom.server.timer.Schedulable; import net.minestom.server.timer.Scheduler; import net.minestom.server.timer.TaskSchedule; import net.minestom.server.utils.PacketUtils; -import net.minestom.server.utils.ViewEngine; import net.minestom.server.utils.async.AsyncUtils; import net.minestom.server.utils.block.BlockIterator; import net.minestom.server.utils.chunk.ChunkUtils; @@ -135,36 +134,8 @@ public class Entity implements Viewable, Tickable, Schedulable, TagHandler, Perm } }; - protected final ViewEngine viewEngine = new ViewEngine(this, - player -> { - // Add viewable - var lock1 = player.getEntityId() < getEntityId() ? player : this; - var lock2 = lock1 == this ? player : this; - synchronized (lock1.viewEngine.mutex()) { - synchronized (lock2.viewEngine.mutex()) { - if (!Entity.this.viewEngine.viewableOption.predicate(player) || - !player.viewEngine.viewerOption.predicate(this)) return; - Entity.this.viewEngine.viewableOption.register(player); - player.viewEngine.viewerOption.register(this); - } - } - updateNewViewer(player); - }, - player -> { - // Remove viewable - var lock1 = player.getEntityId() < getEntityId() ? player : this; - var lock2 = lock1 == this ? player : this; - synchronized (lock1.viewEngine.mutex()) { - synchronized (lock2.viewEngine.mutex()) { - Entity.this.viewEngine.viewableOption.unregister(player); - player.viewEngine.viewerOption.unregister(this); - } - } - updateOldViewer(player); - }, - this instanceof Player player ? entity -> entity.viewEngine.viewableOption.addition.accept(player) : null, - this instanceof Player player ? entity -> entity.viewEngine.viewableOption.removal.accept(player) : null); - protected final Set viewers = viewEngine.asSet(); + protected final EntityView viewEngine = new EntityView(this); + protected final Set viewers = viewEngine.set; private final MutableNBTCompound nbtCompound = new MutableNBTCompound(); private final Scheduler scheduler = Scheduler.newScheduler(); private final Set permissions = new CopyOnWriteArraySet<>(); diff --git a/src/main/java/net/minestom/server/utils/ViewEngine.java b/src/main/java/net/minestom/server/entity/EntityView.java similarity index 79% rename from src/main/java/net/minestom/server/utils/ViewEngine.java rename to src/main/java/net/minestom/server/entity/EntityView.java index fc91e5257..9d54f4d7e 100644 --- a/src/main/java/net/minestom/server/utils/ViewEngine.java +++ b/src/main/java/net/minestom/server/entity/EntityView.java @@ -1,17 +1,14 @@ -package net.minestom.server.utils; +package net.minestom.server.entity; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import net.minestom.server.MinecraftServer; import net.minestom.server.coordinate.Point; -import net.minestom.server.entity.Entity; -import net.minestom.server.entity.Player; import net.minestom.server.instance.EntityTracker; import net.minestom.server.instance.Instance; import net.minestom.server.instance.InstanceContainer; import net.minestom.server.instance.SharedInstance; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,13 +17,9 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.function.Consumer; import java.util.function.Predicate; -/** - * Defines which players are able to see this element. - */ -@ApiStatus.Internal -public final class ViewEngine { +final class EntityView { + private static final int RANGE = MinecraftServer.getEntityViewDistance() * 16; private final Entity entity; - private final int range; private final Set manualViewers = new HashSet<>(); // Decide if this entity should be viewable to X players @@ -34,32 +27,42 @@ public final class ViewEngine { // Decide if this entity should view X entities public final Option viewerOption; - private final Set set; + final Set set = new SetImpl(); private final Object mutex = this; private volatile TrackedLocation trackedLocation; - public ViewEngine(@Nullable Entity entity, - Consumer autoViewableAddition, Consumer autoViewableRemoval, - Consumer autoViewerAddition, Consumer autoViewerRemoval) { + public EntityView(Entity entity) { this.entity = entity; - if (entity != null) { - this.range = MinecraftServer.getEntityViewDistance() * 16; - this.set = new EntitySet(); - } else { - this.range = MinecraftServer.getChunkViewDistance() * 16; - this.set = new ChunkSet(); - } - this.viewableOption = new Option<>(EntityTracker.Target.PLAYERS, Entity::autoViewEntities, autoViewableAddition, autoViewableRemoval); - this.viewerOption = new Option<>(EntityTracker.Target.ENTITIES, Entity::isAutoViewable, autoViewerAddition, autoViewerRemoval); - } - - public ViewEngine(@Nullable Entity entity) { - this(entity, null, null, null, null); - } - - public ViewEngine() { - this(null); + this.viewableOption = new Option<>(EntityTracker.Target.PLAYERS, Entity::autoViewEntities, + player -> { + // Add viewable + var lock1 = player.getEntityId() < entity.getEntityId() ? player : entity; + var lock2 = lock1 == entity ? player : entity; + synchronized (lock1.viewEngine.mutex) { + synchronized (lock2.viewEngine.mutex) { + if (!entity.viewEngine.viewableOption.predicate(player) || + !player.viewEngine.viewerOption.predicate(entity)) return; + entity.viewEngine.viewableOption.register(player); + player.viewEngine.viewerOption.register(entity); + } + } + entity.updateNewViewer(player); + }, player -> { + // Remove viewable + var lock1 = player.getEntityId() < entity.getEntityId() ? player : entity; + var lock2 = lock1 == entity ? player : entity; + synchronized (lock1.viewEngine.mutex) { + synchronized (lock2.viewEngine.mutex) { + entity.viewEngine.viewableOption.unregister(player); + player.viewEngine.viewerOption.unregister(entity); + } + } + entity.updateOldViewer(player); + }); + this.viewerOption = new Option<>(EntityTracker.Target.ENTITIES, Entity::isAutoViewable, + entity instanceof Player player ? e -> e.viewEngine.viewableOption.addition.accept(player) : null, + entity instanceof Player player ? e -> e.viewEngine.viewableOption.removal.accept(player) : null); } public void updateTracker(@Nullable Instance instance, @NotNull Point point) { @@ -124,17 +127,9 @@ public final class ViewEngine { } } - public Object mutex() { - return mutex; - } - - public Set asSet() { - return set; - } - public final class Option { @SuppressWarnings("rawtypes") - private static final AtomicIntegerFieldUpdater