001package net.minecraft.entity.ai; 002 003import java.util.Iterator; 004import java.util.List; 005import java.util.Random; 006import net.minecraft.entity.EntityAgeable; 007import net.minecraft.entity.item.EntityXPOrb; 008import net.minecraft.entity.passive.EntityAnimal; 009import net.minecraft.world.World; 010 011public 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 && this.theAnimal.getDistanceSqToEntity(this.targetMate) < 9.0D) 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 f = 8.0F; 088 List list = this.theWorld.getEntitiesWithinAABB(this.theAnimal.getClass(), this.theAnimal.boundingBox.expand((double)f, (double)f, (double)f)); 089 double d0 = Double.MAX_VALUE; 090 EntityAnimal entityanimal = null; 091 Iterator iterator = list.iterator(); 092 093 while (iterator.hasNext()) 094 { 095 EntityAnimal entityanimal1 = (EntityAnimal)iterator.next(); 096 097 if (this.theAnimal.canMateWith(entityanimal1) && this.theAnimal.getDistanceSqToEntity(entityanimal1) < d0) 098 { 099 entityanimal = entityanimal1; 100 d0 = this.theAnimal.getDistanceSqToEntity(entityanimal1); 101 } 102 } 103 104 return entityanimal; 105 } 106 107 /** 108 * Spawns a baby animal of the same type. 109 */ 110 private void spawnBaby() 111 { 112 EntityAgeable entityageable = this.theAnimal.createChild(this.targetMate); 113 114 if (entityageable != null) 115 { 116 this.theAnimal.setGrowingAge(6000); 117 this.targetMate.setGrowingAge(6000); 118 this.theAnimal.resetInLove(); 119 this.targetMate.resetInLove(); 120 entityageable.setGrowingAge(-24000); 121 entityageable.setLocationAndAngles(this.theAnimal.posX, this.theAnimal.posY, this.theAnimal.posZ, 0.0F, 0.0F); 122 this.theWorld.spawnEntityInWorld(entityageable); 123 Random random = this.theAnimal.getRNG(); 124 125 for (int i = 0; i < 7; ++i) 126 { 127 double d0 = random.nextGaussian() * 0.02D; 128 double d1 = random.nextGaussian() * 0.02D; 129 double d2 = random.nextGaussian() * 0.02D; 130 this.theWorld.spawnParticle("heart", this.theAnimal.posX + (double)(random.nextFloat() * this.theAnimal.width * 2.0F) - (double)this.theAnimal.width, this.theAnimal.posY + 0.5D + (double)(random.nextFloat() * this.theAnimal.height), this.theAnimal.posZ + (double)(random.nextFloat() * this.theAnimal.width * 2.0F) - (double)this.theAnimal.width, d0, d1, d2); 131 } 132 133 this.theWorld.spawnEntityInWorld(new EntityXPOrb(this.theWorld, this.theAnimal.posX, this.theAnimal.posY, this.theAnimal.posZ, random.nextInt(7) + 1)); 134 } 135 } 136}