mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-30 20:39:21 +00:00
fix async mob spawning TRACKED entities not count (#393)
* fix unloaded and TRACKED entities not count #392 * move to archived
This commit is contained in:
@@ -14,7 +14,7 @@ Generally faster than the non-async approach
|
||||
iterate over all entities, get their chunk, and increment the count
|
||||
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index 79674f4bd7a12c42dec19a4175012d7a2dc88b84..0a97a491737807d59815b75635fa3d8c94901ba8 100644
|
||||
index a640cb4d767c6c81ad27bbf0dd8027a80a2fc224..f4d4f39540a25d6772c8078d0ff01af04d90c8e7 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -287,6 +287,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -26,7 +26,7 @@ index 79674f4bd7a12c42dec19a4175012d7a2dc88b84..0a97a491737807d59815b75635fa3d8c
|
||||
}
|
||||
// Paper end - Optional per player mob spawns
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 46e171ca454253c32e22c0c18587e9a7ba19f331..1c7e2e5124c7d4c1b86039b0327bfd92c49df9b1 100644
|
||||
index 46e171ca454253c32e22c0c18587e9a7ba19f331..43156ecde8bb86c77f3b13c17b3330eae95efcc3 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -70,11 +70,11 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -78,7 +78,7 @@ index 46e171ca454253c32e22c0c18587e9a7ba19f331..1c7e2e5124c7d4c1b86039b0327bfd92
|
||||
// Paper start - per player mob spawning backoff
|
||||
for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
|
||||
player.mobCounts[ii] = 0;
|
||||
@@ -524,14 +541,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -524,34 +541,27 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
player.mobBackoffCounts[ii] = newBackoff;
|
||||
}
|
||||
// Paper end - per player mob spawning backoff
|
||||
@@ -89,26 +89,46 @@ index 46e171ca454253c32e22c0c18587e9a7ba19f331..1c7e2e5124c7d4c1b86039b0327bfd92
|
||||
_pufferfish_spawnCountsReady.set(true);
|
||||
}
|
||||
if (_pufferfish_spawnCountsReady.getAndSet(false)) {
|
||||
+ int mapped = distanceManager.getNaturalSpawnChunkCount();
|
||||
+ final int mapped = distanceManager.getNaturalSpawnChunkCount();
|
||||
+ final Iterable<Entity> entities = this.level.getAllEntities();
|
||||
net.minecraft.server.MinecraftServer.getServer().mobSpawnExecutor.submit(() -> {
|
||||
- int mapped = distanceManager.getNaturalSpawnChunkCount();
|
||||
ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.Iterator<Entity> objectiterator =
|
||||
level.entityTickList.entities.iterator(ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS);
|
||||
try {
|
||||
@@ -542,10 +559,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
new LocalMobCapCalculator(chunkMap) : null;
|
||||
|
||||
// This ensures the caps are properly enforced by using the correct calculator
|
||||
- ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.Iterator<Entity> objectiterator =
|
||||
- level.entityTickList.entities.iterator(ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS);
|
||||
- try {
|
||||
- gg.pufferfish.pufferfish.util.IterableWrapper<Entity> wrappedIterator =
|
||||
- new gg.pufferfish.pufferfish.util.IterableWrapper<>(objectiterator);
|
||||
- // Fix: Use proper mob cap calculator based on configuration
|
||||
- LocalMobCapCalculator mobCapCalculator = !level.paperConfig().entities.spawning.perPlayerMobSpawns ?
|
||||
- new LocalMobCapCalculator(chunkMap) : null;
|
||||
-
|
||||
- // This ensures the caps are properly enforced by using the correct calculator
|
||||
- lastSpawnState = NaturalSpawner.createState(
|
||||
+ lastSpawnState = NaturalSpawner.createState1( // Leaf - optimize mob spawning
|
||||
mapped,
|
||||
wrappedIterator,
|
||||
- mapped,
|
||||
- wrappedIterator,
|
||||
- ServerChunkCache.this::getFullChunk,
|
||||
+ this.level, // Leaf - optimize mob spawning
|
||||
mobCapCalculator, // This is the key fix - was previously null
|
||||
level.paperConfig().entities.spawning.perPlayerMobSpawns
|
||||
);
|
||||
@@ -610,6 +627,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
- mobCapCalculator, // This is the key fix - was previously null
|
||||
- level.paperConfig().entities.spawning.perPlayerMobSpawns
|
||||
- );
|
||||
- } finally {
|
||||
- objectiterator.finishedIterating();
|
||||
- }
|
||||
+ // Fix: Use proper mob cap calculator based on configuration
|
||||
+ LocalMobCapCalculator mobCapCalculator = !level.paperConfig().entities.spawning.perPlayerMobSpawns ?
|
||||
+ new LocalMobCapCalculator(chunkMap) : null;
|
||||
+
|
||||
+ // This ensures the caps are properly enforced by using the correct calculator
|
||||
+ lastSpawnState = NaturalSpawner.createState1( // Leaf - optimize mob spawning
|
||||
+ mapped,
|
||||
+ entities,
|
||||
+ this.level, // Leaf - optimize mob spawning
|
||||
+ mobCapCalculator, // This is the key fix - was previously null
|
||||
+ level.paperConfig().entities.spawning.perPlayerMobSpawns
|
||||
+ );
|
||||
_pufferfish_spawnCountsReady.set(true);
|
||||
});
|
||||
}
|
||||
@@ -610,6 +620,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
chunkRange = Math.min(chunkRange, 8);
|
||||
entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange);
|
||||
entityPlayer.playerNaturallySpawnedEvent.callEvent();
|
||||
@@ -116,7 +136,7 @@ index 46e171ca454253c32e22c0c18587e9a7ba19f331..1c7e2e5124c7d4c1b86039b0327bfd92
|
||||
}
|
||||
// Paper end - PlayerNaturallySpawnCreaturesEvent
|
||||
boolean flag = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
|
||||
@@ -621,16 +639,40 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -621,16 +632,40 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
List<LevelChunk> list = this.spawningChunks;
|
||||
|
||||
try {
|
||||
@@ -162,7 +182,7 @@ index 46e171ca454253c32e22c0c18587e9a7ba19f331..1c7e2e5124c7d4c1b86039b0327bfd92
|
||||
list.clear();
|
||||
}
|
||||
|
||||
@@ -648,7 +690,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -648,7 +683,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
|
||||
if (!spawnCategories.isEmpty()) {
|
||||
@@ -184,7 +204,7 @@ index 02c2b9c1978959e1ee0be5c72a5f7b98aa282fc2..4ec5142e233c87d2bb1ebe883cf10a5a
|
||||
final net.minecraft.world.level.levelgen.BitRandomSource simpleRandom = this.simpleRandom; // Paper - optimise random ticking // Leaf - Faster random generator - upcasting
|
||||
ChunkPos pos = chunk.getPos();
|
||||
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a47c8bc6c8 100644
|
||||
index 81e176d17fb072f9ee531639abfe42134ae833a9..c3284577437412e1c3fb891bee2b0e20b52ccd59 100644
|
||||
--- a/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -68,6 +68,7 @@ public final class NaturalSpawner {
|
||||
@@ -195,7 +215,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
public static NaturalSpawner.SpawnState createState(
|
||||
int spawnableChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator, final boolean countMobs
|
||||
) {
|
||||
@@ -108,9 +109,69 @@ public final class NaturalSpawner {
|
||||
@@ -108,9 +109,71 @@ public final class NaturalSpawner {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,20 +245,21 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
+ // Paper end - Only count natural spawns
|
||||
+ BlockPos blockPos = entity.blockPosition();
|
||||
+ LevelChunk chunk = level.chunkSource.fullChunks.get(ChunkPos.asLong(blockPos));
|
||||
+ MobSpawnSettings.MobSpawnCost mobSpawnCost = getRoughBiome(blockPos, chunk).getMobSettings().getMobSpawnCost(entity.getType());
|
||||
+ if (mobSpawnCost != null) {
|
||||
+ potentialCalculator.addCharge(entity.blockPosition(), mobSpawnCost.charge());
|
||||
+ }
|
||||
+ if (chunk != null) {
|
||||
+ MobSpawnSettings.MobSpawnCost mobSpawnCost = getRoughBiome(blockPos, chunk).getMobSettings().getMobSpawnCost(entity.getType());
|
||||
+ if (mobSpawnCost != null) {
|
||||
+ potentialCalculator.addCharge(entity.blockPosition(), mobSpawnCost.charge());
|
||||
+ }
|
||||
+
|
||||
+ if (calculator != null && entity instanceof Mob) { // Paper - Optional per player mob spawns
|
||||
+ calculator.addMob(chunk.getPos(), category);
|
||||
+ }
|
||||
+ if (calculator != null && entity instanceof Mob) { // Paper - Optional per player mob spawns
|
||||
+ calculator.addMob(chunk.getPos(), category);
|
||||
+ }
|
||||
+
|
||||
+ map.addTo(category, 1);
|
||||
+ // Paper start - Optional per player mob spawns
|
||||
+ if (countMobs) {
|
||||
+ final int index = entity.getType().getCategory().ordinal();
|
||||
+ ++chunkCap.computeIfAbsent(chunk.getPos().longKey, k -> new int[net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS])[index];
|
||||
+ map.addTo(category, 1);
|
||||
+ // Paper start - Optional per player mob spawns
|
||||
+ if (countMobs) {
|
||||
+ final int index = entity.getType().getCategory().ordinal();
|
||||
+ ++chunkCap.computeIfAbsent(chunk.getPos().longKey, k -> new int[net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS])[index];
|
||||
+ /*
|
||||
+ final int index = entity.getType().getCategory().ordinal();
|
||||
+ final var inRange = level.moonrise$getNearbyPlayers().getPlayers(entity.chunkPosition(), NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
|
||||
@@ -253,8 +274,9 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
+ ++playerCap.computeIfAbsent(player, k -> new int[net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS])[index];
|
||||
+ }
|
||||
+ */
|
||||
+ }
|
||||
+ // Paper end - Optional per player mob spawns
|
||||
+ }
|
||||
+ // Paper end - Optional per player mob spawns
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@@ -266,7 +288,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) {
|
||||
return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value();
|
||||
}
|
||||
@@ -265,28 +326,68 @@ public final class NaturalSpawner {
|
||||
@@ -265,28 +328,68 @@ public final class NaturalSpawner {
|
||||
MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity, final boolean nothing
|
||||
// Paper end - throttle failed spawn attempts
|
||||
) {
|
||||
@@ -342,7 +364,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
mutableBlockPos.set(x, y, z);
|
||||
double d = x + 0.5;
|
||||
double d1 = z + 0.5;
|
||||
@@ -295,8 +396,8 @@ public final class NaturalSpawner {
|
||||
@@ -295,8 +398,8 @@ public final class NaturalSpawner {
|
||||
double d2 = nearestPlayer.distanceToSqr(d, y, d1);
|
||||
if (level.isLoadedAndInBounds(mutableBlockPos) && isRightDistanceToPlayerAndSpawnPoint(level, chunk, mutableBlockPos, d2)) { // Paper - don't load chunks for mob spawn
|
||||
if (spawnerData == null) {
|
||||
@@ -353,7 +375,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
);
|
||||
if (randomSpawnMobAt.isEmpty()) {
|
||||
break;
|
||||
@@ -307,7 +408,7 @@ public final class NaturalSpawner {
|
||||
@@ -307,7 +410,7 @@ public final class NaturalSpawner {
|
||||
}
|
||||
|
||||
// Paper start - PreCreatureSpawnEvent
|
||||
@@ -362,7 +384,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
// Paper start - per player mob count backoff
|
||||
if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) {
|
||||
level.getChunkSource().chunkMap.updateFailurePlayerMobTypeMap(mutableBlockPos.getX() >> 4, mutableBlockPos.getZ() >> 4, category);
|
||||
@@ -414,6 +515,44 @@ public final class NaturalSpawner {
|
||||
@@ -414,6 +517,44 @@ public final class NaturalSpawner {
|
||||
&& level.noCollision(entityType.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5));
|
||||
return success ? PreSpawnStatus.SUCCESS : PreSpawnStatus.FAIL; // Paper - PreCreatureSpawnEvent
|
||||
}
|
||||
@@ -407,7 +429,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
|
||||
@Nullable
|
||||
private static Mob getMobForSpawn(ServerLevel level, EntityType<?> entityType) {
|
||||
@@ -449,6 +588,17 @@ public final class NaturalSpawner {
|
||||
@@ -449,6 +590,17 @@ public final class NaturalSpawner {
|
||||
: mobsAt(level, structureManager, generator, category, pos, biome).getRandom(random);
|
||||
}
|
||||
|
||||
@@ -425,7 +447,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
private static boolean canSpawnMobAt(
|
||||
ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, MobSpawnSettings.SpawnerData data, BlockPos pos
|
||||
) {
|
||||
@@ -463,6 +613,16 @@ public final class NaturalSpawner {
|
||||
@@ -463,6 +615,16 @@ public final class NaturalSpawner {
|
||||
: generator.getMobsAt(biome != null ? biome : (org.dreeam.leaf.config.modules.opt.OptimizeBiome.mobSpawn ? level.getBiomeCached(null, pos) : level.getBiome(pos)), structureManager, cetagory, pos); // Leaf - cache getBiome
|
||||
}
|
||||
|
||||
@@ -442,7 +464,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
public static boolean isInNetherFortressBounds(BlockPos pos, ServerLevel level, MobCategory category, StructureManager structureManager) {
|
||||
if (category == MobCategory.MONSTER && level.getBlockState(pos.below()).is(Blocks.NETHER_BRICKS)) {
|
||||
Structure structure = structureManager.registryAccess().lookupOrThrow(Registries.STRUCTURE).getValue(BuiltinStructures.FORTRESS);
|
||||
@@ -472,6 +632,17 @@ public final class NaturalSpawner {
|
||||
@@ -472,6 +634,17 @@ public final class NaturalSpawner {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +482,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
private static BlockPos getRandomPosWithin(Level level, LevelChunk chunk) {
|
||||
ChunkPos pos = chunk.getPos();
|
||||
int i = pos.getMinBlockX() + level.random.nextInt(16);
|
||||
@@ -612,18 +783,21 @@ public final class NaturalSpawner {
|
||||
@@ -612,18 +785,21 @@ public final class NaturalSpawner {
|
||||
@Nullable
|
||||
private EntityType<?> lastCheckedType;
|
||||
private double lastCharge;
|
||||
@@ -483,7 +505,7 @@ index 81e176d17fb072f9ee531639abfe42134ae833a9..1052353f3a1ed52ac51cb0bb12f9e6a4
|
||||
}
|
||||
|
||||
private boolean canSpawn(EntityType<?> entityType, BlockPos pos, ChunkAccess chunk) {
|
||||
@@ -680,5 +854,32 @@ public final class NaturalSpawner {
|
||||
@@ -680,5 +856,32 @@ public final class NaturalSpawner {
|
||||
boolean canSpawnForCategoryLocal(MobCategory category, ChunkPos chunkPos) {
|
||||
return this.localMobCapCalculator.canSpawn(category, chunkPos);
|
||||
}
|
||||
@@ -594,3 +616,16 @@ index 11c7c299d4affb9e78488590e7db939efe6e3dd9..a89c61aac1f1a35dc8c5943c0002661c
|
||||
public void createStructures(
|
||||
RegistryAccess registryAccess,
|
||||
ChunkGeneratorStructureState structureState,
|
||||
diff --git a/net/minecraft/world/level/entity/EntityTickList.java b/net/minecraft/world/level/entity/EntityTickList.java
|
||||
index 5a90b3bffeeb08a168b370e49d18c5f8b257a980..ba173bc1751c495e6fa497566b5ed3c7a9547364 100644
|
||||
--- a/net/minecraft/world/level/entity/EntityTickList.java
|
||||
+++ b/net/minecraft/world/level/entity/EntityTickList.java
|
||||
@@ -9,7 +9,7 @@ import javax.annotation.Nullable;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
public class EntityTickList {
|
||||
- public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<net.minecraft.world.entity.Entity> entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled); // Paper - rewrite chunk system // Pufferfish - private->public and do thread check
|
||||
+ private final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<net.minecraft.world.entity.Entity> entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system
|
||||
|
||||
// Leaf start - SparklyPaper - parallel world ticking mod
|
||||
// preserve original constructor
|
||||
|
||||
@@ -5,10 +5,10 @@ Subject: [PATCH] throttle mob spawning
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
|
||||
index ab6fa7ed111ef16a0b6774c21988589ee2110c66..b1220364424db2e0dce58c5a0f6334e2e9f06dec 100644
|
||||
index c3284577437412e1c3fb891bee2b0e20b52ccd59..bb5b51b661542996c5a3dce2dc873bf198a89745 100644
|
||||
--- a/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -215,6 +215,17 @@ public final class NaturalSpawner {
|
||||
@@ -217,6 +217,17 @@ public final class NaturalSpawner {
|
||||
// Paper start - Optional per player mob spawns
|
||||
final boolean canSpawn;
|
||||
int maxSpawns = Integer.MAX_VALUE;
|
||||
|
||||
@@ -5,10 +5,10 @@ Subject: [PATCH] optimize random tick
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 1c7e2e5124c7d4c1b86039b0327bfd92c49df9b1..976fcc96f8f0a10338c5b98bd3908e6def217676 100644
|
||||
index 43156ecde8bb86c77f3b13c17b3330eae95efcc3..ba0f66b5089e252e5d532cb4b94c6246a65d69d8 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -676,7 +676,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -669,7 +669,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
list.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Raneri <kevin.raneri@gmail.com>
|
||||
Date: Wed, 10 Nov 2021 00:37:03 -0500
|
||||
Subject: [PATCH] Pufferfish: Optimize mob spawning
|
||||
|
||||
Original license: GPL v3
|
||||
Original project: https://github.com/pufferfish-gg/Pufferfish
|
||||
|
||||
Co-authored-by: booky10 <boooky10@gmail.com>
|
||||
Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
|
||||
This patch aims to reduce the main-thread impact of mob spawning by
|
||||
offloading as much work as possible to other threads. It is possible for
|
||||
inconsistencies to come up, but when they happen they never interfere
|
||||
with the server's operation (they don't produce errors), and side
|
||||
effects are limited to more or less mobs being spawned in any particular
|
||||
tick.
|
||||
|
||||
It is possible to disable this optimization if it is not required or if
|
||||
it interferes with any plugins. On servers with thousands of entities,
|
||||
this can result in performance gains of up to 15%, which is significant
|
||||
and, in my opinion, worth the low risk of minor mob-spawning-related
|
||||
inconsistencies.
|
||||
|
||||
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java b/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java
|
||||
index ece6db7b9a0dfd535141c0c756947c4898140503..06bf5e6e40bde49da7a2a73119c24dd45e7378a7 100644
|
||||
--- a/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java
|
||||
+++ b/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java
|
||||
@@ -11,7 +11,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
public static final int ITERATOR_FLAG_SEE_ADDITIONS = 1 << 0;
|
||||
|
||||
private final Reference2IntLinkedOpenHashMap<E> indexMap;
|
||||
- private int firstInvalidIndex = -1;
|
||||
+ private final java.util.concurrent.atomic.AtomicInteger firstInvalidIndex = new java.util.concurrent.atomic.AtomicInteger(-1); // Leaf - Pufferfish - Async mob spawning - atomic
|
||||
|
||||
/* list impl */
|
||||
private E[] listElements;
|
||||
@@ -19,27 +19,41 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
|
||||
private final double maxFragFactor;
|
||||
|
||||
- private int iteratorCount;
|
||||
+ private int iteratorCount; // Pufferfish - async mob spawning
|
||||
+
|
||||
+ // Pufferfish start - async mob spawning
|
||||
+ private final boolean threadRestricted;
|
||||
|
||||
public IteratorSafeOrderedReferenceSet() {
|
||||
- this(Object.class);
|
||||
+ this(16, 0.75f, 16, 0.2, Object.class, false);
|
||||
+ }
|
||||
+
|
||||
+ public IteratorSafeOrderedReferenceSet(final boolean threadRestricted) {
|
||||
+ this(16, 0.75f, 16, 0.2, Object.class, threadRestricted);
|
||||
}
|
||||
|
||||
public IteratorSafeOrderedReferenceSet(final Class<? super E> arrComponent) {
|
||||
- this(16, 0.75f, 16, 0.2, arrComponent);
|
||||
+ this(16, 0.75f, 16, 0.2, arrComponent, false);
|
||||
}
|
||||
|
||||
public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
|
||||
final double maxFragFactor) {
|
||||
- this(setCapacity, setLoadFactor, arrayCapacity, maxFragFactor, Object.class);
|
||||
+ this(setCapacity, setLoadFactor, arrayCapacity, maxFragFactor, Object.class, false);
|
||||
}
|
||||
|
||||
public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
|
||||
final double maxFragFactor, final Class<? super E> arrComponent) {
|
||||
+ this(setCapacity, setLoadFactor, arrayCapacity, maxFragFactor, arrComponent, false);
|
||||
+ }
|
||||
+
|
||||
+ public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
|
||||
+ final double maxFragFactor, final Class<? super E> arrComponent, final boolean threadRestricted) {
|
||||
this.indexMap = new Reference2IntLinkedOpenHashMap<>(setCapacity, setLoadFactor);
|
||||
this.indexMap.defaultReturnValue(-1);
|
||||
this.maxFragFactor = maxFragFactor;
|
||||
this.listElements = (E[])Array.newInstance(arrComponent, arrayCapacity);
|
||||
+ this.threadRestricted = threadRestricted;
|
||||
+ // Pufferfish end - async mob spawning
|
||||
}
|
||||
|
||||
// includes null (gravestone) elements
|
||||
@@ -94,16 +108,24 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
}
|
||||
*/
|
||||
|
||||
+ // Pufferfish start - async mob spawning
|
||||
+ // Bring back allowSafeIteration from Paper 1.20.4
|
||||
+ // To defrag only on the main thread
|
||||
+ private boolean allowSafeIteration() {
|
||||
+ return !this.threadRestricted || ca.spottedleaf.moonrise.common.util.TickThread.isTickThread();
|
||||
+ }
|
||||
+ // Pufferfish end - async mob spawning
|
||||
+
|
||||
private double getFragFactor() {
|
||||
return 1.0 - ((double)this.indexMap.size() / (double)this.listSize);
|
||||
}
|
||||
|
||||
public int createRawIterator() {
|
||||
- ++this.iteratorCount;
|
||||
+ if (this.allowSafeIteration()) this.iteratorCount++; // Pufferfish - async mob spawning
|
||||
if (this.indexMap.isEmpty()) {
|
||||
return Integer.MAX_VALUE;
|
||||
} else {
|
||||
- return this.firstInvalidIndex == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0;
|
||||
+ return this.firstInvalidIndex.get() == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0; // Leaf - Pufferfish - Async mob spawning
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +142,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
}
|
||||
|
||||
public void finishRawIterator() {
|
||||
- if (--this.iteratorCount == 0) {
|
||||
+ if (--this.iteratorCount == 0) { // Pufferfish - async mob spawning
|
||||
if (this.getFragFactor() >= this.maxFragFactor) {
|
||||
this.defrag();
|
||||
}
|
||||
@@ -130,14 +152,17 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
public boolean remove(final E element) {
|
||||
final int index = this.indexMap.removeInt(element);
|
||||
if (index >= 0) {
|
||||
- if (this.firstInvalidIndex < 0 || index < this.firstInvalidIndex) {
|
||||
- this.firstInvalidIndex = index;
|
||||
+ // Leaf start - Pufferfish - Async mob spawning
|
||||
+ int firstInvalidIndex = this.firstInvalidIndex.get();
|
||||
+ if (firstInvalidIndex < 0 || index < firstInvalidIndex) {
|
||||
+ this.firstInvalidIndex.set(index);
|
||||
}
|
||||
+ // Leaf end - Pufferfish - Async mob spawning
|
||||
if (this.listElements[index] != element) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
this.listElements[index] = null;
|
||||
- if (this.iteratorCount == 0 && this.getFragFactor() >= this.maxFragFactor) {
|
||||
+ if (this.allowSafeIteration() && this.iteratorCount == 0 && this.getFragFactor() >= this.maxFragFactor) { // Pufferfish - async mob spawning
|
||||
this.defrag();
|
||||
}
|
||||
//this.check();
|
||||
@@ -169,14 +194,17 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
}
|
||||
|
||||
private void defrag() {
|
||||
- if (this.firstInvalidIndex < 0) {
|
||||
+ // Leaf start - Pufferfish - Async mob spawning
|
||||
+ int firstInvalidIndex = this.firstInvalidIndex.get();
|
||||
+ if (firstInvalidIndex < 0) {
|
||||
return; // nothing to do
|
||||
}
|
||||
+ // Leaf end - Pufferfish - Async mob spawning
|
||||
|
||||
if (this.indexMap.isEmpty()) {
|
||||
Arrays.fill(this.listElements, 0, this.listSize, null);
|
||||
this.listSize = 0;
|
||||
- this.firstInvalidIndex = -1;
|
||||
+ this.firstInvalidIndex.set(-1); // Leaf - Pufferfish - Async mob spawning
|
||||
//this.check();
|
||||
return;
|
||||
}
|
||||
@@ -186,11 +214,11 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
int lastValidIndex;
|
||||
java.util.Iterator<Reference2IntMap.Entry<E>> iterator;
|
||||
|
||||
- if (this.firstInvalidIndex == 0) {
|
||||
+ if (firstInvalidIndex == 0) { // Leaf - Pufferfish - Async mob spawning
|
||||
iterator = this.indexMap.reference2IntEntrySet().fastIterator();
|
||||
lastValidIndex = 0;
|
||||
} else {
|
||||
- lastValidIndex = this.firstInvalidIndex;
|
||||
+ lastValidIndex = firstInvalidIndex; // Leaf - Pufferfish - Async mob spawning
|
||||
final E key = backingArray[lastValidIndex - 1];
|
||||
iterator = this.indexMap.reference2IntEntrySet().fastIterator(new Reference2IntMap.Entry<E>() {
|
||||
@Override
|
||||
@@ -221,7 +249,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
// cleanup end
|
||||
Arrays.fill(backingArray, lastValidIndex, this.listSize, null);
|
||||
this.listSize = lastValidIndex;
|
||||
- this.firstInvalidIndex = -1;
|
||||
+ this.firstInvalidIndex.set(-1); // Leaf - Pufferfish - Async mob spawning
|
||||
//this.check();
|
||||
}
|
||||
|
||||
@@ -235,7 +263,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
}
|
||||
|
||||
public IteratorSafeOrderedReferenceSet.Iterator<E> iterator(final int flags) {
|
||||
- ++this.iteratorCount;
|
||||
+ if (this.allowSafeIteration()) ++this.iteratorCount; // Pufferfish - async mob spawning
|
||||
return new BaseIterator<>(this, true, (flags & ITERATOR_FLAG_SEE_ADDITIONS) != 0 ? Integer.MAX_VALUE : this.listSize);
|
||||
}
|
||||
|
||||
@@ -322,7 +350,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
|
||||
}
|
||||
this.lastReturned = null;
|
||||
this.finished = true;
|
||||
- this.set.finishRawIterator();
|
||||
+ if (this.set.allowSafeIteration()) this.set.finishRawIterator(); // Pufferfish - async mob spawning - diff on change
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ Subject: [PATCH] Fix Pufferfish and Purpur patches
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
|
||||
index 5b844d2fea387f2cb655169f458ec0ca627f1c65..f267abd6f905180cfa5cf4961cf79f57544a891c 100644
|
||||
index f5302d038e4bb731075dccde4015627dc9e7b420..afaff6dcfe2044c465693dd0971d07644470ba8a 100644
|
||||
--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
|
||||
+++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
|
||||
@@ -32,9 +32,11 @@ public record ServerBuildInfoImpl(
|
||||
@@ -20,7 +20,7 @@ index a4d5c65edc1db59f3486ce5d3757cc306211a54b..b00a82816784ea2f6422ca98c1f11597
|
||||
|
||||
// Paper start
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
index 63f6b5d00b401fe670fd237e53dd2073d042535b..eb51cfce4069035664d2d1e3d30ab681e917dee6 100644
|
||||
index a43f3d6e54de52da6b1ee050aefd0028a1adafcf..db71a9fc02bfac7799b58f07da044e53b2273e98 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
@@ -185,7 +185,7 @@ public final class CraftBlockStates {
|
||||
@@ -6,7 +6,7 @@ Subject: [PATCH] Paw optimization
|
||||
Some random optimizations
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
index ae9c9a96ac070f629564fba867749df173fd4f85..461b7ae34a4448cac0f9ca315b25ed9e7564f0b8 100644
|
||||
index e9ec96e9aee0cdf72ff18f8a42389ff78869f58c..ae0b0e2bea46707d78adc60d2cc212a813bef076 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
@@ -244,13 +244,37 @@ public class CraftBlockData implements BlockData {
|
||||
@@ -3,6 +3,7 @@ package gg.pufferfish.pufferfish.util;
|
||||
import it.unimi.dsi.fastutil.PriorityQueue;
|
||||
import it.unimi.dsi.fastutil.PriorityQueues;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayFIFOQueue;
|
||||
import net.minecraft.Util;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -21,6 +22,7 @@ public class AsyncExecutor implements Runnable {
|
||||
.name(threadName)
|
||||
.priority(Thread.NORM_PRIORITY - 1)
|
||||
.daemon(false)
|
||||
.uncaughtExceptionHandler(Util::onThreadException)
|
||||
.unstarted(this);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user