diff --git a/lophine-server/src/main/java/fun/bm/lophine/utils/EntitiesCounterUtil.java b/lophine-server/src/main/java/fun/bm/lophine/utils/EntitiesCounterUtil.java index ad751c4..5cb145d 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/utils/EntitiesCounterUtil.java +++ b/lophine-server/src/main/java/fun/bm/lophine/utils/EntitiesCounterUtil.java @@ -4,6 +4,7 @@ import ca.spottedleaf.moonrise.common.list.ReferenceList; import ca.spottedleaf.moonrise.common.misc.PositionCountingAreaMap; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.mojang.logging.LogUtils; import fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.minecraft.core.BlockPos; @@ -28,7 +29,7 @@ import static net.minecraft.world.level.NaturalSpawner.getRoughBiome; public class EntitiesCounterUtil { private static final Map>> globalLoadedEntities = new ConcurrentHashMap<>(); - private static final Map> mobsMap = new WeakHashMap<>(); + private static final Map> mobsMap = Collections.synchronizedMap(new WeakHashMap<>()); private static final Map>> mobsAreaMap = new ConcurrentHashMap<>(); private static final Map spawnableChunkCount = new ConcurrentHashMap<>(); private static final Map> tasks = new ConcurrentHashMap<>(); @@ -54,8 +55,15 @@ public class EntitiesCounterUtil { public static void onWorldDataUnload(ServerLevel level, int uniqueId) { UniqueIds.remove(uniqueId); - globalLoadedEntities.get(level).invalidate(uniqueId); - mobsAreaMap.get(level).invalidate(uniqueId); + Cache> entitiesCache = globalLoadedEntities.get(level); + if (entitiesCache != null) { + entitiesCache.invalidate(uniqueId); + } + + Cache> areaCache = mobsAreaMap.get(level); + if (areaCache != null) { + areaCache.invalidate(uniqueId); + } } private static void runCleanUp() { @@ -97,41 +105,53 @@ public class EntitiesCounterUtil { public static void tick(ServerLevel level) { Runnable task = () -> { - Cache> data0 = globalLoadedEntities.get(level); - Object2IntOpenHashMap map = new Object2IntOpenHashMap<>(); - Collection> snapshot = data0.asMap().values(); + try { + Cache> data0 = globalLoadedEntities.get(level); + if (data0 == null) return; - for (ReferenceList data : snapshot) { - for (Entity entity : GlobalEntitiesCounter.async ? data.copy() : data) { - if (entity == null || entity.isRemoved() || !entity.isAlive()) continue; - // Lophine start - Copy from net/minecraft/world/level/NaturalSpawner - MobCategory category = entity.getType().getCategory(); - if (category != MobCategory.MISC) { - // Paper start - Only count natural spawns - if (!entity.level().paperConfig().entities.spawning.countAllMobsForSpawning && - !(entity.spawnReason == CreatureSpawnEvent.SpawnReason.NATURAL || - entity.spawnReason == CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { - continue; + Object2IntOpenHashMap map = new Object2IntOpenHashMap<>(); + Collection> snapshot = data0.asMap().values(); + + for (ReferenceList data : snapshot) { + if (data == null) continue; + for (Entity entity : GlobalEntitiesCounter.async ? data.copy() : data) { + if (entity == null || entity.isRemoved() || !entity.isAlive()) continue; + // Lophine start - Copy from net/minecraft/world/level/NaturalSpawner + MobCategory category = entity.getType().getCategory(); + if (category != MobCategory.MISC) { + // Paper start - Only count natural spawns + if (!entity.level().paperConfig().entities.spawning.countAllMobsForSpawning && + !(entity.spawnReason == CreatureSpawnEvent.SpawnReason.NATURAL || + entity.spawnReason == CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { + continue; + } + // Paper end - Only count natural spawns + map.addTo(category, 1); } - // Paper end - Only count natural spawns - map.addTo(category, 1); } // Lophine end - Copy from net/minecraft/world/level/NaturalSpawner } - } - mobsMap.put(level, map); - for (ServerLevel world : mobsAreaMap.keySet()) { - int count = 0; + mobsMap.put(level, map); + Cache> collection = mobsAreaMap.get(level); - if (collection == null) continue; - for (PositionCountingAreaMap areaMap : collection.asMap().values()) { - count += areaMap.getTotalPositions(); + if (collection != null) { + int count = 0; + for (PositionCountingAreaMap areaMap : collection.asMap().values()) { + if (areaMap != null) { + count += areaMap.getTotalPositions(); + } + } + spawnableChunkCount.put(level, count); } - spawnableChunkCount.put(world, count); + } catch (Exception e) { + LogUtils.getClassLogger().error("Failed to run task", e); } }; if (GlobalEntitiesCounter.async) { - tasks.put(level, CompletableFuture.runAsync(task)); + tasks.put(level, CompletableFuture.runAsync(task).exceptionally(ex -> { + LogUtils.getClassLogger().error("Failed to run task", ex); + return null; + })); } else { task.run(); }