    001    package net.minecraft.entity.ai;
    002
    003    import java.util.Iterator;
    004    import java.util.List;
    005    import java.util.Random;
    006    import net.minecraft.entity.EntityAgeable;
    007    import net.minecraft.entity.item.EntityXPOrb;
    008    import net.minecraft.entity.passive.EntityAnimal;
    009    import net.minecraft.world.World;
    010
    011    public class EntityAIMate extends EntityAIBase
    012    {
    013        private EntityAnimal theAnimal;
    014        World theWorld;
    015        private EntityAnimal targetMate;
    016
    017        /**
    018         * Delay preventing a baby from spawning immediately when two mate-able animals find each other.
    019         */
    020        int spawnBabyDelay = 0;
    021
    022        /** The speed the creature moves at during mating behavior. */
    023        float moveSpeed;
    024
    025        public EntityAIMate(EntityAnimal par1EntityAnimal, float par2)
    026        {
    027            this.theAnimal = par1EntityAnimal;
    028            this.theWorld = par1EntityAnimal.worldObj;
    029            this.moveSpeed = par2;
    030            this.setMutexBits(3);
    031        }
    032
    033        /**
    034         * Returns whether the EntityAIBase should begin execution.
    035         */
    036        public boolean shouldExecute()
    037        {
    038            if (!this.theAnimal.isInLove())
    039            {
    040                return false;
    041            }
    042            else
    043            {
    044                this.targetMate = this.getNearbyMate();
    045                return this.targetMate != null;
    046            }
    047        }
    048
    049        /**
    050         * Returns whether an in-progress EntityAIBase should continue executing
    051         */
    052        public boolean continueExecuting()
    053        {
    054            return this.targetMate.isEntityAlive() && this.targetMate.isInLove() && this.spawnBabyDelay < 60;
    055        }
    056
    057        /**
    058         * Resets the task
    059         */
    060        public void resetTask()
    061        {
    062            this.targetMate = null;
    063            this.spawnBabyDelay = 0;
    064        }
    065
    066        /**
    067         * Updates the task
    068         */
    069        public void updateTask()
    070        {
    071            this.theAnimal.getLookHelper().setLookPositionWithEntity(this.targetMate, 10.0F, (float)this.theAnimal.getVerticalFaceSpeed());
    072            this.theAnimal.getNavigator().tryMoveToEntityLiving(this.targetMate, this.moveSpeed);
    073            ++this.spawnBabyDelay;
    074
    075            if (this.spawnBabyDelay == 60)
    076            {
    077                this.spawnBaby();
    078            }
    079        }
    080
    081        /**
    082         * Loops through nearby animals and finds another animal of the same type that can be mated with. Returns the first
    083         * valid mate found.
    084         */
    085        private EntityAnimal getNearbyMate()
    086        {
    087            float var1 = 8.0F;
    088            List var2 = this.theWorld.getEntitiesWithinAABB(this.theAnimal.getClass(), this.theAnimal.boundingBox.expand((double)var1, (double)var1, (double)var1));
    089            Iterator var3 = var2.iterator();
    090            EntityAnimal var4;
    091
    092            do
    093            {
    094                if (!var3.hasNext())
    095                {
    096                    return null;
    097                }
    098
    099                var4 = (EntityAnimal)var3.next();
    100            }
    101            while (!this.theAnimal.canMateWith(var4));
    102
    103            return var4;
    104        }
    105
    106        /**
    107         * Spawns a baby animal of the same type.
    108         */
    109        private void spawnBaby()
    110        {
    111            EntityAgeable var1 = this.theAnimal.func_90011_a(this.targetMate);
    112
    113            if (var1 != null)
    114            {
    115                this.theAnimal.setGrowingAge(6000);
    116                this.targetMate.setGrowingAge(6000);
    117                this.theAnimal.resetInLove();
    118                this.targetMate.resetInLove();
    119                var1.setGrowingAge(-24000);
    120                var1.setLocationAndAngles(this.theAnimal.posX, this.theAnimal.posY, this.theAnimal.posZ, 0.0F, 0.0F);
    121                this.theWorld.spawnEntityInWorld(var1);
    122                Random var2 = this.theAnimal.getRNG();
    123
    124                for (int var3 = 0; var3 < 7; ++var3)
    125                {
    126                    double var4 = var2.nextGaussian() * 0.02D;
    127                    double var6 = var2.nextGaussian() * 0.02D;
    128                    double var8 = var2.nextGaussian() * 0.02D;
    129                    this.theWorld.spawnParticle("heart", this.theAnimal.posX + (double)(var2.nextFloat() * this.theAnimal.width * 2.0F) - (double)this.theAnimal.width, this.theAnimal.posY + 0.5D + (double)(var2.nextFloat() * this.theAnimal.height), this.theAnimal.posZ + (double)(var2.nextFloat() * this.theAnimal.width * 2.0F) - (double)this.theAnimal.width, var4, var6, var8);
    130                }
    131
    132                this.theWorld.spawnEntityInWorld(new EntityXPOrb(this.theWorld, this.theAnimal.posX, this.theAnimal.posY, this.theAnimal.posZ, var2.nextInt(7) + 1));
    133            }
    134        }
    135    }