Paper/CraftBukkit-Patches/0016-Fix-Mob-Spawning-Relative-to-View-Distance.patch
md_5 af480b8b95 Revert previous change to clear chunk list on the end of each tick, make it configurable instead.
Whilst the new behaviour was technically correct as it prevented the possibility of the chunk tick list actually increasing over time, it introduced a few issues, namely the fact that it slowed growth to unreasonable levels, and interfered with the values which server admins have finally tuned, and come to enjoy over the last few years.
If it is absolutely essential that growth be halted and ticking reduced as much as possible, the config option is there for power users.
If we wish to 'fix' this by default in the future, a new chunk ticking algorithm, which actually has meaningful config options should be designed.
2014-01-14 19:16:43 +11:00

156 lines
7.1 KiB
Diff

From d9860352fadbcf7ba9dc05acdfa6f57bbb3fe2e7 Mon Sep 17 00:00:00 2001
From: md_5 <md_5@live.com.au>
Date: Fri, 21 Jun 2013 17:29:54 +1000
Subject: [PATCH] Fix Mob Spawning Relative to View Distance
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 95b4704..3bcca91 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -40,6 +40,7 @@ public class Chunk {
public int r;
public long s;
private int x;
+ protected gnu.trove.map.hash.TObjectIntHashMap<Class> entityCount = new gnu.trove.map.hash.TObjectIntHashMap<Class>(); // Spigot
public Chunk(World world, int i, int j) {
this.sections = new ChunkSection[16];
@@ -601,6 +602,22 @@ public class Chunk {
entity.aj = k;
entity.ak = this.locZ;
this.entitySlices[k].add(entity);
+ // Spigot start - increment creature type count
+ // Keep this synced up with World.a(Class)
+ if (entity instanceof EntityInsentient) {
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
+ if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) {
+ return;
+ }
+ }
+ for ( EnumCreatureType creatureType : EnumCreatureType.values() )
+ {
+ if ( creatureType.a().isAssignableFrom( entity.getClass() ) )
+ {
+ this.entityCount.adjustOrPutValue( creatureType.a(), 1, 1 );
+ }
+ }
+ // Spigot end
}
public void b(Entity entity) {
@@ -617,6 +634,22 @@ public class Chunk {
}
this.entitySlices[i].remove(entity);
+ // Spigot start - decrement creature type count
+ // Keep this synced up with World.a(Class)
+ if (entity instanceof EntityInsentient) {
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
+ if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) {
+ return;
+ }
+ }
+ for ( EnumCreatureType creatureType : EnumCreatureType.values() )
+ {
+ if ( creatureType.a().isAssignableFrom( entity.getClass() ) )
+ {
+ this.entityCount.adjustValue( creatureType.a(), -1 );
+ }
+ }
+ // Spigot end
}
public boolean d(int i, int j, int k) {
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index f514b78..3f0dd70 100644
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -27,6 +27,23 @@ public final class SpawnerCreature {
return new ChunkPosition(k, i1, l);
}
+ // Spigot start - get entity count only from chunks being processed in b
+ private int getEntityCount(WorldServer server, Class oClass)
+ {
+ int i = 0;
+ for ( Long coord : this.a.keySet() )
+ {
+ int x = LongHash.msw( coord );
+ int z = LongHash.lsw( coord );
+ if ( !server.chunkProviderServer.unloadQueue.contains( coord ) && server.isChunkLoaded( x, z ) )
+ {
+ i += server.getChunkAt( x, z ).entityCount.get( oClass );
+ }
+ }
+ return i;
+ }
+ // Spigot end
+
public int spawnEntities(WorldServer worldserver, boolean flag, boolean flag1, boolean flag2) {
if (!flag && !flag1) {
return 0;
@@ -42,6 +59,11 @@ public final class SpawnerCreature {
j = MathHelper.floor(entityhuman.locZ / 16.0D);
byte b0 = 8;
+ // Spigot Start
+ b0 = worldserver.spigotConfig.mobSpawnRange;
+ b0 = ( b0 > worldserver.spigotConfig.viewDistance ) ? (byte) worldserver.spigotConfig.viewDistance : b0;
+ b0 = ( b0 > 8 ) ? 8 : b0;
+ // Spigot End
for (int l = -b0; l <= b0; ++l) {
for (int i1 = -b0; i1 <= b0; ++i1) {
@@ -89,13 +111,15 @@ public final class SpawnerCreature {
if (limit == 0) {
continue;
}
+ int mobcnt = 0;
// CraftBukkit end
- if ((!enumcreaturetype.d() || flag1) && (enumcreaturetype.d() || flag) && (!enumcreaturetype.e() || flag2) && worldserver.a(enumcreaturetype.a()) <= limit * this.a.size() / 256) { // CraftBukkit - use per-world limits
+ if ((!enumcreaturetype.d() || flag1) && (enumcreaturetype.d() || flag) && (!enumcreaturetype.e() || flag2) && (mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * this.a.size() / 256) { // Spigot - use per-world limits and use all loaded chunks
Iterator iterator = this.a.keySet().iterator();
+ int moblimit = (limit * this.a.size() / 256) - mobcnt + 1; // Spigot - up to 1 more than limit
label110:
- while (iterator.hasNext()) {
+ while (iterator.hasNext() && (moblimit > 0)) { // Spigot - while more allowed
// CraftBukkit start
long key = ((Long) iterator.next()).longValue();
@@ -160,6 +184,13 @@ public final class SpawnerCreature {
groupdataentity = entityinsentient.a(groupdataentity);
worldserver.addEntity(entityinsentient, SpawnReason.NATURAL);
// CraftBukkit end
+ // Spigot start
+ if ( --moblimit <= 0 )
+ {
+ // If we're past limit, stop spawn
+ continue label110;
+ }
+ // Spigot end
if (j2 >= entityinsentient.bz()) {
continue label110;
}
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
index 15b2ac8..49a5b7a 100644
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
@@ -131,4 +131,11 @@ public class SpigotWorldConfig
viewDistance = getInt( "view-distance", Bukkit.getViewDistance() );
log( "View Distance: " + viewDistance );
}
+
+ public byte mobSpawnRange;
+ private void mobSpawnRange()
+ {
+ mobSpawnRange = (byte) getInt( "mob-spawn-range", 4 );
+ log( "Mob Spawn Range: " + mobSpawnRange );
+ }
}
--
1.8.3.2