From fc91a1144c3a77270d6a1a6ea8eaf61fc7120153 Mon Sep 17 00:00:00 2001 From: md_5 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 5b13dea..51db2db 100644 --- a/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java @@ -33,6 +33,7 @@ public class Chunk { public int p; public long q; private int u; + protected gnu.trove.map.hash.TObjectIntHashMap entityCount = new gnu.trove.map.hash.TObjectIntHashMap(); // Spigot public Chunk(World world, int i, int j) { this.sections = new ChunkSection[16]; @@ -552,6 +553,15 @@ public class Chunk { entity.ak = k; entity.al = this.z; this.entitySlices[k].add(entity); + // Spigot start - increment creature type count + 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) { @@ -568,6 +578,15 @@ public class Chunk { } this.entitySlices[i].remove(entity); + // Spigot start - decrement creature type count + 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 9812538..ecf13aa 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.bv()) { continue label110; } diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java index f74fc9b..f0becc1 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -154,4 +154,11 @@ public class SpigotWorldConfig antiXrayInstance = new AntiXray( this ); } + + public byte mobSpawnRange; + private void mobSpawnRange() + { + mobSpawnRange = (byte) getInt( "mob-spawn-range", 4 ); + log( "Mob Spawn Range: " + mobSpawnRange ); + } } -- 1.8.1.2