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    
348        public void func_82163_bD()
349        {
350            if (this.worldObj.rand.nextInt(7) == 0)
351            {
352                for (int var1 = 0; var1 < 2; ++var1)
353                {
354                    EntityOcelot var2 = new EntityOcelot(this.worldObj);
355                    var2.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
356                    var2.setGrowingAge(-24000);
357                    this.worldObj.spawnEntityInWorld(var2);
358                }
359            }
360        }
361    }