package net.minecraft.tileentity;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.Packet132TileEntityData;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.WeightedRandom;
import net.minecraft.world.World;
public class TileEntityMobSpawner extends TileEntity
{
/** The stored delay before a new spawn. */
public int delay = -1;
/**
* The string ID of the mobs being spawned from this spawner. Defaults to pig, apparently.
*/
private String mobID = "Pig";
private List field_92016_e = null;
/** The extra NBT data to add to spawned entities */
private TileEntityMobSpawnerSpawnData spawnerTags = null;
public double yaw;
public double yaw2 = 0.0D;
private int minSpawnDelay = 200;
private int maxSpawnDelay = 800;
private int spawnCount = 4;
private Entity field_92017_j;
/** Maximum number of entities for limiting mob spawning */
private int maxNearbyEntities = 6;
/** Required player range for mob spawning to occur */
private int requiredPlayerRange = 16;
/** Range for spawning new entities with mob spawners */
private int spawnRange = 4;
public TileEntityMobSpawner()
{
this.delay = 20;
}
public String func_92015_a()
{
return this.spawnerTags == null ? this.mobID : this.spawnerTags.field_92033_c;
}
public void setMobID(String par1Str)
{
this.mobID = par1Str;
}
/**
* Returns true if there is a player in range (using World.getClosestPlayer)
*/
public boolean anyPlayerInRange()
{
return this.worldObj.getClosestPlayer((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D, (double)this.requiredPlayerRange) != null;
}
/**
* Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
* ticks and creates a new spawn inside its implementation.
*/
public void updateEntity()
{
if (this.anyPlayerInRange())
{
double var5;
if (this.worldObj.isRemote)
{
double var1 = (double)((float)this.xCoord + this.worldObj.rand.nextFloat());
double var3 = (double)((float)this.yCoord + this.worldObj.rand.nextFloat());
var5 = (double)((float)this.zCoord + this.worldObj.rand.nextFloat());
this.worldObj.spawnParticle("smoke", var1, var3, var5, 0.0D, 0.0D, 0.0D);
this.worldObj.spawnParticle("flame", var1, var3, var5, 0.0D, 0.0D, 0.0D);
if (this.delay > 0)
{
--this.delay;
}
this.yaw2 = this.yaw;
this.yaw = (this.yaw + (double)(1000.0F / ((float)this.delay + 200.0F))) % 360.0D;
}
else
{
if (this.delay == -1)
{
this.updateDelay();
}
if (this.delay > 0)
{
--this.delay;
return;
}
boolean var12 = false;
for (int var2 = 0; var2 < this.spawnCount; ++var2)
{
Entity var13 = EntityList.createEntityByName(this.func_92015_a(), this.worldObj);
if (var13 == null)
{
return;
}
int var4 = this.worldObj.getEntitiesWithinAABB(var13.getClass(), AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)this.xCoord, (double)this.yCoord, (double)this.zCoord, (double)(this.xCoord + 1), (double)(this.yCoord + 1), (double)(this.zCoord + 1)).expand((double)(this.spawnRange * 2), 4.0D, (double)(this.spawnRange * 2))).size();
if (var4 >= this.maxNearbyEntities)
{
this.updateDelay();
return;
}
if (var13 != null)
{
var5 = (double)this.xCoord + (this.worldObj.rand.nextDouble() - this.worldObj.rand.nextDouble()) * (double)this.spawnRange;
double var7 = (double)(this.yCoord + this.worldObj.rand.nextInt(3) - 1);
double var9 = (double)this.zCoord + (this.worldObj.rand.nextDouble() - this.worldObj.rand.nextDouble()) * (double)this.spawnRange;
EntityLiving var11 = var13 instanceof EntityLiving ? (EntityLiving)var13 : null;
var13.setLocationAndAngles(var5, var7, var9, this.worldObj.rand.nextFloat() * 360.0F, 0.0F);
if (var11 == null || var11.getCanSpawnHere())
{
this.writeNBTTagsTo(var13);
this.worldObj.spawnEntityInWorld(var13);
this.worldObj.playAuxSFX(2004, this.xCoord, this.yCoord, this.zCoord, 0);
if (var11 != null)
{
var11.spawnExplosionParticle();
}
var12 = true;
}
}
}
if (var12)
{
this.updateDelay();
}
}
super.updateEntity();
}
}
public void writeNBTTagsTo(Entity par1Entity)
{
if (this.spawnerTags != null)
{
NBTTagCompound var2 = new NBTTagCompound();
par1Entity.addEntityID(var2);
Iterator var3 = this.spawnerTags.field_92032_b.getTags().iterator();
while (var3.hasNext())
{
NBTBase var4 = (NBTBase)var3.next();
var2.setTag(var4.getName(), var4.copy());
}
par1Entity.readFromNBT(var2);
}
else if (par1Entity instanceof EntityLiving && par1Entity.worldObj != null)
{
((EntityLiving)par1Entity).initCreature();
}
}
/**
* Sets the delay before a new spawn (base delay of 200 + random number up to 600).
*/
private void updateDelay()
{
if (this.maxSpawnDelay <= this.minSpawnDelay)
{
this.delay = this.minSpawnDelay;
}
else
{
this.delay = this.minSpawnDelay + this.worldObj.rand.nextInt(this.maxSpawnDelay - this.minSpawnDelay);
}
if (this.field_92016_e != null && this.field_92016_e.size() > 0)
{
this.spawnerTags = (TileEntityMobSpawnerSpawnData)WeightedRandom.getRandomItem(this.worldObj.rand, this.field_92016_e);
this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord);
}
this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType().blockID, 1, 0);
}
/**
* Reads a tile entity from NBT.
*/
public void readFromNBT(NBTTagCompound par1NBTTagCompound)
{
super.readFromNBT(par1NBTTagCompound);
this.mobID = par1NBTTagCompound.getString("EntityId");
this.delay = par1NBTTagCompound.getShort("Delay");
if (par1NBTTagCompound.hasKey("SpawnPotentials"))
{
this.field_92016_e = new ArrayList();
NBTTagList var2 = par1NBTTagCompound.getTagList("SpawnPotentials");
for (int var3 = 0; var3 < var2.tagCount(); ++var3)
{
this.field_92016_e.add(new TileEntityMobSpawnerSpawnData(this, (NBTTagCompound)var2.tagAt(var3)));
}
}
else
{
this.field_92016_e = null;
}
if (par1NBTTagCompound.hasKey("SpawnData"))
{
this.spawnerTags = new TileEntityMobSpawnerSpawnData(this, par1NBTTagCompound.getCompoundTag("SpawnData"), this.mobID);
}
else
{
this.spawnerTags = null;
}
if (par1NBTTagCompound.hasKey("MinSpawnDelay"))
{
this.minSpawnDelay = par1NBTTagCompound.getShort("MinSpawnDelay");
this.maxSpawnDelay = par1NBTTagCompound.getShort("MaxSpawnDelay");
this.spawnCount = par1NBTTagCompound.getShort("SpawnCount");
}
if (par1NBTTagCompound.hasKey("MaxNearbyEntities"))
{
this.maxNearbyEntities = par1NBTTagCompound.getShort("MaxNearbyEntities");
this.requiredPlayerRange = par1NBTTagCompound.getShort("RequiredPlayerRange");
}
if (par1NBTTagCompound.hasKey("SpawnRange"))
{
this.spawnRange = par1NBTTagCompound.getShort("SpawnRange");
}
if (this.worldObj != null && this.worldObj.isRemote)
{
this.field_92017_j = null;
}
}
/**
* Writes a tile entity to NBT.
*/
public void writeToNBT(NBTTagCompound par1NBTTagCompound)
{
super.writeToNBT(par1NBTTagCompound);
par1NBTTagCompound.setString("EntityId", this.func_92015_a());
par1NBTTagCompound.setShort("Delay", (short)this.delay);
par1NBTTagCompound.setShort("MinSpawnDelay", (short)this.minSpawnDelay);
par1NBTTagCompound.setShort("MaxSpawnDelay", (short)this.maxSpawnDelay);
par1NBTTagCompound.setShort("SpawnCount", (short)this.spawnCount);
par1NBTTagCompound.setShort("MaxNearbyEntities", (short)this.maxNearbyEntities);
par1NBTTagCompound.setShort("RequiredPlayerRange", (short)this.requiredPlayerRange);
par1NBTTagCompound.setShort("SpawnRange", (short)this.spawnRange);
if (this.spawnerTags != null)
{
par1NBTTagCompound.setCompoundTag("SpawnData", (NBTTagCompound)this.spawnerTags.field_92032_b.copy());
}
if (this.spawnerTags != null || this.field_92016_e != null && this.field_92016_e.size() > 0)
{
NBTTagList var2 = new NBTTagList();
if (this.field_92016_e != null && this.field_92016_e.size() > 0)
{
Iterator var3 = this.field_92016_e.iterator();
while (var3.hasNext())
{
TileEntityMobSpawnerSpawnData var4 = (TileEntityMobSpawnerSpawnData)var3.next();
var2.appendTag(var4.func_92030_a());
}
}
else
{
var2.appendTag(this.spawnerTags.func_92030_a());
}
par1NBTTagCompound.setTag("SpawnPotentials", var2);
}
}
@SideOnly(Side.CLIENT)
/**
* will create the entity from the internalID the first time it is accessed
*/
public Entity getMobEntity()
{
if (this.field_92017_j == null)
{
Entity var1 = EntityList.createEntityByName(this.func_92015_a(), (World)null);
this.writeNBTTagsTo(var1);
this.field_92017_j = var1;
}
return this.field_92017_j;
}
/**
* Overriden in a sign to provide the text.
*/
public Packet getDescriptionPacket()
{
NBTTagCompound var1 = new NBTTagCompound();
this.writeToNBT(var1);
var1.removeTag("SpawnPotentials");
return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, var1);
}
/**
* Called when a client event is received with the event number and argument, see World.sendClientEvent
*/
public void receiveClientEvent(int par1, int par2)
{
if (par1 == 1 && this.worldObj.isRemote)
{
this.delay = this.minSpawnDelay;
}
}
}