2014-11-29 01:06:26 +01:00
|
|
|
From bc6052de701c26b98da0e84539c029dfadd6b153 Mon Sep 17 00:00:00 2001
|
2014-07-21 22:46:54 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
Changes the mob spawning algorithm to properly account for view distance and the range around players.
|
|
|
|
|
|
|
|
Needs better documentation.
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
2014-11-28 02:17:45 +01:00
|
|
|
index 7519bfa..c3059b6 100644
|
2014-07-21 22:46:54 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
2014-11-28 02:17:45 +01:00
|
|
|
@@ -42,6 +42,7 @@ public class Chunk {
|
|
|
|
private long u;
|
|
|
|
private int v;
|
|
|
|
private ConcurrentLinkedQueue w;
|
|
|
|
+ protected gnu.trove.map.hash.TObjectIntHashMap<Class> entityCount = new gnu.trove.map.hash.TObjectIntHashMap<Class>(); // Spigot
|
2014-07-21 22:46:54 +02:00
|
|
|
|
|
|
|
// CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
|
|
|
|
private int neighbors = 0x1 << 12;
|
2014-11-28 02:17:45 +01:00
|
|
|
@@ -662,6 +663,22 @@ public class Chunk {
|
|
|
|
entity.af = k;
|
|
|
|
entity.ag = this.locZ;
|
2014-07-21 22:46:54 +02:00
|
|
|
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) {
|
2014-11-28 02:17:45 +01:00
|
|
|
@@ -678,6 +695,22 @@ public class Chunk {
|
2014-07-21 22:46:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2014-11-28 02:17:45 +01:00
|
|
|
public boolean d(BlockPosition blockposition) {
|
2014-07-21 22:46:54 +02:00
|
|
|
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
2014-11-28 02:17:45 +01:00
|
|
|
index 25988d4..43954b3 100644
|
2014-07-21 22:46:54 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
2014-11-28 02:17:45 +01:00
|
|
|
@@ -19,6 +19,25 @@ public final class SpawnerCreature {
|
|
|
|
|
|
|
|
public SpawnerCreature() {}
|
2014-07-21 22:46:54 +02:00
|
|
|
|
|
|
|
+ // Spigot start - get entity count only from chunks being processed in b
|
|
|
|
+ private int getEntityCount(WorldServer server, Class oClass)
|
|
|
|
+ {
|
|
|
|
+ int i = 0;
|
2014-11-28 02:17:45 +01:00
|
|
|
+ Iterator<Long> it = this.b.iterator();
|
|
|
|
+ while ( it.hasNext() )
|
2014-07-21 22:46:54 +02:00
|
|
|
+ {
|
2014-11-28 02:17:45 +01:00
|
|
|
+ Long coord = it.next();
|
2014-07-21 22:46:54 +02:00
|
|
|
+ int x = LongHash.msw( coord );
|
|
|
|
+ int z = LongHash.lsw( coord );
|
2014-11-28 02:17:45 +01:00
|
|
|
+ if ( !server.chunkProviderServer.unloadQueue.contains( coord ) && server.isChunkLoaded( x, z, true ) )
|
2014-07-21 22:46:54 +02:00
|
|
|
+ {
|
|
|
|
+ i += server.getChunkAt( x, z ).entityCount.get( oClass );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return i;
|
|
|
|
+ }
|
|
|
|
+ // Spigot end
|
|
|
|
+
|
2014-11-28 02:17:45 +01:00
|
|
|
public int a(WorldServer worldserver, boolean flag, boolean flag1, boolean flag2) {
|
2014-07-21 22:46:54 +02:00
|
|
|
if (!flag && !flag1) {
|
|
|
|
return 0;
|
2014-11-28 02:17:45 +01:00
|
|
|
@@ -38,6 +57,11 @@ public final class SpawnerCreature {
|
2014-07-21 22:46:54 +02:00
|
|
|
|
2014-11-28 02:17:45 +01:00
|
|
|
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
|
2014-07-21 22:46:54 +02:00
|
|
|
|
|
|
|
for (int i1 = -b0; i1 <= b0; ++i1) {
|
2014-11-28 02:17:45 +01:00
|
|
|
for (k = -b0; k <= b0; ++k) {
|
|
|
|
@@ -88,17 +112,19 @@ public final class SpawnerCreature {
|
2014-07-21 22:46:54 +02:00
|
|
|
if (limit == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2014-11-28 02:17:45 +01:00
|
|
|
+ int mobcnt = 0; // Spigot
|
2014-07-21 22:46:54 +02:00
|
|
|
// CraftBukkit end
|
|
|
|
|
2014-11-28 02:17:45 +01:00
|
|
|
if ((!enumcreaturetype.d() || flag1) && (enumcreaturetype.d() || flag) && (!enumcreaturetype.e() || flag2)) {
|
|
|
|
k = worldserver.a(enumcreaturetype.a());
|
|
|
|
int l1 = limit * i / a; // CraftBukkit - use per-world limits
|
|
|
|
|
|
|
|
- if (k <= l1) {
|
|
|
|
+ if ((mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * i / 256) {
|
|
|
|
Iterator iterator1 = this.b.iterator();
|
2014-07-21 22:46:54 +02:00
|
|
|
|
2014-11-28 02:17:45 +01:00
|
|
|
+ int moblimit = (limit * i / 256) - mobcnt + 1; // Spigot - up to 1 more than limit
|
|
|
|
label115:
|
|
|
|
- while (iterator1.hasNext()) {
|
|
|
|
+ while (iterator1.hasNext() && (moblimit > 0)) { // Spigot - while more allowed
|
|
|
|
// CraftBukkit start = use LongHash and LongObjectHashMap
|
|
|
|
long key = ((Long) iterator1.next()).longValue();
|
|
|
|
BlockPosition blockposition1 = getRandomPosition(worldserver, LongHash.msw(key), LongHash.lsw(key));
|
|
|
|
@@ -156,6 +182,13 @@ public final class SpawnerCreature {
|
|
|
|
worldserver.addEntity(entityinsentient, SpawnReason.NATURAL); // CraftBukkit - Added a reason for spawning this creature
|
|
|
|
}
|
2014-07-21 22:46:54 +02:00
|
|
|
|
2014-11-28 02:17:45 +01:00
|
|
|
+ // Spigot start
|
|
|
|
+ if ( --moblimit <= 0 )
|
|
|
|
+ {
|
|
|
|
+ // If we're past limit, stop spawn
|
|
|
|
+ continue label115;
|
|
|
|
+ }
|
|
|
|
+ // Spigot end
|
|
|
|
if (l2 >= entityinsentient.bU()) {
|
|
|
|
continue label115;
|
|
|
|
}
|
2014-07-21 22:46:54 +02:00
|
|
|
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
|
|
|
index 6cc3a91..46249d7 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 );
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
--
|
2014-11-28 02:17:45 +01:00
|
|
|
2.1.0
|
2014-07-21 22:46:54 +02:00
|
|
|
|