001 package net.minecraft.src; 002 003 import cpw.mods.fml.common.Side; 004 import cpw.mods.fml.common.asm.SideOnly; 005 006 public class EntityOcelot extends EntityTameable 007 { 008 /** 009 * The tempt AI task for this mob, used to prevent taming while it is fleeing. 010 */ 011 private EntityAITempt aiTempt; 012 013 public EntityOcelot(World par1World) 014 { 015 super(par1World); 016 this.texture = "/mob/ozelot.png"; 017 this.setSize(0.6F, 0.8F); 018 this.getNavigator().setAvoidsWater(true); 019 this.tasks.addTask(1, new EntityAISwimming(this)); 020 this.tasks.addTask(2, this.aiSit); 021 this.tasks.addTask(3, this.aiTempt = new EntityAITempt(this, 0.18F, Item.fishRaw.shiftedIndex, true)); 022 this.tasks.addTask(4, new EntityAIAvoidEntity(this, EntityPlayer.class, 16.0F, 0.23F, 0.4F)); 023 this.tasks.addTask(5, new EntityAIFollowOwner(this, 0.3F, 10.0F, 5.0F)); 024 this.tasks.addTask(6, new EntityAIOcelotSit(this, 0.4F)); 025 this.tasks.addTask(7, new EntityAILeapAtTarget(this, 0.3F)); 026 this.tasks.addTask(8, new EntityAIOcelotAttack(this)); 027 this.tasks.addTask(9, new EntityAIMate(this, 0.23F)); 028 this.tasks.addTask(10, new EntityAIWander(this, 0.23F)); 029 this.tasks.addTask(11, new EntityAIWatchClosest(this, EntityPlayer.class, 10.0F)); 030 this.targetTasks.addTask(1, new EntityAITargetNonTamed(this, EntityChicken.class, 14.0F, 750, false)); 031 } 032 033 protected void entityInit() 034 { 035 super.entityInit(); 036 this.dataWatcher.addObject(18, Byte.valueOf((byte)0)); 037 } 038 039 /** 040 * main AI tick function, replaces updateEntityActionState 041 */ 042 public void updateAITick() 043 { 044 if (this.getMoveHelper().func_75640_a()) 045 { 046 float var1 = this.getMoveHelper().getSpeed(); 047 048 if (var1 == 0.18F) 049 { 050 this.setSneaking(true); 051 this.setSprinting(false); 052 } 053 else if (var1 == 0.4F) 054 { 055 this.setSneaking(false); 056 this.setSprinting(true); 057 } 058 else 059 { 060 this.setSneaking(false); 061 this.setSprinting(false); 062 } 063 } 064 else 065 { 066 this.setSneaking(false); 067 this.setSprinting(false); 068 } 069 } 070 071 /** 072 * Determines if an entity can be despawned, used on idle far away entities 073 */ 074 protected boolean canDespawn() 075 { 076 return !this.isTamed(); 077 } 078 079 @SideOnly(Side.CLIENT) 080 081 /** 082 * Returns the texture's file path as a String. 083 */ 084 public String getTexture() 085 { 086 switch (this.getTameSkin()) 087 { 088 case 0: 089 return "/mob/ozelot.png"; 090 case 1: 091 return "/mob/cat_black.png"; 092 case 2: 093 return "/mob/cat_red.png"; 094 case 3: 095 return "/mob/cat_siamese.png"; 096 default: 097 return super.getTexture(); 098 } 099 } 100 101 /** 102 * Returns true if the newer Entity AI code should be run 103 */ 104 public boolean isAIEnabled() 105 { 106 return true; 107 } 108 109 public int getMaxHealth() 110 { 111 return 10; 112 } 113 114 /** 115 * Called when the mob is falling. Calculates and applies fall damage. 116 */ 117 protected void fall(float par1) {} 118 119 /** 120 * (abstract) Protected helper method to write subclass entity data to NBT. 121 */ 122 public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 123 { 124 super.writeEntityToNBT(par1NBTTagCompound); 125 par1NBTTagCompound.setInteger("CatType", this.getTameSkin()); 126 } 127 128 /** 129 * (abstract) Protected helper method to read subclass entity data from NBT. 130 */ 131 public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 132 { 133 super.readEntityFromNBT(par1NBTTagCompound); 134 this.setTameSkin(par1NBTTagCompound.getInteger("CatType")); 135 } 136 137 /** 138 * Returns the sound this mob makes while it's alive. 139 */ 140 protected String getLivingSound() 141 { 142 return this.isTamed() ? (this.isInLove() ? "mob.cat.purr" : (this.rand.nextInt(4) == 0 ? "mob.cat.purreow" : "mob.cat.meow")) : ""; 143 } 144 145 /** 146 * Returns the sound this mob makes when it is hurt. 147 */ 148 protected String getHurtSound() 149 { 150 return "mob.cat.hitt"; 151 } 152 153 /** 154 * Returns the sound this mob makes on death. 155 */ 156 protected String getDeathSound() 157 { 158 return "mob.cat.hitt"; 159 } 160 161 /** 162 * Returns the volume for the sounds this mob makes. 163 */ 164 protected float getSoundVolume() 165 { 166 return 0.4F; 167 } 168 169 /** 170 * Returns the item ID for the item the mob drops on death. 171 */ 172 protected int getDropItemId() 173 { 174 return Item.leather.shiftedIndex; 175 } 176 177 public boolean attackEntityAsMob(Entity par1Entity) 178 { 179 return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), 3); 180 } 181 182 /** 183 * Called when the entity is attacked. 184 */ 185 public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) 186 { 187 this.aiSit.setSitting(false); 188 return super.attackEntityFrom(par1DamageSource, par2); 189 } 190 191 /** 192 * Drop 0-2 items of this living's type 193 */ 194 protected void dropFewItems(boolean par1, int par2) {} 195 196 /** 197 * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. 198 */ 199 public boolean interact(EntityPlayer par1EntityPlayer) 200 { 201 ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem(); 202 203 if (this.isTamed()) 204 { 205 if (par1EntityPlayer.username.equalsIgnoreCase(this.getOwnerName()) && !this.worldObj.isRemote && !this.isWheat(var2)) 206 { 207 this.aiSit.setSitting(!this.isSitting()); 208 } 209 } 210 else if (this.aiTempt.func_75277_f() && var2 != null && var2.itemID == Item.fishRaw.shiftedIndex && par1EntityPlayer.getDistanceSqToEntity(this) < 9.0D) 211 { 212 if (!par1EntityPlayer.capabilities.isCreativeMode) 213 { 214 --var2.stackSize; 215 } 216 217 if (var2.stackSize <= 0) 218 { 219 par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem, (ItemStack)null); 220 } 221 222 if (!this.worldObj.isRemote) 223 { 224 if (this.rand.nextInt(3) == 0) 225 { 226 this.setTamed(true); 227 this.setTameSkin(1 + this.worldObj.rand.nextInt(3)); 228 this.setOwner(par1EntityPlayer.username); 229 this.playTameEffect(true); 230 this.aiSit.setSitting(true); 231 this.worldObj.setEntityState(this, (byte)7); 232 } 233 else 234 { 235 this.playTameEffect(false); 236 this.worldObj.setEntityState(this, (byte)6); 237 } 238 } 239 240 return true; 241 } 242 243 return super.interact(par1EntityPlayer); 244 } 245 246 /** 247 * This function is used when two same-species animals in 'love mode' breed to generate the new baby animal. 248 */ 249 public EntityAnimal spawnBabyAnimal(EntityAnimal par1EntityAnimal) 250 { 251 EntityOcelot var2 = new EntityOcelot(this.worldObj); 252 253 if (this.isTamed()) 254 { 255 var2.setOwner(this.getOwnerName()); 256 var2.setTamed(true); 257 var2.setTameSkin(this.getTameSkin()); 258 } 259 260 return var2; 261 } 262 263 /** 264 * Checks if the parameter is an wheat item. 265 */ 266 public boolean isWheat(ItemStack par1ItemStack) 267 { 268 return par1ItemStack != null && par1ItemStack.itemID == Item.fishRaw.shiftedIndex; 269 } 270 271 /** 272 * Returns true if the mob is currently able to mate with the specified mob. 273 */ 274 public boolean canMateWith(EntityAnimal par1EntityAnimal) 275 { 276 if (par1EntityAnimal == this) 277 { 278 return false; 279 } 280 else if (!this.isTamed()) 281 { 282 return false; 283 } 284 else if (!(par1EntityAnimal instanceof EntityOcelot)) 285 { 286 return false; 287 } 288 else 289 { 290 EntityOcelot var2 = (EntityOcelot)par1EntityAnimal; 291 return !var2.isTamed() ? false : this.isInLove() && var2.isInLove(); 292 } 293 } 294 295 public int getTameSkin() 296 { 297 return this.dataWatcher.getWatchableObjectByte(18); 298 } 299 300 public void setTameSkin(int par1) 301 { 302 this.dataWatcher.updateObject(18, Byte.valueOf((byte)par1)); 303 } 304 305 /** 306 * Checks if the entity's current position is a valid location to spawn this entity. 307 */ 308 public boolean getCanSpawnHere() 309 { 310 if (this.worldObj.rand.nextInt(3) == 0) 311 { 312 return false; 313 } 314 else 315 { 316 if (this.worldObj.checkIfAABBIsClear(this.boundingBox) && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() && !this.worldObj.isAnyLiquid(this.boundingBox)) 317 { 318 int var1 = MathHelper.floor_double(this.posX); 319 int var2 = MathHelper.floor_double(this.boundingBox.minY); 320 int var3 = MathHelper.floor_double(this.posZ); 321 322 if (var2 < 63) 323 { 324 return false; 325 } 326 327 int var4 = this.worldObj.getBlockId(var1, var2 - 1, var3); 328 Block block = Block.blocksList[var4]; 329 330 if (var4 == Block.grass.blockID || (block != null && block.isLeaves(worldObj, var1, var2 - 1, var3))) 331 { 332 return true; 333 } 334 } 335 336 return false; 337 } 338 } 339 340 /** 341 * Gets the username of the entity. 342 */ 343 public String getEntityName() 344 { 345 return this.isTamed() ? "entity.Cat.name" : super.getEntityName(); 346 } 347 }