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            if (this.func_85032_ar())
188            {
189                return false;
190            }
191            else
192            {
193                this.aiSit.setSitting(false);
194                return super.attackEntityFrom(par1DamageSource, par2);
195            }
196        }
197    
198        /**
199         * Drop 0-2 items of this living's type
200         */
201        protected void dropFewItems(boolean par1, int par2) {}
202    
203        /**
204         * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
205         */
206        public boolean interact(EntityPlayer par1EntityPlayer)
207        {
208            ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
209    
210            if (this.isTamed())
211            {
212                if (par1EntityPlayer.username.equalsIgnoreCase(this.getOwnerName()) && !this.worldObj.isRemote && !this.isBreedingItem(var2))
213                {
214                    this.aiSit.setSitting(!this.isSitting());
215                }
216            }
217            else if (this.aiTempt.func_75277_f() && var2 != null && var2.itemID == Item.fishRaw.shiftedIndex && par1EntityPlayer.getDistanceSqToEntity(this) < 9.0D)
218            {
219                if (!par1EntityPlayer.capabilities.isCreativeMode)
220                {
221                    --var2.stackSize;
222                }
223    
224                if (var2.stackSize <= 0)
225                {
226                    par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem, (ItemStack)null);
227                }
228    
229                if (!this.worldObj.isRemote)
230                {
231                    if (this.rand.nextInt(3) == 0)
232                    {
233                        this.setTamed(true);
234                        this.setTameSkin(1 + this.worldObj.rand.nextInt(3));
235                        this.setOwner(par1EntityPlayer.username);
236                        this.playTameEffect(true);
237                        this.aiSit.setSitting(true);
238                        this.worldObj.setEntityState(this, (byte)7);
239                    }
240                    else
241                    {
242                        this.playTameEffect(false);
243                        this.worldObj.setEntityState(this, (byte)6);
244                    }
245                }
246    
247                return true;
248            }
249    
250            return super.interact(par1EntityPlayer);
251        }
252    
253        /**
254         * This function is used when two same-species animals in 'love mode' breed to generate the new baby animal.
255         */
256        public EntityAnimal spawnBabyAnimal(EntityAnimal par1EntityAnimal)
257        {
258            EntityOcelot var2 = new EntityOcelot(this.worldObj);
259    
260            if (this.isTamed())
261            {
262                var2.setOwner(this.getOwnerName());
263                var2.setTamed(true);
264                var2.setTameSkin(this.getTameSkin());
265            }
266    
267            return var2;
268        }
269    
270        /**
271         * Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
272         * the animal type)
273         */
274        public boolean isBreedingItem(ItemStack par1ItemStack)
275        {
276            return par1ItemStack != null && par1ItemStack.itemID == Item.fishRaw.shiftedIndex;
277        }
278    
279        /**
280         * Returns true if the mob is currently able to mate with the specified mob.
281         */
282        public boolean canMateWith(EntityAnimal par1EntityAnimal)
283        {
284            if (par1EntityAnimal == this)
285            {
286                return false;
287            }
288            else if (!this.isTamed())
289            {
290                return false;
291            }
292            else if (!(par1EntityAnimal instanceof EntityOcelot))
293            {
294                return false;
295            }
296            else
297            {
298                EntityOcelot var2 = (EntityOcelot)par1EntityAnimal;
299                return !var2.isTamed() ? false : this.isInLove() && var2.isInLove();
300            }
301        }
302    
303        public int getTameSkin()
304        {
305            return this.dataWatcher.getWatchableObjectByte(18);
306        }
307    
308        public void setTameSkin(int par1)
309        {
310            this.dataWatcher.updateObject(18, Byte.valueOf((byte)par1));
311        }
312    
313        /**
314         * Checks if the entity's current position is a valid location to spawn this entity.
315         */
316        public boolean getCanSpawnHere()
317        {
318            if (this.worldObj.rand.nextInt(3) == 0)
319            {
320                return false;
321            }
322            else
323            {
324                if (this.worldObj.checkIfAABBIsClear(this.boundingBox) && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() && !this.worldObj.isAnyLiquid(this.boundingBox))
325                {
326                    int var1 = MathHelper.floor_double(this.posX);
327                    int var2 = MathHelper.floor_double(this.boundingBox.minY);
328                    int var3 = MathHelper.floor_double(this.posZ);
329    
330                    if (var2 < 63)
331                    {
332                        return false;
333                    }
334    
335                    int var4 = this.worldObj.getBlockId(var1, var2 - 1, var3);
336                    Block block = Block.blocksList[var4];
337    
338                    if (var4 == Block.grass.blockID || (block != null && block.isLeaves(worldObj, var1, var2 - 1, var3)))
339                    {
340                        return true;
341                    }
342                }
343    
344                return false;
345            }
346        }
347    
348        /**
349         * Gets the username of the entity.
350         */
351        public String getEntityName()
352        {
353            return this.isTamed() ? "entity.Cat.name" : super.getEntityName();
354        }
355    
356        /**
357         * Initialize this creature.
358         */
359        public void initCreature()
360        {
361            if (this.worldObj.rand.nextInt(7) == 0)
362            {
363                for (int var1 = 0; var1 < 2; ++var1)
364                {
365                    EntityOcelot var2 = new EntityOcelot(this.worldObj);
366                    var2.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
367                    var2.setGrowingAge(-24000);
368                    this.worldObj.spawnEntityInWorld(var2);
369                }
370            }
371        }
372    }