fix: fix global entity count max limit problem
This commit is contained in:
@@ -5,29 +5,72 @@ Subject: [PATCH] Global Entities Counter
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
index 3b39b8f7ccb278cf910e3cc4e00da29790465a81..8a985f9b1fed90e167d625815eb5fa6586a00972 100644
|
||||
index 3b39b8f7ccb278cf910e3cc4e00da29790465a81..7cc41630a39c1e29840d70eee78473d06b7c11cd 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
@@ -529,6 +529,8 @@ public final class RegionizedWorldData {
|
||||
@@ -520,6 +520,9 @@ public final class RegionizedWorldData {
|
||||
public final Map<Long, ChunkSectionItemEntityMovementTracker> itemEntityMovementTrackerMap = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>();
|
||||
// Luminol end
|
||||
|
||||
+ public int uniqueId = -1; // Lophine - Global Entities Counter
|
||||
+ public boolean underGlobalEntitiesCounter = false; // Lophine - Global Entities Counter
|
||||
+
|
||||
public RegionizedWorldData(final ServerLevel world) {
|
||||
this.world = world;
|
||||
this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true);
|
||||
@@ -529,6 +532,15 @@ public final class RegionizedWorldData {
|
||||
this.wireHandler = new alternate.current.wire.WireHandler(world);
|
||||
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
|
||||
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.addDataToLoaded(loadedEntities, world); // Lophine - Global Entities Counter
|
||||
+ // Lophine start - Global Entities Counter
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ uniqueId = fun.bm.lophine.utils.EntitiesCounterUtil.generateUniqueId();
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.reportAreaMap(world, spawnChunkTracker, uniqueId);
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.addDataToLoaded(world, loadedEntities, uniqueId);
|
||||
+ underGlobalEntitiesCounter = true;
|
||||
+ }
|
||||
+ // Lophine end - Global Entities Counter
|
||||
+
|
||||
// tasks may be drained before the region ticks, so we must set up the tick data early just in case
|
||||
this.updateTickData();
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 05bad0366bd36b8134290a0cceb4d4dfcbbd0544..446dc2e3db99fe7f081b8d3df48ba8a9778ae379 100644
|
||||
index 05bad0366bd36b8134290a0cceb4d4dfcbbd0544..604681c8fda696dcc824b1b36b53c0d8434ec5c2 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -580,7 +580,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -516,6 +516,25 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
this.chunkMap.tick(hasTimeLeft);
|
||||
profilerFiller.pop();
|
||||
this.clearCache();
|
||||
+ // Lophine start - Global Entities Counter
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData();
|
||||
+ if (regionizedWorldData != null) {
|
||||
+ if (regionizedWorldData.underGlobalEntitiesCounter) {
|
||||
+ if (regionizedWorldData.getLocalPlayers().isEmpty()) {
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.onWorldDataUnload(level, regionizedWorldData.uniqueId);
|
||||
+ regionizedWorldData.underGlobalEntitiesCounter = false;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (!regionizedWorldData.getLocalPlayers().isEmpty()) {
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.reportAreaMap(level, regionizedWorldData.spawnChunkTracker, regionizedWorldData.uniqueId);
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.addDataToLoaded(level, (ca.spottedleaf.moonrise.common.list.ReferenceList<Entity>) regionizedWorldData.getLoadedEntities(), regionizedWorldData.uniqueId);
|
||||
+ regionizedWorldData.underGlobalEntitiesCounter = true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Lophine end - Global Entities Counter
|
||||
}
|
||||
|
||||
private void tickChunks() {
|
||||
@@ -580,7 +599,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, null, true); // Folia - region threading - note: function only cares about loaded entities, doesn't need all
|
||||
} else {
|
||||
+ // Lophine start - Global Entities Counter
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ spawnState = fun.bm.lophine.utils.EntitiesCounterUtil.runRemainingTasks(level, naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
||||
+ spawnState = fun.bm.lophine.utils.EntitiesCounterUtil.runRemainingTasks(level, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
||||
+ } else {
|
||||
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all
|
||||
+ }
|
||||
@@ -35,7 +78,7 @@ index 05bad0366bd36b8134290a0cceb4d4dfcbbd0544..446dc2e3db99fe7f081b8d3df48ba8a9
|
||||
}
|
||||
} finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MOB_SPAWN_ENTITY_COUNT); } // Folia - profiler
|
||||
// Paper end - Optional per player mob spawns
|
||||
@@ -589,7 +595,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -589,7 +614,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.getLocalPlayers().isEmpty(); // CraftBukkit // Folia - region threading
|
||||
int _int = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
|
||||
List<MobCategory> filteredSpawningCategories;
|
||||
@@ -44,7 +87,7 @@ index 05bad0366bd36b8134290a0cceb4d4dfcbbd0544..446dc2e3db99fe7f081b8d3df48ba8a9
|
||||
// Paper start - PlayerNaturallySpawnCreaturesEvent
|
||||
for (ServerPlayer entityPlayer : this.level.getLocalPlayers()) { // Folia - region threading
|
||||
int chunkRange = Math.min(level.spigotConfig.mobSpawnRange, entityPlayer.getBukkitEntity().getViewDistance());
|
||||
@@ -646,7 +652,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -646,7 +671,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
this.level.tickThunder(chunk);
|
||||
}
|
||||
|
||||
@@ -54,7 +97,7 @@ index 05bad0366bd36b8134290a0cceb4d4dfcbbd0544..446dc2e3db99fe7f081b8d3df48ba8a9
|
||||
NaturalSpawner.spawnForChunk(this.level, chunk, spawnState, spawnCategories);
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index c0ba36849da0983117901f0cd04b2c785df0010b..a51ae9326907c8a1ecdbc3112ca6d76520791678 100644
|
||||
index c0ba36849da0983117901f0cd04b2c785df0010b..0b0d9322632ef1a751add633bdcb87ec84f82704 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -729,6 +729,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -63,7 +106,7 @@ index c0ba36849da0983117901f0cd04b2c785df0010b..a51ae9326907c8a1ecdbc3112ca6d765
|
||||
public void tick(BooleanSupplier hasTimeLeft, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - regionised ticking
|
||||
+ // Lophine start - Global Entities Counter
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.tick(this);
|
||||
+ if (fun.bm.lophine.utils.EntitiesCounterUtil.canRunNewTask(this)) fun.bm.lophine.utils.EntitiesCounterUtil.tick(this);
|
||||
+ }
|
||||
+ // Lophine end - Global Entities Counter
|
||||
final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.getCurrentWorldData(); // Folia - regionised ticking
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package fun.bm.lophine.utils;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||
import ca.spottedleaf.moonrise.common.misc.PositionCountingAreaMap;
|
||||
import fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
@@ -13,32 +15,61 @@ import net.minecraft.world.level.LocalMobCapCalculator;
|
||||
import net.minecraft.world.level.NaturalSpawner;
|
||||
import net.minecraft.world.level.PotentialCalculator;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings;
|
||||
import org.bukkit.craftbukkit.util.WeakCollection;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static net.minecraft.world.level.NaturalSpawner.getRoughBiome;
|
||||
|
||||
public class EntitiesCounterUtil {
|
||||
private static final WeakHashMap<ServerLevel, WeakCollection<ReferenceList<Entity>>> globalLoadedEntities = new WeakHashMap<>();
|
||||
private static final WeakHashMap<ServerLevel, WeakHashMap<Integer, ReferenceList<Entity>>> globalLoadedEntities = new WeakHashMap<>();
|
||||
private static final WeakHashMap<ServerLevel, Object2IntOpenHashMap<MobCategory>> mobsMap = new WeakHashMap<>();
|
||||
private static final WeakHashMap<ServerLevel, WeakHashMap<Thread, ChunkCounter>> fullSpawnableChunkCount = new WeakHashMap<>();
|
||||
private static final WeakHashMap<ServerLevel, WeakHashMap<Integer, PositionCountingAreaMap<ServerPlayer>>> mobsAreaMap = new WeakHashMap<>();
|
||||
private static final WeakHashMap<ServerLevel, Integer> spawnableChunkCount = new WeakHashMap<>();
|
||||
private static final WeakHashMap<ServerLevel, CompletableFuture<Void>> tasks = new WeakHashMap<>();
|
||||
private static final Set<Integer> UniqueIds = new HashSet<>();
|
||||
|
||||
public static void addDataToLoaded(ReferenceList<Entity> data, ServerLevel level) {
|
||||
WeakCollection<ReferenceList<Entity>> data0 = globalLoadedEntities.computeIfAbsent(level, k -> new WeakCollection<>());
|
||||
data0.add(data);
|
||||
private static int lastUsedId = 0;
|
||||
|
||||
public static int generateUniqueId() {
|
||||
synchronized (UniqueIds) {
|
||||
int id = lastUsedId;
|
||||
while (UniqueIds.contains(id)) {
|
||||
id++;
|
||||
}
|
||||
|
||||
lastUsedId = id;
|
||||
UniqueIds.add(id);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
public static void reportChunkCount(int count, ServerLevel level) {
|
||||
Map<Thread, ChunkCounter> counter = fullSpawnableChunkCount.computeIfAbsent(level, k -> new WeakHashMap<>());
|
||||
counter.put(Thread.currentThread(), new ChunkCounter(count));
|
||||
public static void onWorldDataUnload(ServerLevel level, int uniqueId) {
|
||||
synchronized (UniqueIds) {
|
||||
UniqueIds.remove(uniqueId);
|
||||
}
|
||||
synchronized (globalLoadedEntities) {
|
||||
globalLoadedEntities.get(level).remove(uniqueId);
|
||||
}
|
||||
synchronized (mobsMap) {
|
||||
mobsAreaMap.get(level).remove(uniqueId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addDataToLoaded(ServerLevel level, ReferenceList<Entity> data, int uniqueId) {
|
||||
WeakHashMap<Integer, ReferenceList<Entity>> data0 = globalLoadedEntities.computeIfAbsent(level, k -> new WeakHashMap<>());
|
||||
if (data0.containsKey(uniqueId)) return;
|
||||
data0.put(uniqueId, data);
|
||||
}
|
||||
|
||||
public static void reportAreaMap(ServerLevel level, PositionCountingAreaMap<ServerPlayer> areaMap, int uniqueId) {
|
||||
WeakHashMap<Integer, PositionCountingAreaMap<ServerPlayer>> areaMap0 = mobsAreaMap.computeIfAbsent(level, k -> new WeakHashMap<>());
|
||||
if (areaMap0.containsKey(uniqueId)) return;
|
||||
areaMap0.put(uniqueId, areaMap);
|
||||
}
|
||||
|
||||
public static int getTotalChunkCount(ServerLevel level) {
|
||||
@@ -56,9 +87,9 @@ public class EntitiesCounterUtil {
|
||||
|
||||
public static void tick(ServerLevel level) {
|
||||
Runnable task = () -> {
|
||||
WeakCollection<ReferenceList<Entity>> data0 = globalLoadedEntities.get(level);
|
||||
WeakHashMap<Integer, ReferenceList<Entity>> data0 = globalLoadedEntities.get(level);
|
||||
Object2IntOpenHashMap<MobCategory> map = new Object2IntOpenHashMap<>();
|
||||
for (ReferenceList<Entity> data : data0) {
|
||||
for (ReferenceList<Entity> data : data0.values()) {
|
||||
for (Entity entity : GlobalEntitiesCounter.enabled ? data.copy() : data) {
|
||||
// Lophine start - Copy from net/minecraft/world/level/NaturalSpawner
|
||||
MobCategory category = entity.getType().getCategory();
|
||||
@@ -76,24 +107,14 @@ public class EntitiesCounterUtil {
|
||||
}
|
||||
}
|
||||
mobsMap.put(level, map);
|
||||
|
||||
synchronized (fullSpawnableChunkCount) {
|
||||
for (ServerLevel world : fullSpawnableChunkCount.keySet()) {
|
||||
int count = 0;
|
||||
Map<Thread, ChunkCounter> map0 = fullSpawnableChunkCount.get(level);
|
||||
if (map0 == null) continue;
|
||||
Map<Thread, ChunkCounter> map1 = Map.copyOf(map0);
|
||||
for (Thread thread : map1.keySet()) {
|
||||
ChunkCounter counter = map1.get(thread);
|
||||
counter.tick();
|
||||
if (counter.timeout()) {
|
||||
fullSpawnableChunkCount.get(world).remove(thread);
|
||||
} else {
|
||||
count += counter.getChunkCount();
|
||||
}
|
||||
}
|
||||
spawnableChunkCount.put(level, count);
|
||||
for (ServerLevel world : mobsAreaMap.keySet()) {
|
||||
int count = 0;
|
||||
WeakHashMap<Integer, PositionCountingAreaMap<ServerPlayer>> collection = mobsAreaMap.get(level);
|
||||
if (collection == null) continue;
|
||||
for (PositionCountingAreaMap<ServerPlayer> areaMap : collection.values()) {
|
||||
count += areaMap.getTotalPositions();
|
||||
}
|
||||
spawnableChunkCount.put(world, count);
|
||||
}
|
||||
};
|
||||
if (GlobalEntitiesCounter.async) {
|
||||
@@ -104,9 +125,8 @@ public class EntitiesCounterUtil {
|
||||
}
|
||||
|
||||
public static NaturalSpawner.SpawnState runRemainingTasks(
|
||||
ServerLevel level, int newSpawnableChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator, final boolean countMobs
|
||||
ServerLevel level, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator, final boolean countMobs
|
||||
) {
|
||||
reportChunkCount(newSpawnableChunkCount, level);
|
||||
Object2IntOpenHashMap<MobCategory> map = getMobsMap(level);
|
||||
if (map == null) return null; // skip if no data
|
||||
// Lophine start - Copy from net/minecraft/world/level/NaturalSpawner
|
||||
|
||||
Reference in New Issue
Block a user