package net.minecraft.entity.passive;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.List;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.stats.AchievementList;
import net.minecraft.stats.StatList;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public abstract class EntityAnimal extends EntityAgeable implements IAnimals
{
private int inLove;
/**
* This is representation of a counter for reproduction progress. (Note that this is different from the inLove which
* represent being in Love-Mode)
*/
private int breeding;
private EntityPlayer playerInLove;
private static final String __OBFID = "CL_00001638";
public EntityAnimal(World p_i1681_1_)
{
super(p_i1681_1_);
}
/**
* main AI tick function, replaces updateEntityActionState
*/
protected void updateAITick()
{
if (this.getGrowingAge() != 0)
{
this.inLove = 0;
}
super.updateAITick();
}
/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
public void onLivingUpdate()
{
super.onLivingUpdate();
if (this.getGrowingAge() != 0)
{
this.inLove = 0;
}
if (this.inLove > 0)
{
--this.inLove;
String s = "heart";
if (this.inLove % 10 == 0)
{
double d0 = this.rand.nextGaussian() * 0.02D;
double d1 = this.rand.nextGaussian() * 0.02D;
double d2 = this.rand.nextGaussian() * 0.02D;
this.worldObj.spawnParticle(s, this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + 0.5D + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, d0, d1, d2);
}
}
else
{
this.breeding = 0;
}
}
/**
* Basic mob attack. Default to touch of death in EntityCreature. Overridden by each mob to define their attack.
*/
protected void attackEntity(Entity p_70785_1_, float p_70785_2_)
{
if (p_70785_1_ instanceof EntityPlayer)
{
if (p_70785_2_ < 3.0F)
{
double d0 = p_70785_1_.posX - this.posX;
double d1 = p_70785_1_.posZ - this.posZ;
this.rotationYaw = (float)(Math.atan2(d1, d0) * 180.0D / Math.PI) - 90.0F;
this.hasAttacked = true;
}
EntityPlayer entityplayer = (EntityPlayer)p_70785_1_;
if (entityplayer.getCurrentEquippedItem() == null || !this.isBreedingItem(entityplayer.getCurrentEquippedItem()))
{
this.entityToAttack = null;
}
}
else if (p_70785_1_ instanceof EntityAnimal)
{
EntityAnimal entityanimal = (EntityAnimal)p_70785_1_;
if (this.getGrowingAge() > 0 && entityanimal.getGrowingAge() < 0)
{
if ((double)p_70785_2_ < 2.5D)
{
this.hasAttacked = true;
}
}
else if (this.inLove > 0 && entityanimal.inLove > 0)
{
if (entityanimal.entityToAttack == null)
{
entityanimal.entityToAttack = this;
}
if (entityanimal.entityToAttack == this && (double)p_70785_2_ < 3.5D)
{
++entityanimal.inLove;
++this.inLove;
++this.breeding;
if (this.breeding % 4 == 0)
{
this.worldObj.spawnParticle("heart", this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + 0.5D + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, 0.0D, 0.0D, 0.0D);
}
if (this.breeding == 60)
{
this.procreate((EntityAnimal)p_70785_1_);
}
}
else
{
this.breeding = 0;
}
}
else
{
this.breeding = 0;
this.entityToAttack = null;
}
}
}
/**
* Creates a baby animal according to the animal type of the target at the actual position and spawns 'love'
* particles.
*/
private void procreate(EntityAnimal p_70876_1_)
{
EntityAgeable entityageable = this.createChild(p_70876_1_);
if (entityageable != null)
{
if (this.playerInLove == null && p_70876_1_.func_146083_cb() != null)
{
this.playerInLove = p_70876_1_.func_146083_cb();
}
if (this.playerInLove != null)
{
this.playerInLove.triggerAchievement(StatList.animalsBredStat);
if (this instanceof EntityCow)
{
this.playerInLove.triggerAchievement(AchievementList.breedCow);
}
}
this.setGrowingAge(6000);
p_70876_1_.setGrowingAge(6000);
this.inLove = 0;
this.breeding = 0;
this.entityToAttack = null;
p_70876_1_.entityToAttack = null;
p_70876_1_.breeding = 0;
p_70876_1_.inLove = 0;
entityageable.setGrowingAge(-24000);
entityageable.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
for (int i = 0; i < 7; ++i)
{
double d0 = this.rand.nextGaussian() * 0.02D;
double d1 = this.rand.nextGaussian() * 0.02D;
double d2 = this.rand.nextGaussian() * 0.02D;
this.worldObj.spawnParticle("heart", this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + 0.5D + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, d0, d1, d2);
}
this.worldObj.spawnEntityInWorld(entityageable);
}
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (this.isEntityInvulnerable())
{
return false;
}
else
{
this.fleeingTick = 60;
if (!this.isAIEnabled())
{
IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.movementSpeed);
if (iattributeinstance.getModifier(field_110179_h) == null)
{
iattributeinstance.applyModifier(field_110181_i);
}
}
this.entityToAttack = null;
this.inLove = 0;
return super.attackEntityFrom(source, amount);
}
}
/**
* Takes a coordinate in and returns a weight to determine how likely this creature will try to path to the block.
* Args: x, y, z
*/
public float getBlockPathWeight(int p_70783_1_, int p_70783_2_, int p_70783_3_)
{
return this.worldObj.getBlock(p_70783_1_, p_70783_2_ - 1, p_70783_3_) == Blocks.grass ? 10.0F : this.worldObj.getLightBrightness(p_70783_1_, p_70783_2_, p_70783_3_) - 0.5F;
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound tagCompound)
{
super.writeEntityToNBT(tagCompound);
tagCompound.setInteger("InLove", this.inLove);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound tagCompund)
{
super.readEntityFromNBT(tagCompund);
this.inLove = tagCompund.getInteger("InLove");
}
/**
* Finds the closest player within 16 blocks to attack, or null if this Entity isn't interested in attacking
* (Animals, Spiders at day, peaceful PigZombies).
*/
protected Entity findPlayerToAttack()
{
if (this.fleeingTick > 0)
{
return null;
}
else
{
float f = 8.0F;
List list;
int i;
EntityAnimal entityanimal;
if (this.inLove > 0)
{
list = this.worldObj.getEntitiesWithinAABB(this.getClass(), this.boundingBox.expand((double)f, (double)f, (double)f));
for (i = 0; i < list.size(); ++i)
{
entityanimal = (EntityAnimal)list.get(i);
if (entityanimal != this && entityanimal.inLove > 0)
{
return entityanimal;
}
}
}
else if (this.getGrowingAge() == 0)
{
list = this.worldObj.getEntitiesWithinAABB(EntityPlayer.class, this.boundingBox.expand((double)f, (double)f, (double)f));
for (i = 0; i < list.size(); ++i)
{
EntityPlayer entityplayer = (EntityPlayer)list.get(i);
if (entityplayer.getCurrentEquippedItem() != null && this.isBreedingItem(entityplayer.getCurrentEquippedItem()))
{
return entityplayer;
}
}
}
else if (this.getGrowingAge() > 0)
{
list = this.worldObj.getEntitiesWithinAABB(this.getClass(), this.boundingBox.expand((double)f, (double)f, (double)f));
for (i = 0; i < list.size(); ++i)
{
entityanimal = (EntityAnimal)list.get(i);
if (entityanimal != this && entityanimal.getGrowingAge() < 0)
{
return entityanimal;
}
}
}
return null;
}
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
int i = MathHelper.floor_double(this.posX);
int j = MathHelper.floor_double(this.boundingBox.minY);
int k = MathHelper.floor_double(this.posZ);
return this.worldObj.getBlock(i, j - 1, k) == Blocks.grass && this.worldObj.getFullBlockLightValue(i, j, k) > 8 && super.getCanSpawnHere();
}
/**
* Get number of ticks, at least during which the living entity will be silent.
*/
public int getTalkInterval()
{
return 120;
}
/**
* Determines if an entity can be despawned, used on idle far away entities
*/
protected boolean canDespawn()
{
return false;
}
/**
* Get the experience points the entity currently has.
*/
protected int getExperiencePoints(EntityPlayer p_70693_1_)
{
return 1 + this.worldObj.rand.nextInt(3);
}
/**
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
* the animal type)
*/
public boolean isBreedingItem(ItemStack p_70877_1_)
{
return p_70877_1_.getItem() == Items.wheat;
}
/**
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
*/
public boolean interact(EntityPlayer p_70085_1_)
{
ItemStack itemstack = p_70085_1_.inventory.getCurrentItem();
if (itemstack != null && this.isBreedingItem(itemstack) && this.getGrowingAge() == 0 && this.inLove <= 0)
{
if (!p_70085_1_.capabilities.isCreativeMode)
{
--itemstack.stackSize;
if (itemstack.stackSize <= 0)
{
p_70085_1_.inventory.setInventorySlotContents(p_70085_1_.inventory.currentItem, (ItemStack)null);
}
}
this.setInLove(p_70085_1_);
return true;
}
else
{
return super.interact(p_70085_1_);
}
}
public void setInLove(EntityPlayer p_146082_1_)
{
this.inLove = 600;
this.playerInLove = p_146082_1_;
this.entityToAttack = null;
this.worldObj.setEntityState(this, (byte)18);
}
public EntityPlayer func_146083_cb()
{
return this.playerInLove;
}
/**
* Returns if the entity is currently in 'love mode'.
*/
public boolean isInLove()
{
return this.inLove > 0;
}
public void resetInLove()
{
this.inLove = 0;
}
/**
* Returns true if the mob is currently able to mate with the specified mob.
*/
public boolean canMateWith(EntityAnimal p_70878_1_)
{
return p_70878_1_ == this ? false : (p_70878_1_.getClass() != this.getClass() ? false : this.isInLove() && p_70878_1_.isInLove());
}
@SideOnly(Side.CLIENT)
public void handleHealthUpdate(byte p_70103_1_)
{
if (p_70103_1_ == 18)
{
for (int i = 0; i < 7; ++i)
{
double d0 = this.rand.nextGaussian() * 0.02D;
double d1 = this.rand.nextGaussian() * 0.02D;
double d2 = this.rand.nextGaussian() * 0.02D;
this.worldObj.spawnParticle("heart", this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + 0.5D + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, d0, d1, d2);
}
}
else
{
super.handleHealthUpdate(p_70103_1_);
}
}
}