package net.minecraft.world;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.MathHelper;
import net.minecraft.util.WeightedRandom;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.chunk.Chunk;
import cpw.mods.fml.common.eventhandler.Event.Result;
import net.minecraftforge.event.ForgeEventFactory;
public final class SpawnerAnimals
{
/** The 17x17 area around the player where mobs can spawn */
private HashMap eligibleChunksForSpawning = new HashMap();
private static final String __OBFID = "CL_00000152";
protected static ChunkPosition func_151350_a(World p_151350_0_, int p_151350_1_, int p_151350_2_)
{
Chunk chunk = p_151350_0_.getChunkFromChunkCoords(p_151350_1_, p_151350_2_);
int k = p_151350_1_ * 16 + p_151350_0_.rand.nextInt(16);
int l = p_151350_2_ * 16 + p_151350_0_.rand.nextInt(16);
int i1 = p_151350_0_.rand.nextInt(chunk == null ? p_151350_0_.getActualHeight() : chunk.getTopFilledSegment() + 16 - 1);
return new ChunkPosition(k, i1, l);
}
/**
* adds all chunks within the spawn radius of the players to eligibleChunksForSpawning. pars: the world,
* hostileCreatures, passiveCreatures. returns number of eligible chunks.
*/
public int findChunksForSpawning(WorldServer p_77192_1_, boolean p_77192_2_, boolean p_77192_3_, boolean p_77192_4_)
{
if (!p_77192_2_ && !p_77192_3_)
{
return 0;
}
else
{
this.eligibleChunksForSpawning.clear();
int i;
int k;
for (i = 0; i < p_77192_1_.playerEntities.size(); ++i)
{
EntityPlayer entityplayer = (EntityPlayer)p_77192_1_.playerEntities.get(i);
int j = MathHelper.floor_double(entityplayer.posX / 16.0D);
k = MathHelper.floor_double(entityplayer.posZ / 16.0D);
byte b0 = 8;
for (int l = -b0; l <= b0; ++l)
{
for (int i1 = -b0; i1 <= b0; ++i1)
{
boolean flag3 = l == -b0 || l == b0 || i1 == -b0 || i1 == b0;
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(l + j, i1 + k);
if (!flag3)
{
this.eligibleChunksForSpawning.put(chunkcoordintpair, Boolean.valueOf(false));
}
else if (!this.eligibleChunksForSpawning.containsKey(chunkcoordintpair))
{
this.eligibleChunksForSpawning.put(chunkcoordintpair, Boolean.valueOf(true));
}
}
}
}
i = 0;
ChunkCoordinates chunkcoordinates = p_77192_1_.getSpawnPoint();
EnumCreatureType[] aenumcreaturetype = EnumCreatureType.values();
k = aenumcreaturetype.length;
for (int k3 = 0; k3 < k; ++k3)
{
EnumCreatureType enumcreaturetype = aenumcreaturetype[k3];
if ((!enumcreaturetype.getPeacefulCreature() || p_77192_3_) && (enumcreaturetype.getPeacefulCreature() || p_77192_2_) && (!enumcreaturetype.getAnimal() || p_77192_4_) && p_77192_1_.countEntities(enumcreaturetype, true) <= enumcreaturetype.getMaxNumberOfCreature() * this.eligibleChunksForSpawning.size() / 256)
{
Iterator iterator = this.eligibleChunksForSpawning.keySet().iterator();
ArrayList<ChunkCoordIntPair> tmp = new ArrayList(eligibleChunksForSpawning.keySet());
Collections.shuffle(tmp);
iterator = tmp.iterator();
label110:
while (iterator.hasNext())
{
ChunkCoordIntPair chunkcoordintpair1 = (ChunkCoordIntPair)iterator.next();
if (!((Boolean)this.eligibleChunksForSpawning.get(chunkcoordintpair1)).booleanValue())
{
ChunkPosition chunkposition = func_151350_a(p_77192_1_, chunkcoordintpair1.chunkXPos, chunkcoordintpair1.chunkZPos);
int j1 = chunkposition.chunkPosX;
int k1 = chunkposition.chunkPosY;
int l1 = chunkposition.chunkPosZ;
if (!p_77192_1_.getBlock(j1, k1, l1).isNormalCube() && p_77192_1_.getBlock(j1, k1, l1).getMaterial() == enumcreaturetype.getCreatureMaterial())
{
int i2 = 0;
int j2 = 0;
while (j2 < 3)
{
int k2 = j1;
int l2 = k1;
int i3 = l1;
byte b1 = 6;
BiomeGenBase.SpawnListEntry spawnlistentry = null;
IEntityLivingData ientitylivingdata = null;
int j3 = 0;
while (true)
{
if (j3 < 4)
{
label103:
{
k2 += p_77192_1_.rand.nextInt(b1) - p_77192_1_.rand.nextInt(b1);
l2 += p_77192_1_.rand.nextInt(1) - p_77192_1_.rand.nextInt(1);
i3 += p_77192_1_.rand.nextInt(b1) - p_77192_1_.rand.nextInt(b1);
if (canCreatureTypeSpawnAtLocation(enumcreaturetype, p_77192_1_, k2, l2, i3))
{
float f = (float)k2 + 0.5F;
float f1 = (float)l2;
float f2 = (float)i3 + 0.5F;
if (p_77192_1_.getClosestPlayer((double)f, (double)f1, (double)f2, 24.0D) == null)
{
float f3 = f - (float)chunkcoordinates.posX;
float f4 = f1 - (float)chunkcoordinates.posY;
float f5 = f2 - (float)chunkcoordinates.posZ;
float f6 = f3 * f3 + f4 * f4 + f5 * f5;
if (f6 >= 576.0F)
{
if (spawnlistentry == null)
{
spawnlistentry = p_77192_1_.spawnRandomCreature(enumcreaturetype, k2, l2, i3);
if (spawnlistentry == null)
{
break label103;
}
}
EntityLiving entityliving;
try
{
entityliving = (EntityLiving)spawnlistentry.entityClass.getConstructor(new Class[] {World.class}).newInstance(new Object[] {p_77192_1_});
}
catch (Exception exception)
{
exception.printStackTrace();
return i;
}
entityliving.setLocationAndAngles((double)f, (double)f1, (double)f2, p_77192_1_.rand.nextFloat() * 360.0F, 0.0F);
Result canSpawn = ForgeEventFactory.canEntitySpawn(entityliving, p_77192_1_, f, f1, f2);
if (canSpawn == Result.ALLOW || (canSpawn == Result.DEFAULT && entityliving.getCanSpawnHere()))
{
++i2;
p_77192_1_.spawnEntityInWorld(entityliving);
if (!ForgeEventFactory.doSpecialSpawn(entityliving, p_77192_1_, f, f1, f2))
{
ientitylivingdata = entityliving.onSpawnWithEgg(ientitylivingdata);
}
if (j2 >= ForgeEventFactory.getMaxSpawnPackSize(entityliving))
{
continue label110;
}
}
i += i2;
}
}
}
++j3;
continue;
}
}
++j2;
break;
}
}
}
}
}
}
}
return i;
}
}
/**
* Returns whether or not the specified creature type can spawn at the specified location.
*/
public static boolean canCreatureTypeSpawnAtLocation(EnumCreatureType p_77190_0_, World p_77190_1_, int p_77190_2_, int p_77190_3_, int p_77190_4_)
{
if (p_77190_0_.getCreatureMaterial() == Material.water)
{
return p_77190_1_.getBlock(p_77190_2_, p_77190_3_, p_77190_4_).getMaterial().isLiquid() && p_77190_1_.getBlock(p_77190_2_, p_77190_3_ - 1, p_77190_4_).getMaterial().isLiquid() && !p_77190_1_.getBlock(p_77190_2_, p_77190_3_ + 1, p_77190_4_).isNormalCube();
}
else if (!World.doesBlockHaveSolidTopSurface(p_77190_1_, p_77190_2_, p_77190_3_ - 1, p_77190_4_))
{
return false;
}
else
{
Block block = p_77190_1_.getBlock(p_77190_2_, p_77190_3_ - 1, p_77190_4_);
boolean spawnBlock = block.canCreatureSpawn(p_77190_0_, p_77190_1_, p_77190_2_, p_77190_3_ - 1, p_77190_4_);
return spawnBlock && block != Blocks.bedrock && !p_77190_1_.getBlock(p_77190_2_, p_77190_3_, p_77190_4_).isNormalCube() && !p_77190_1_.getBlock(p_77190_2_, p_77190_3_, p_77190_4_).getMaterial().isLiquid() && !p_77190_1_.getBlock(p_77190_2_, p_77190_3_ + 1, p_77190_4_).isNormalCube();
}
}
/**
* Called during chunk generation to spawn initial creatures.
*/
public static void performWorldGenSpawning(World p_77191_0_, BiomeGenBase p_77191_1_, int p_77191_2_, int p_77191_3_, int p_77191_4_, int p_77191_5_, Random p_77191_6_)
{
List list = p_77191_1_.getSpawnableList(EnumCreatureType.creature);
if (!list.isEmpty())
{
while (p_77191_6_.nextFloat() < p_77191_1_.getSpawningChance())
{
BiomeGenBase.SpawnListEntry spawnlistentry = (BiomeGenBase.SpawnListEntry)WeightedRandom.getRandomItem(p_77191_0_.rand, list);
IEntityLivingData ientitylivingdata = null;
int i1 = spawnlistentry.minGroupCount + p_77191_6_.nextInt(1 + spawnlistentry.maxGroupCount - spawnlistentry.minGroupCount);
int j1 = p_77191_2_ + p_77191_6_.nextInt(p_77191_4_);
int k1 = p_77191_3_ + p_77191_6_.nextInt(p_77191_5_);
int l1 = j1;
int i2 = k1;
for (int j2 = 0; j2 < i1; ++j2)
{
boolean flag = false;
for (int k2 = 0; !flag && k2 < 4; ++k2)
{
int l2 = p_77191_0_.getTopSolidOrLiquidBlock(j1, k1);
if (canCreatureTypeSpawnAtLocation(EnumCreatureType.creature, p_77191_0_, j1, l2, k1))
{
float f = (float)j1 + 0.5F;
float f1 = (float)l2;
float f2 = (float)k1 + 0.5F;
EntityLiving entityliving;
try
{
entityliving = (EntityLiving)spawnlistentry.entityClass.getConstructor(new Class[] {World.class}).newInstance(new Object[] {p_77191_0_});
}
catch (Exception exception)
{
exception.printStackTrace();
continue;
}
entityliving.setLocationAndAngles((double)f, (double)f1, (double)f2, p_77191_6_.nextFloat() * 360.0F, 0.0F);
p_77191_0_.spawnEntityInWorld(entityliving);
ientitylivingdata = entityliving.onSpawnWithEgg(ientitylivingdata);
flag = true;
}
j1 += p_77191_6_.nextInt(5) - p_77191_6_.nextInt(5);
for (k1 += p_77191_6_.nextInt(5) - p_77191_6_.nextInt(5); j1 < p_77191_2_ || j1 >= p_77191_2_ + p_77191_4_ || k1 < p_77191_3_ || k1 >= p_77191_3_ + p_77191_4_; k1 = i2 + p_77191_6_.nextInt(5) - p_77191_6_.nextInt(5))
{
j1 = l1 + p_77191_6_.nextInt(5) - p_77191_6_.nextInt(5);
}
}
}
}
}
}
}