diff --git a/leaf-server/minecraft-patches/features/0166-Multithreaded-Tracker.patch b/leaf-server/minecraft-patches/features/0166-Multithreaded-Tracker.patch index 64a98080..15ef82a7 100644 --- a/leaf-server/minecraft-patches/features/0166-Multithreaded-Tracker.patch +++ b/leaf-server/minecraft-patches/features/0166-Multithreaded-Tracker.patch @@ -28,28 +28,10 @@ However we still recommend to use those packet based NPC plugins, e.g. ZNPC Plus, Adyeshach, Fancy NPC, etc. diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java -index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6644b6914 100644 +index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..356ec20eff799aa12ed6b4f9e54e8721c50a0068 100644 --- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java +++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java -@@ -60,7 +60,16 @@ public final class NearbyPlayers { - - private final ServerLevel world; - private final Reference2ReferenceOpenHashMap players = new Reference2ReferenceOpenHashMap<>(); -- private final Long2ReferenceOpenHashMap byChunk = new Long2ReferenceOpenHashMap<>(); -+ // Leaf start - Multithreaded tracker -+ private final it.unimi.dsi.fastutil.longs.Long2ReferenceMap byChunk; -+ { -+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) { -+ byChunk = it.unimi.dsi.fastutil.longs.Long2ReferenceMaps.synchronize(new Long2ReferenceOpenHashMap<>()); -+ } else { -+ byChunk = new Long2ReferenceOpenHashMap<>(); -+ } -+ } -+ // Leaf end - Multithreaded tracker - private final Long2ReferenceOpenHashMap>[] directByChunk = new Long2ReferenceOpenHashMap[TOTAL_MAP_TYPES]; - { - for (int i = 0; i < this.directByChunk.length; ++i) { -@@ -164,6 +173,8 @@ public final class NearbyPlayers { +@@ -164,6 +164,8 @@ public final class NearbyPlayers { private int nonEmptyLists; private long updateCount; @@ -58,7 +40,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6 public TrackedChunk(final long chunkKey, final NearbyPlayers nearbyPlayers) { this.chunkKey = chunkKey; this.nearbyPlayers = nearbyPlayers; -@@ -177,6 +188,12 @@ public final class NearbyPlayers { +@@ -177,6 +179,12 @@ public final class NearbyPlayers { return this.updateCount; } @@ -71,7 +53,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6 public ReferenceList getPlayers(final NearbyMapType type) { return this.players[type.ordinal()]; } -@@ -185,6 +202,12 @@ public final class NearbyPlayers { +@@ -185,6 +193,12 @@ public final class NearbyPlayers { ++this.updateCount; final int idx = type.ordinal(); @@ -84,7 +66,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6 final ReferenceList list = this.players[idx]; if (list == null) { ++this.nonEmptyLists; -@@ -203,6 +226,12 @@ public final class NearbyPlayers { +@@ -203,6 +217,12 @@ public final class NearbyPlayers { ++this.updateCount; final int idx = type.ordinal(); @@ -98,7 +80,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6 if (list == null) { throw new IllegalStateException("Does not contain player " + player); diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java -index bdc1200ef5317fdaf58973bf580b0a672aee800f..e36086cd3c205e66ba1028343028af2239c1d93f 100644 +index bdc1200ef5317fdaf58973bf580b0a672aee800f..f34b8012d48ce1b69c1a1529d7ae46b624785ffa 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java @@ -344,7 +344,7 @@ public final class RegionizedPlayerChunkLoader { @@ -116,7 +98,7 @@ index bdc1200ef5317fdaf58973bf580b0a672aee800f..e36086cd3c205e66ba1028343028af22 PlayerChunkSender.sendChunk(this.player.connection, this.world, chunk); + // Leaf start - Multithreaded tracker + if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) { -+ ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk trackedChunk = this.world.moonrise$getNearbyPlayers().getChunk(chunkX, chunkZ); ++ ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk trackedChunk = chunk.moonrise$getChunkHolder().holderData.nearbyPlayers; + if (trackedChunk != null) { + trackedChunk.trackingUpdateCountAtomic.getAndIncrement(); + } diff --git a/leaf-server/minecraft-patches/features/0183-Cache-chunk-key.patch b/leaf-server/minecraft-patches/features/0183-Cache-chunk-key.patch index 97d57b10..88f7ab83 100644 --- a/leaf-server/minecraft-patches/features/0183-Cache-chunk-key.patch +++ b/leaf-server/minecraft-patches/features/0183-Cache-chunk-key.patch @@ -9,10 +9,10 @@ This patch didn't cahce SectionPos or BlockPos to chunkKey, since they are mutab The JMH benchmark of this patch can be found in SunBox's `CacheChunkKey` diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java -index 2a2626e90836ae52a8a686b2040843c6644b6914..283e02b32cae0bc1b0cd71602795aa48987903db 100644 +index 356ec20eff799aa12ed6b4f9e54e8721c50a0068..499cad369242f9ad724b3251538d62d8dc8d2ec8 100644 --- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java +++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java -@@ -136,7 +136,7 @@ public final class NearbyPlayers { +@@ -127,7 +127,7 @@ public final class NearbyPlayers { } public TrackedChunk getChunk(final ChunkPos pos) { @@ -21,7 +21,7 @@ index 2a2626e90836ae52a8a686b2040843c6644b6914..283e02b32cae0bc1b0cd71602795aa48 } public TrackedChunk getChunk(final BlockPos pos) { -@@ -152,7 +152,7 @@ public final class NearbyPlayers { +@@ -143,7 +143,7 @@ public final class NearbyPlayers { } public ReferenceList getPlayers(final ChunkPos pos, final NearbyMapType type) { diff --git a/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/TrackerCtx.java b/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/TrackerCtx.java index abe3b78b..5689740d 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/TrackerCtx.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/TrackerCtx.java @@ -1,6 +1,7 @@ package org.dreeam.leaf.async.tracker; -import ca.spottedleaf.moonrise.common.misc.NearbyPlayers; +import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity; +import ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity; import io.papermc.paper.event.player.PlayerTrackEntityEvent; import io.papermc.paper.event.player.PlayerUntrackEntityEvent; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -119,31 +120,34 @@ public final class TrackerCtx { } void handle(boolean flush) { - handlePackets(world, packets, flush); - if (!pluginEntity.isEmpty()) { for (final Entity entity : pluginEntity) { - final ChunkMap.TrackedEntity tracker = ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity(); + final ChunkMap.TrackedEntity tracker = ((EntityTrackerEntity) entity).moonrise$getTrackedEntity(); if (tracker == null) { continue; } - NearbyPlayers.TrackedChunk trackedChunk = world.moonrise$getNearbyPlayers().getChunk(entity.chunkPosition()); - tracker.leafTick(this, trackedChunk); + ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData chunk = ((ChunkSystemEntity) entity).moonrise$getChunkData(); + if (chunk == null) { + continue; + } + tracker.moonrise$tick(chunk.nearbyPlayers); boolean flag = false; if (tracker.moonrise$hasPlayers()) { flag = true; } else { - FullChunkStatus status = ((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity) entity).moonrise$getChunkStatus(); + FullChunkStatus status = ((ChunkSystemEntity) entity).moonrise$getChunkStatus(); if (status != null && status.isOrAfter(FullChunkStatus.ENTITY_TICKING)) { flag = true; } } if (flag) { - tracker.serverEntity.leafSendChanges(this, tracker); + tracker.serverEntity.sendChanges(); } } pluginEntity.clear(); } + + handlePackets(world, packets, flush); if (!bukkitVelocityEvent.isEmpty()) { for (ServerPlayer player : bukkitVelocityEvent) { if (!world.equals(player.level())) { diff --git a/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/TrackerTask.java b/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/TrackerTask.java index 3c698e96..4ec2ff4f 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/TrackerTask.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/TrackerTask.java @@ -1,36 +1,26 @@ package org.dreeam.leaf.async.tracker; -import ca.spottedleaf.moonrise.common.misc.NearbyPlayers; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity; +import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData; +import ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.ChunkPos; import org.dreeam.leaf.util.EntitySlice; import java.util.concurrent.Callable; -public final class TrackerTask implements Callable { - public final ServerLevel world; - private final EntitySlice entities; - - public TrackerTask(ServerLevel world, EntitySlice trackerEntities) { - this.world = world; - this.entities = trackerEntities; - } +public record TrackerTask(ServerLevel world, EntitySlice entities) implements Callable { @Override public TrackerCtx call() throws Exception { - NearbyPlayers nearbyPlayers = world.moonrise$getNearbyPlayers(); - TrackerCtx ctx = new TrackerCtx(this.world); + final TrackerCtx ctx = new TrackerCtx(this.world); final Entity[] raw = entities.array(); - Long2ObjectMap chunkCache = new Long2ObjectOpenHashMap<>(); for (int i = entities.start(); i < entities.end(); i++) { final Entity entity = raw[i]; - final ChunkMap.TrackedEntity tracker = ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity(); - long chunkPos = entity.chunkPosition().toLong(); + final ChunkMap.TrackedEntity tracker = ((EntityTrackerEntity) entity).moonrise$getTrackedEntity(); + // removed in world if null if (tracker == null) { continue; } @@ -38,16 +28,18 @@ public final class TrackerTask implements Callable { ctx.citizensEntity(entity); continue; } - NearbyPlayers.TrackedChunk trackedChunk = chunkCache.computeIfAbsent(chunkPos, k -> nearbyPlayers.getChunk(ChunkPos.getX(k), ChunkPos.getZ(k))); - - tracker.leafTick(ctx, trackedChunk); + ChunkData chunkData = ((ChunkSystemEntity) entity).moonrise$getChunkData(); + // removed in world if null + if (chunkData == null) { + continue; + } + tracker.leafTick(ctx, chunkData.nearbyPlayers); boolean flag = false; if (tracker.moonrise$hasPlayers()) { flag = true; } else { - // may read old value - FullChunkStatus status = ((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity) entity).moonrise$getChunkStatus(); - // removed in world + FullChunkStatus status = ((ChunkSystemEntity) entity).moonrise$getChunkStatus(); + // removed in world if null if (status != null && status.isOrAfter(FullChunkStatus.ENTITY_TICKING)) { flag = true; }