2011-06-22 17:55:04 +02:00
|
|
|
package net.minecraft.server;
|
|
|
|
|
2011-09-15 02:23:52 +02:00
|
|
|
import java.util.Collection;
|
2011-11-20 09:01:14 +01:00
|
|
|
import java.util.HashMap;
|
2011-06-22 17:55:04 +02:00
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.List;
|
2011-09-15 02:23:52 +02:00
|
|
|
import java.util.Random;
|
2011-06-22 17:55:04 +02:00
|
|
|
|
2012-02-10 06:43:12 +01:00
|
|
|
// CraftBukkit start
|
2011-12-07 01:21:10 +01:00
|
|
|
import org.bukkit.craftbukkit.util.LongBaseHashtable;
|
2011-12-06 14:52:45 +01:00
|
|
|
import org.bukkit.craftbukkit.util.EntryBase;
|
|
|
|
import org.bukkit.craftbukkit.util.LongHash;
|
2011-06-22 17:55:04 +02:00
|
|
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
2012-02-10 06:43:12 +01:00
|
|
|
// CraftBukkit end
|
2011-06-22 17:55:04 +02:00
|
|
|
|
|
|
|
public final class SpawnerCreature {
|
2012-02-10 06:43:12 +01:00
|
|
|
// CraftBukkit start
|
|
|
|
// private static HashMap b = new HashMap(); // Moved local to spawnEntities
|
2011-12-06 14:52:45 +01:00
|
|
|
static private class ChunkEntry extends EntryBase {
|
|
|
|
public boolean spawn;
|
2012-01-14 23:02:10 +01:00
|
|
|
|
|
|
|
public ChunkEntry(int x, int z, boolean spawn) {
|
2011-12-06 14:52:45 +01:00
|
|
|
super(LongHash.toLong(x, z));
|
|
|
|
this.spawn = spawn;
|
|
|
|
}
|
2012-01-14 23:02:10 +01:00
|
|
|
|
2011-12-06 14:52:45 +01:00
|
|
|
int getX() {
|
|
|
|
return LongHash.msw(key);
|
|
|
|
}
|
2012-01-14 23:02:10 +01:00
|
|
|
|
2011-12-06 14:52:45 +01:00
|
|
|
int getZ() {
|
|
|
|
return LongHash.lsw(key);
|
|
|
|
}
|
|
|
|
}
|
2012-02-10 06:43:12 +01:00
|
|
|
// CraftBukkit end
|
2011-12-06 14:52:45 +01:00
|
|
|
|
2011-06-22 17:55:04 +02:00
|
|
|
protected static final Class[] a = new Class[] { EntitySpider.class, EntityZombie.class, EntitySkeleton.class};
|
|
|
|
|
2012-01-14 21:03:48 +01:00
|
|
|
protected static ChunkPosition getRandomPosition(World world, int i, int j) {
|
2012-03-01 11:49:23 +01:00
|
|
|
Chunk chunk = world.getChunkAt(i, j);
|
|
|
|
int k = i * 16 + world.random.nextInt(16);
|
2012-07-29 09:33:13 +02:00
|
|
|
int l = j * 16 + world.random.nextInt(16);
|
|
|
|
int i1 = world.random.nextInt(chunk == null ? world.L() : chunk.h() + 16 - 1);
|
2011-06-22 17:55:04 +02:00
|
|
|
|
2012-07-29 09:33:13 +02:00
|
|
|
return new ChunkPosition(k, i1, l);
|
2011-06-22 17:55:04 +02:00
|
|
|
}
|
|
|
|
|
2012-07-29 09:33:13 +02:00
|
|
|
public static final int spawnEntities(WorldServer worldserver, boolean flag, boolean flag1) {
|
2011-06-22 17:55:04 +02:00
|
|
|
if (!flag && !flag1) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
2012-02-10 06:43:12 +01:00
|
|
|
// CraftBukkit start
|
|
|
|
// b.clear();
|
|
|
|
LongBaseHashtable chunkCoords = new LongBaseHashtable();
|
|
|
|
// CraftBukkit end
|
2011-06-22 17:55:04 +02:00
|
|
|
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
|
2012-07-29 09:33:13 +02:00
|
|
|
for (i = 0; i < worldserver.players.size(); ++i) {
|
|
|
|
EntityHuman entityhuman = (EntityHuman) worldserver.players.get(i);
|
2011-06-22 17:55:04 +02:00
|
|
|
int k = MathHelper.floor(entityhuman.locX / 16.0D);
|
|
|
|
|
|
|
|
j = MathHelper.floor(entityhuman.locZ / 16.0D);
|
|
|
|
byte b0 = 8;
|
|
|
|
|
|
|
|
for (int l = -b0; l <= b0; ++l) {
|
|
|
|
for (int i1 = -b0; i1 <= b0; ++i1) {
|
2011-11-20 09:01:14 +01:00
|
|
|
boolean flag2 = l == -b0 || l == b0 || i1 == -b0 || i1 == b0;
|
2011-12-06 14:52:45 +01:00
|
|
|
// CraftBukkit start
|
|
|
|
long chunkCoord = LongHash.toLong(l + k, i1 + j);
|
2011-11-20 09:01:14 +01:00
|
|
|
|
|
|
|
if (!flag2) {
|
2011-12-06 14:52:45 +01:00
|
|
|
chunkCoords.put(new ChunkEntry(l + k, i1 + j, false));
|
|
|
|
} else if (!chunkCoords.containsKey(chunkCoord)) {
|
|
|
|
chunkCoords.put(new ChunkEntry(l + k, i1 + j, true));
|
2011-11-20 09:01:14 +01:00
|
|
|
}
|
2011-12-06 14:52:45 +01:00
|
|
|
// CraftBukkit end
|
2011-06-22 17:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
2012-07-29 09:33:13 +02:00
|
|
|
ChunkCoordinates chunkcoordinates = worldserver.getSpawn();
|
2012-07-22 08:18:00 +02:00
|
|
|
java.util.ArrayList<EntryBase> b = chunkCoords.entries(); // CraftBukkit
|
2011-06-22 17:55:04 +02:00
|
|
|
EnumCreatureType[] aenumcreaturetype = EnumCreatureType.values();
|
|
|
|
|
|
|
|
j = aenumcreaturetype.length;
|
|
|
|
|
|
|
|
for (int j1 = 0; j1 < j; ++j1) {
|
|
|
|
EnumCreatureType enumcreaturetype = aenumcreaturetype[j1];
|
|
|
|
|
2012-04-24 02:01:22 +02:00
|
|
|
// CraftBukkit start - use per-world spawn limits
|
|
|
|
int limit = 0;
|
2012-04-25 01:59:55 +02:00
|
|
|
switch (enumcreaturetype) {
|
|
|
|
case MONSTER:
|
2012-07-29 09:33:13 +02:00
|
|
|
limit = worldserver.getWorld().getMonsterSpawnLimit();
|
2012-04-25 01:59:55 +02:00
|
|
|
break;
|
|
|
|
case CREATURE:
|
2012-07-29 09:33:13 +02:00
|
|
|
limit = worldserver.getWorld().getAnimalSpawnLimit();
|
2012-04-25 01:59:55 +02:00
|
|
|
break;
|
|
|
|
case WATER_CREATURE:
|
2012-07-29 09:33:13 +02:00
|
|
|
limit = worldserver.getWorld().getWaterAnimalSpawnLimit();
|
2012-04-25 01:59:55 +02:00
|
|
|
break;
|
2012-04-24 02:01:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (limit == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// CraftBukkit end
|
|
|
|
|
2012-07-29 09:33:13 +02:00
|
|
|
if ((!enumcreaturetype.d() || flag1) && (enumcreaturetype.d() || flag) && worldserver.a(enumcreaturetype.a()) <= limit * b.size() / 256) { // CraftBukkit - use per-world limits
|
2011-06-22 17:55:04 +02:00
|
|
|
|
2011-12-07 01:21:10 +01:00
|
|
|
// CraftBukkit start
|
2011-12-06 14:52:45 +01:00
|
|
|
label108:
|
2011-12-07 01:21:10 +01:00
|
|
|
for (EntryBase base : b) {
|
2011-12-06 14:52:45 +01:00
|
|
|
ChunkEntry entry = (SpawnerCreature.ChunkEntry) base;
|
|
|
|
if (!entry.spawn) {
|
2012-07-29 09:33:13 +02:00
|
|
|
ChunkPosition chunkposition = getRandomPosition(worldserver, entry.getX(), entry.getZ());
|
2011-12-07 01:21:10 +01:00
|
|
|
// CraftBukkit end
|
2011-09-15 02:23:52 +02:00
|
|
|
int k1 = chunkposition.x;
|
|
|
|
int l1 = chunkposition.y;
|
|
|
|
int i2 = chunkposition.z;
|
2011-06-22 17:55:04 +02:00
|
|
|
|
2012-07-29 09:33:13 +02:00
|
|
|
if (!worldserver.s(k1, l1, i2) && worldserver.getMaterial(k1, l1, i2) == enumcreaturetype.c()) {
|
2011-09-15 02:23:52 +02:00
|
|
|
int j2 = 0;
|
2011-11-20 09:01:14 +01:00
|
|
|
int k2 = 0;
|
2011-06-22 17:55:04 +02:00
|
|
|
|
2011-11-20 09:01:14 +01:00
|
|
|
while (k2 < 3) {
|
2011-09-15 02:23:52 +02:00
|
|
|
int l2 = k1;
|
|
|
|
int i3 = l1;
|
2011-06-22 17:55:04 +02:00
|
|
|
int j3 = i2;
|
|
|
|
byte b1 = 6;
|
2011-11-20 09:01:14 +01:00
|
|
|
BiomeMeta biomemeta = null;
|
|
|
|
int k3 = 0;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
if (k3 < 4) {
|
|
|
|
label101: {
|
2012-07-29 09:33:13 +02:00
|
|
|
l2 += worldserver.random.nextInt(b1) - worldserver.random.nextInt(b1);
|
|
|
|
i3 += worldserver.random.nextInt(1) - worldserver.random.nextInt(1);
|
|
|
|
j3 += worldserver.random.nextInt(b1) - worldserver.random.nextInt(b1);
|
|
|
|
if (a(enumcreaturetype, worldserver, l2, i3, j3)) {
|
2011-11-20 09:01:14 +01:00
|
|
|
float f = (float) l2 + 0.5F;
|
|
|
|
float f1 = (float) i3;
|
|
|
|
float f2 = (float) j3 + 0.5F;
|
|
|
|
|
2012-07-29 09:33:13 +02:00
|
|
|
if (worldserver.findNearbyPlayer((double) f, (double) f1, (double) f2, 24.0D) == null) {
|
2011-11-20 09:01:14 +01:00
|
|
|
float f3 = f - (float) chunkcoordinates.x;
|
|
|
|
float f4 = f1 - (float) chunkcoordinates.y;
|
|
|
|
float f5 = f2 - (float) chunkcoordinates.z;
|
|
|
|
float f6 = f3 * f3 + f4 * f4 + f5 * f5;
|
|
|
|
|
|
|
|
if (f6 >= 576.0F) {
|
|
|
|
if (biomemeta == null) {
|
2012-07-29 09:33:13 +02:00
|
|
|
biomemeta = worldserver.a(enumcreaturetype, l2, i3, j3);
|
2011-11-20 09:01:14 +01:00
|
|
|
if (biomemeta == null) {
|
|
|
|
break label101;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EntityLiving entityliving;
|
|
|
|
|
|
|
|
try {
|
2012-07-29 09:33:13 +02:00
|
|
|
entityliving = (EntityLiving) biomemeta.b.getConstructor(new Class[] { World.class}).newInstance(new Object[] { worldserver});
|
2011-11-20 09:01:14 +01:00
|
|
|
} catch (Exception exception) {
|
|
|
|
exception.printStackTrace();
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2012-07-29 09:33:13 +02:00
|
|
|
entityliving.setPositionRotation((double) f, (double) f1, (double) f2, worldserver.random.nextFloat() * 360.0F, 0.0F);
|
2012-01-14 21:03:48 +01:00
|
|
|
if (entityliving.canSpawn()) {
|
2011-11-20 09:01:14 +01:00
|
|
|
++j2;
|
|
|
|
// CraftBukkit - added a reason for spawning this creature
|
2012-07-29 09:33:13 +02:00
|
|
|
worldserver.addEntity(entityliving, SpawnReason.NATURAL);
|
|
|
|
a(entityliving, worldserver, f, f1, f2);
|
|
|
|
if (j2 >= entityliving.bl()) {
|
2011-11-20 09:01:14 +01:00
|
|
|
continue label108;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
i += j2;
|
2011-06-22 17:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-11-20 09:01:14 +01:00
|
|
|
|
|
|
|
++k3;
|
|
|
|
continue;
|
2011-06-22 17:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
2011-11-20 09:01:14 +01:00
|
|
|
|
|
|
|
++k2;
|
|
|
|
break;
|
2011-06-22 17:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-01 11:49:23 +01:00
|
|
|
public static boolean a(EnumCreatureType enumcreaturetype, World world, int i, int j, int k) {
|
|
|
|
if (enumcreaturetype.c() == Material.WATER) {
|
2012-07-29 09:33:13 +02:00
|
|
|
return world.getMaterial(i, j, k).isLiquid() && !world.s(i, j + 1, k);
|
|
|
|
} else if (!world.t(i, j - 1, k)) {
|
|
|
|
return false;
|
2012-03-01 11:49:23 +01:00
|
|
|
} else {
|
|
|
|
int l = world.getTypeId(i, j - 1, k);
|
|
|
|
|
2012-07-29 09:33:13 +02:00
|
|
|
return l != Block.BEDROCK.id && !world.s(i, j, k) && !world.getMaterial(i, j, k).isLiquid() && !world.s(i, j + 1, k);
|
2012-03-01 11:49:23 +01:00
|
|
|
}
|
2011-06-22 17:55:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private static void a(EntityLiving entityliving, World world, float f, float f1, float f2) {
|
2012-04-04 01:00:07 +02:00
|
|
|
if (entityliving.dead) return; // CraftBukkit
|
2011-06-22 17:55:04 +02:00
|
|
|
if (entityliving instanceof EntitySpider && world.random.nextInt(100) == 0) {
|
|
|
|
EntitySkeleton entityskeleton = new EntitySkeleton(world);
|
|
|
|
|
|
|
|
entityskeleton.setPositionRotation((double) f, (double) f1, (double) f2, entityliving.yaw, 0.0F);
|
|
|
|
// CraftBukkit - added a reason for spawning this creature
|
2012-02-10 06:48:45 +01:00
|
|
|
world.addEntity(entityskeleton, SpawnReason.JOCKEY);
|
2011-06-22 17:55:04 +02:00
|
|
|
entityskeleton.mount(entityliving);
|
|
|
|
} else if (entityliving instanceof EntitySheep) {
|
|
|
|
((EntitySheep) entityliving).setColor(EntitySheep.a(world.random));
|
2012-03-01 11:49:23 +01:00
|
|
|
} else if (entityliving instanceof EntityOcelot && world.random.nextInt(7) == 0) {
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
|
|
|
EntityOcelot entityocelot = new EntityOcelot(world);
|
|
|
|
|
|
|
|
entityocelot.setPositionRotation((double) f, (double) f1, (double) f2, entityliving.yaw, 0.0F);
|
|
|
|
entityocelot.setAge(-24000);
|
2012-07-29 09:33:13 +02:00
|
|
|
world.addEntity(entityocelot, SpawnReason.NATURAL); // CraftBukkit - added SpawnReason
|
2012-03-01 11:49:23 +01:00
|
|
|
}
|
2011-06-22 17:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-15 02:23:52 +02:00
|
|
|
public static void a(World world, BiomeBase biomebase, int i, int j, int k, int l, Random random) {
|
2012-01-12 16:27:39 +01:00
|
|
|
List list = biomebase.getMobs(EnumCreatureType.CREATURE);
|
2011-09-15 02:23:52 +02:00
|
|
|
|
|
|
|
if (!list.isEmpty()) {
|
2012-03-22 21:39:39 +01:00
|
|
|
while (random.nextFloat() < biomebase.f()) {
|
2011-09-15 02:23:52 +02:00
|
|
|
BiomeMeta biomemeta = (BiomeMeta) WeightedRandom.a(world.random, (Collection) list);
|
2012-07-29 09:33:13 +02:00
|
|
|
int i1 = biomemeta.c + random.nextInt(1 + biomemeta.d - biomemeta.c);
|
2011-09-15 02:23:52 +02:00
|
|
|
int j1 = i + random.nextInt(k);
|
|
|
|
int k1 = j + random.nextInt(l);
|
|
|
|
int l1 = j1;
|
|
|
|
int i2 = k1;
|
|
|
|
|
|
|
|
for (int j2 = 0; j2 < i1; ++j2) {
|
|
|
|
boolean flag = false;
|
|
|
|
|
|
|
|
for (int k2 = 0; !flag && k2 < 4; ++k2) {
|
2012-07-29 09:33:13 +02:00
|
|
|
int l2 = world.h(j1, k1);
|
2011-09-15 02:23:52 +02:00
|
|
|
|
|
|
|
if (a(EnumCreatureType.CREATURE, world, j1, l2, k1)) {
|
|
|
|
float f = (float) j1 + 0.5F;
|
|
|
|
float f1 = (float) l2;
|
|
|
|
float f2 = (float) k1 + 0.5F;
|
|
|
|
|
|
|
|
EntityLiving entityliving;
|
|
|
|
|
|
|
|
try {
|
2012-07-29 09:33:13 +02:00
|
|
|
entityliving = (EntityLiving) biomemeta.b.getConstructor(new Class[] { World.class}).newInstance(new Object[] { world});
|
2011-09-15 02:23:52 +02:00
|
|
|
} catch (Exception exception) {
|
|
|
|
exception.printStackTrace();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
entityliving.setPositionRotation((double) f, (double) f1, (double) f2, random.nextFloat() * 360.0F, 0.0F);
|
|
|
|
// CraftBukkit - added a reason for spawning this creature
|
2012-02-10 06:48:45 +01:00
|
|
|
world.addEntity(entityliving, SpawnReason.CHUNK_GEN);
|
2011-09-15 02:23:52 +02:00
|
|
|
a(entityliving, world, f, f1, f2);
|
|
|
|
flag = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
j1 += random.nextInt(5) - random.nextInt(5);
|
|
|
|
|
|
|
|
for (k1 += random.nextInt(5) - random.nextInt(5); j1 < i || j1 >= i + k || k1 < j || k1 >= j + k; k1 = i2 + random.nextInt(5) - random.nextInt(5)) {
|
|
|
|
j1 = l1 + random.nextInt(5) - random.nextInt(5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|