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.createChild(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 }