9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-19 15:09:25 +00:00

optimize collectSpawningChunks (#382)

* optimize collectSpawningChunks

* add bit set

* cleanup

* cleanup

* cleanup

* cleanup
This commit is contained in:
hayanesuru
2025-06-29 18:44:04 +09:00
committed by GitHub
parent 58575d0adc
commit 5d663b4d36
4 changed files with 229 additions and 43 deletions

View File

@@ -26,7 +26,7 @@ index 79674f4bd7a12c42dec19a4175012d7a2dc88b84..0a97a491737807d59815b75635fa3d8c
} }
// Paper end - Optional per player mob spawns // Paper end - Optional per player mob spawns
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 46e171ca454253c32e22c0c18587e9a7ba19f331..d91d6988268174ea9f2c919b57a6ba7ea00d7066 100644 index 46e171ca454253c32e22c0c18587e9a7ba19f331..1c7e2e5124c7d4c1b86039b0327bfd92c49df9b1 100644
--- a/net/minecraft/server/level/ServerChunkCache.java --- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/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 @@ -70,11 +70,11 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -47,7 +47,7 @@ index 46e171ca454253c32e22c0c18587e9a7ba19f331..d91d6988268174ea9f2c919b57a6ba7e
} }
private void tickChunks() { private void tickChunks() {
+ // Leaf start + // Leaf start - optimize mob spawning
+ if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled && this.level.tickRateManager().runsNormally()) { + if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled && this.level.tickRateManager().runsNormally()) {
+ for (ServerPlayer player : this.level.players) { + for (ServerPlayer player : this.level.players) {
+ // Paper start - per player mob spawning backoff + // Paper start - per player mob spawning backoff
@@ -63,7 +63,7 @@ index 46e171ca454253c32e22c0c18587e9a7ba19f331..d91d6988268174ea9f2c919b57a6ba7e
+ // Paper end - per player mob spawning backoff + // Paper end - per player mob spawning backoff
+ } + }
+ } + }
+ // Leaf end + // Leaf end - optimize mob spawning
long gameTime = this.level.getGameTime(); long gameTime = this.level.getGameTime();
long l = gameTime - this.lastInhabitedUpdate; long l = gameTime - this.lastInhabitedUpdate;
this.lastInhabitedUpdate = gameTime; this.lastInhabitedUpdate = gameTime;
@@ -108,32 +108,81 @@ index 46e171ca454253c32e22c0c18587e9a7ba19f331..d91d6988268174ea9f2c919b57a6ba7e
mobCapCalculator, // This is the key fix - was previously null mobCapCalculator, // This is the key fix - was previously null
level.paperConfig().entities.spawning.perPlayerMobSpawns level.paperConfig().entities.spawning.perPlayerMobSpawns
); );
@@ -627,9 +644,23 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -610,6 +627,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled chunkRange = Math.min(chunkRange, 8);
entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange);
entityPlayer.playerNaturallySpawnedEvent.callEvent();
+ this.level.natureSpawnChunkMap.addPlayer(entityPlayer); // Leaf - optimize mob spawning
}
// 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
List<LevelChunk> list = this.spawningChunks;
try {
- this.chunkMap.collectSpawningChunks(list);
+ // Leaf start - optimize mob spawning
+ // this.chunkMap.collectSpawningChunks(list);
+ this.level.natureSpawnChunkMap.build();
// Paper start - chunk tick iteration optimisation
- this.shuffleRandom.setSeed(this.level.random.nextLong());
- if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ this.level.natureSpawnChunkMap.collectSpawningChunks(this.level.moonrise$getPlayerTickingChunks(), list);
+ this.shuffleRandom.setSeed(this.level.random.nextLong()); // Leaf - paw optimization - Only set seed if is really used
+ Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
+ }
// Paper end - chunk tick iteration optimisation // Paper end - chunk tick iteration optimisation
- for (LevelChunk levelChunk : list) { - for (LevelChunk levelChunk : list) {
- this.tickSpawningChunk(levelChunk, timeInhabited, filteredSpawningCategories, lastSpawnState); // Pufferfish - this.tickSpawningChunk(levelChunk, timeInhabited, filteredSpawningCategories, lastSpawnState); // Pufferfish
+ // Leaf start - optimize mob spawning + if (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) {
+ var lastSpawnState1 = lastSpawnState; + NaturalSpawner.SpawnState currentState = lastSpawnState;
+ if ((!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) && lastSpawnState1 != null) { + if (currentState != null) {
+ lastSpawnState1.applyPerPlayerMobCount(level); + currentState.applyPerPlayerMobCount(level);
+ if (list instanceof it.unimi.dsi.fastutil.objects.ReferenceArrayList<LevelChunk> arrayList) { + if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ LevelChunk[] levelChunks = arrayList.elements(); + for (LevelChunk levelChunk : list) {
+ int size = arrayList.size(); + this.tickSpawningChunk(levelChunk, timeInhabited, filteredSpawningCategories, currentState); // Pufferfish
+ for (int i = 0; i < size; i++) { + }
+ this.tickSpawningChunk(levelChunks[i], timeInhabited, filteredSpawningCategories, lastSpawnState1); // Pufferfish + } else {
+ } + ca.spottedleaf.moonrise.common.list.ReferenceList<LevelChunk> chunks = this.level.moonrise$getPlayerTickingChunks();
+ } else { + LevelChunk[] raw = chunks.getRawDataUnchecked();
+ for (LevelChunk levelChunk : list) { + for (int i = 0, length = chunks.size(); i < length; i++) {
+ this.tickSpawningChunk(levelChunk, timeInhabited, filteredSpawningCategories, lastSpawnState1); // Pufferfish + LevelChunk levelChunk = raw[i];
+ if (level.natureSpawnChunkMap.contains(levelChunk.locX, levelChunk.locZ)) {
+ this.tickSpawningChunk(levelChunk, timeInhabited, filteredSpawningCategories, currentState); // Pufferfish
+ }
+ }
+ } + }
+ } + }
} }
+ // Leaf end - optimize mob spawning + // Leaf end - optimize mob spawning
} finally { } finally {
+ this.level.natureSpawnChunkMap.clear(); // Leaf - optimize mob spawning
list.clear(); list.clear();
} }
@@ -648,7 +690,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
}
if (!spawnCategories.isEmpty()) {
- if (this.level.getWorldBorder().isWithinBounds(pos) && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get())) { // Paper - rewrite chunk system // Pufferfish
+ if (this.level.getWorldBorder().isWithinBounds(pos)) { // Paper - rewrite chunk system
NaturalSpawner.spawnForChunk(this.level, chunk, spawnState, spawnCategories);
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index fc61a7083232148397a0b330ce2a4d70ba38543d..d13ab16368d5fed5c81211b63c7670e534f6ed01 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1114,6 +1114,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.simpleRandom.nextInt(16); } // Gale - Airplane - optimize random calls in chunk ticking
+ public org.dreeam.leaf.world.NatureSpawnChunkMap natureSpawnChunkMap = new org.dreeam.leaf.world.NatureSpawnChunkMap(); // Leaf - optimize mob spawning
public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
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 diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 81e176d17fb072f9ee531639abfe42134ae833a9..ab6fa7ed111ef16a0b6774c21988589ee2110c66 100644 index 81e176d17fb072f9ee531639abfe42134ae833a9..ab6fa7ed111ef16a0b6774c21988589ee2110c66 100644
--- a/net/minecraft/world/level/NaturalSpawner.java --- a/net/minecraft/world/level/NaturalSpawner.java

View File

@@ -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 diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index d91d6988268174ea9f2c919b57a6ba7ea00d7066..804ad5ae82b875d3b2cccb828eaa0ea54fe43011 100644 index f3489fda7f144e13e23fdb4521c942489238fe75..76c0b36025e2c12f990b9d4ec7c1d88b227c333b 100644
--- a/net/minecraft/server/level/ServerChunkCache.java --- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -665,7 +665,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -676,7 +676,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
list.clear(); list.clear();
} }
@@ -24,13 +24,13 @@ index d91d6988268174ea9f2c919b57a6ba7ea00d7066..804ad5ae82b875d3b2cccb828eaa0ea5
this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies);
} }
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index fc61a7083232148397a0b330ce2a4d70ba38543d..d34a7cfa3b923d59ade35ce4c43cfd3f1477e057 100644 index d13ab16368d5fed5c81211b63c7670e534f6ed01..c49d2f7314a35763831285d7d46d34dade2f0085 100644
--- a/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -1114,6 +1114,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -1115,6 +1115,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.simpleRandom.nextInt(16); } // Gale - Airplane - optimize random calls in chunk ticking private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.simpleRandom.nextInt(16); } // Gale - Airplane - optimize random calls in chunk ticking
public org.dreeam.leaf.world.NatureSpawnChunkMap natureSpawnChunkMap = new org.dreeam.leaf.world.NatureSpawnChunkMap(); // Leaf - optimize mob spawning
+ public org.dreeam.leaf.world.RandomTickSystem randomTickSystem = new org.dreeam.leaf.world.RandomTickSystem(); // Leaf - optimize random tick + public org.dreeam.leaf.world.RandomTickSystem randomTickSystem = new org.dreeam.leaf.world.RandomTickSystem(); // Leaf - optimize random tick
public void tickChunk(LevelChunk chunk, int randomTickSpeed) { public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
final net.minecraft.world.level.levelgen.BitRandomSource simpleRandom = this.simpleRandom; // Paper - optimise random ticking // Leaf - Faster random generator - upcasting final net.minecraft.world.level.levelgen.BitRandomSource simpleRandom = this.simpleRandom; // Paper - optimise random ticking // Leaf - Faster random generator - upcasting

View File

@@ -99,28 +99,11 @@ index 4535858701b2bb232b9d2feb2af6551526232ddc..e65c62dbe4c1560ae153e4c4344e9194
- } - }
- // Paper end - detailed watchdog information - // Paper end - detailed watchdog information
} }
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 804ad5ae82b875d3b2cccb828eaa0ea54fe43011..328ed610f5d532784bd6c38c4833591dc19442cb 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -640,8 +640,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
try {
this.chunkMap.collectSpawningChunks(list);
// Paper start - chunk tick iteration optimisation
- this.shuffleRandom.setSeed(this.level.random.nextLong());
- if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ this.shuffleRandom.setSeed(this.level.random.nextLong()); // Leaf - paw optimization - Only set seed if is really used
+ Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
+ }
// Paper end - chunk tick iteration optimisation
// Leaf start - optimize mob spawning
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index d34a7cfa3b923d59ade35ce4c43cfd3f1477e057..e5ec54af005eb53399f9d2db49917c24023fcfdc 100644 index c49d2f7314a35763831285d7d46d34dade2f0085..79f2b26bc466238ec83cd049f38d257b0000028d 100644
--- a/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -1517,13 +1517,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -1518,13 +1518,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper end - log detailed entity tick information // Paper end - log detailed entity tick information
public void tickNonPassenger(Entity entity) { public void tickNonPassenger(Entity entity) {
@@ -134,7 +117,7 @@ index d34a7cfa3b923d59ade35ce4c43cfd3f1477e057..e5ec54af005eb53399f9d2db49917c24
entity.setOldPosAndRot(); entity.setOldPosAndRot();
entity.tickCount++; entity.tickCount++;
entity.totalEntityAge++; // Paper - age-like counter for all entities entity.totalEntityAge++; // Paper - age-like counter for all entities
@@ -1536,13 +1530,6 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -1537,13 +1531,6 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
for (Entity entity1 : entity.getPassengers()) { for (Entity entity1 : entity.getPassengers()) {
this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2 this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2
} }

View File

@@ -0,0 +1,154 @@
package org.dreeam.leaf.world;
import ca.spottedleaf.moonrise.common.list.ReferenceList;
import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent;
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.LevelChunk;
import java.util.List;
public class NatureSpawnChunkMap {
/// breadth-first search
///
/// 0 4 12 28 48 80 112 148 196
private static final long[][] TABLE_BFS = new long[][]{
{0L},
{0L, 4294967295L, -4294967296L, 4294967296L, 1L},
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, 4294967294L, -8589934592L, 8589934592L, 2L},
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, 4294967293L, -12884901888L, 12884901888L, 3L},
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 4294967292L, -17179869184L, 17179869184L, 4L},
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -8589934595L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869181L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -12884901885L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 12884901891L, -8589934596L, -4294967300L, -12884901891L, -12884901890L, -4L, 4294967292L, -12884901889L, -17179869184L, 8589934588L, 12884901884L, -17179869183L, -17179869182L, 17179869180L, 21474836477L, 21474836478L, 21474836479L, 17179869184L, 17179869185L, 17179869186L, -17179869181L, 17179869187L, -12884901884L, -8589934588L, -4294967292L, 4L, 4294967300L, 8589934596L, 12884901892L, 4294967291L, -21474836480L, 21474836480L, 5L},
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -8589934595L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869181L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -12884901885L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 12884901891L, -12884901892L, -8589934596L, -4294967300L, -12884901891L, -12884901890L, -4L, 4294967292L, -12884901889L, -17179869184L, 8589934588L, 12884901884L, -17179869183L, -17179869182L, 17179869180L, 21474836476L, 21474836477L, 21474836478L, 21474836479L, 17179869184L, 17179869185L, 17179869186L, -17179869181L, 17179869187L, -17179869180L, -12884901884L, -8589934588L, -4294967292L, 4L, 4294967300L, 8589934596L, 12884901892L, 17179869188L, -8589934597L, -17179869187L, -4294967301L, -5L, -17179869186L, -17179869185L, 4294967291L, 8589934587L, -21474836480L, -21474836479L, 12884901883L, 17179869179L, -21474836478L, -21474836477L, 25769803773L, 25769803774L, 25769803775L, 21474836480L, 21474836481L, 21474836482L, 21474836483L, -12884901883L, -8589934587L, -4294967291L, 5L, 4294967301L, 8589934597L, 12884901893L, 4294967290L, -25769803776L, 25769803776L, 6L},
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -8589934595L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869181L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -12884901885L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 12884901891L, -12884901892L, -8589934596L, -4294967300L, -12884901891L, -12884901890L, -4L, 4294967292L, -12884901889L, -17179869184L, 8589934588L, 12884901884L, -17179869183L, -17179869182L, 17179869180L, 21474836476L, 21474836477L, 21474836478L, 21474836479L, 17179869184L, 17179869185L, 17179869186L, -17179869181L, 17179869187L, -17179869180L, -12884901884L, -8589934588L, -4294967292L, 4L, 4294967300L, 8589934596L, 12884901892L, 17179869188L, -12884901893L, -8589934597L, -17179869188L, -17179869187L, -4294967301L, -5L, -17179869186L, -17179869185L, 4294967291L, 8589934587L, -21474836480L, -21474836479L, 12884901883L, 17179869179L, -21474836478L, -21474836477L, 21474836475L, 25769803772L, 25769803773L, 25769803774L, 25769803775L, 21474836480L, 21474836481L, 21474836482L, 21474836483L, -21474836476L, 21474836484L, -17179869179L, -12884901883L, -8589934587L, -4294967291L, 5L, 4294967301L, 8589934597L, 12884901893L, 17179869189L, -8589934598L, -4294967302L, -21474836483L, -21474836482L, -6L, 4294967290L, -21474836481L, -25769803776L, 8589934586L, 12884901882L, -25769803775L, -25769803774L, 17179869178L, -25769803773L, 30064771069L, 30064771070L, 30064771071L, 25769803776L, 25769803777L, 25769803778L, 25769803779L, -12884901882L, -8589934586L, -4294967290L, 6L, 4294967302L, 8589934598L, 12884901894L, 4294967289L, -30064771072L, 30064771072L, 7L},
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -8589934595L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869181L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -12884901885L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 12884901891L, -12884901892L, -8589934596L, -4294967300L, -12884901891L, -12884901890L, -4L, 4294967292L, -12884901889L, -17179869184L, 8589934588L, 12884901884L, -17179869183L, -17179869182L, 17179869180L, 21474836476L, 21474836477L, 21474836478L, 21474836479L, 17179869184L, 17179869185L, 17179869186L, -17179869181L, 17179869187L, -17179869180L, -12884901884L, -8589934588L, -4294967292L, 4L, 4294967300L, 8589934596L, 12884901892L, 17179869188L, -17179869189L, -12884901893L, -8589934597L, -17179869188L, -17179869187L, -4294967301L, -5L, -17179869186L, -17179869185L, 4294967291L, 8589934587L, -21474836480L, -21474836479L, 12884901883L, 17179869179L, -21474836478L, -21474836477L, 21474836475L, 25769803771L, 25769803772L, 25769803773L, 25769803774L, 25769803775L, 21474836480L, 21474836481L, 21474836482L, 21474836483L, -21474836476L, 21474836484L, -21474836475L, -17179869179L, -12884901883L, -8589934587L, -4294967291L, 5L, 4294967301L, 8589934597L, 12884901893L, 17179869189L, 21474836485L, -17179869190L, -12884901894L, -21474836485L, -21474836484L, -8589934598L, -4294967302L, -21474836483L, -21474836482L, -6L, 4294967290L, -21474836481L, -25769803776L, 8589934586L, 12884901882L, -25769803775L, -25769803774L, 17179869178L, 21474836474L, -25769803773L, -25769803772L, 25769803770L, 30064771067L, 30064771068L, 30064771069L, 30064771070L, 30064771071L, 25769803776L, 25769803777L, 25769803778L, 25769803779L, 25769803780L, -25769803771L, 25769803781L, -21474836474L, -17179869178L, -12884901882L, -8589934586L, -4294967290L, 6L, 4294967302L, 8589934598L, 12884901894L, 17179869190L, 21474836486L, -8589934599L, -25769803779L, -4294967303L, -7L, -25769803778L, -25769803777L, 4294967289L, 8589934585L, -30064771072L, -30064771071L, 12884901881L, 17179869177L, -30064771070L, -30064771069L, 34359738365L, 34359738366L, 34359738367L, 30064771072L, 30064771073L, 30064771074L, 30064771075L, -12884901881L, -8589934585L, -4294967289L, 7L, 4294967303L, 8589934599L, 12884901895L, 4294967288L, -34359738368L, 34359738368L, 8L}
};
private static final int MAX_RADIUS = 8;
private static final int SIZE_RADIUS = 9;
private static final int REGION_MASK = 15;
private static final int REGION_SHIFT = 4;
private final LongArrayList[] centersByRadius;
private final Long2LongOpenHashMap regionBitSets;
public NatureSpawnChunkMap() {
this.centersByRadius = new LongArrayList[SIZE_RADIUS];
for (int i = 0; i < SIZE_RADIUS; i++) {
this.centersByRadius[i] = new LongArrayList();
}
this.regionBitSets = new Long2LongOpenHashMap();
}
public void clear() {
for (LongArrayList chunkPosition : this.centersByRadius) {
chunkPosition.clear();
}
this.regionBitSets.clear();
}
public void addPlayer(ServerPlayer player) {
if (player.isSpectator()) {
return;
}
PlayerNaturallySpawnCreaturesEvent event = player.playerNaturallySpawnedEvent;
if (event == null || event.isCancelled()) {
return;
}
int range = event.getSpawnRadius();
if (range > MAX_RADIUS) {
range = MAX_RADIUS;
} else if (range < 0) {
return;
}
this.centersByRadius[range].add(player.chunkPosition().longKey);
}
public void build() {
for (int index = 0; index < SIZE_RADIUS; index++) {
buildBy(index);
}
}
private void buildBy(int index) {
LongArrayList list = this.centersByRadius[index];
int centersSize = deduplicate(list);
if (centersSize == 0) {
return;
}
long[] centersRaw = list.elements();
long cachedKey = ChunkPos.asLong(ChunkPos.getX(centersRaw[0]) >> REGION_SHIFT, ChunkPos.getZ(centersRaw[0]) >> REGION_SHIFT);
long cachedVal = this.regionBitSets.get(cachedKey);
long[] offsets = TABLE_BFS[index];
for (int i = 0; i < centersSize; i++) {
long center = centersRaw[i];
int cx = ChunkPos.getX(center);
int cz = ChunkPos.getZ(center);
for (long packedOffset : offsets) {
int dx = ChunkPos.getX(packedOffset);
int dz = ChunkPos.getZ(packedOffset);
int chunkX = cx + dx;
int chunkZ = cz + dz;
int regionX = chunkX >> REGION_SHIFT;
int regionZ = chunkZ >> REGION_SHIFT;
long regionKey = ChunkPos.asLong(regionX, regionZ);
int localX = chunkX & REGION_MASK;
int localZ = chunkZ & REGION_MASK;
int bitIndex = (localZ << REGION_SHIFT) | localX;
long bitMask = 1L << bitIndex;
if (regionKey != cachedKey) {
this.regionBitSets.put(cachedKey, cachedVal);
cachedKey = regionKey;
cachedVal = this.regionBitSets.get(regionKey);
}
cachedVal |= bitMask;
}
}
if (cachedVal != 0L) {
this.regionBitSets.put(cachedKey, cachedVal);
}
}
private int deduplicate(LongArrayList list) {
int n = list.size();
if (n == 0) {
return 0;
}
list.unstableSort(null);
long[] centersRaw = list.elements();
int size = 0;
for (int i = 1; i < n; i++) {
long current = centersRaw[i];
long last = centersRaw[size];
if (current != last) {
size++;
centersRaw[size] = current;
}
}
return size + 1;
}
public void collectSpawningChunks(ReferenceList<LevelChunk> chunks, List<LevelChunk> out) {
LevelChunk[] raw = chunks.getRawDataUnchecked();
for (int i = 0, length = chunks.size(); i < length; i++) {
LevelChunk chunk = raw[i];
if (contains(chunk.locX, chunk.locZ)) {
out.add(chunk);
}
}
}
public boolean contains(int chunkX, int chunkZ) {
int regionX = chunkX >> REGION_SHIFT;
int regionZ = chunkZ >> REGION_SHIFT;
long bitset = this.regionBitSets.get(ChunkPos.asLong(regionX, regionZ));
return bitset != 0 && (bitset & (1L << (((chunkZ & REGION_MASK) << REGION_SHIFT) | (chunkX & REGION_MASK)))) != 0L;
}
}