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.isBreedingItem(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 item which this animal can be fed to breed it (wheat, carrots or seeds depending on
265         * the animal type)
266         */
267        public boolean isBreedingItem(ItemStack par1ItemStack)
268        {
269            return par1ItemStack != null && par1ItemStack.itemID == Item.fishRaw.shiftedIndex;
270        }
271    
272        /**
273         * Returns true if the mob is currently able to mate with the specified mob.
274         */
275        public boolean canMateWith(EntityAnimal par1EntityAnimal)
276        {
277            if (par1EntityAnimal == this)
278            {
279                return false;
280            }
281            else if (!this.isTamed())
282            {
283                return false;
284            }
285            else if (!(par1EntityAnimal instanceof EntityOcelot))
286            {
287                return false;
288            }
289            else
290            {
291                EntityOcelot var2 = (EntityOcelot)par1EntityAnimal;
292                return !var2.isTamed() ? false : this.isInLove() && var2.isInLove();
293            }
294        }
295    
296        public int getTameSkin()
297        {
298            return this.dataWatcher.getWatchableObjectByte(18);
299        }
300    
301        public void setTameSkin(int par1)
302        {
303            this.dataWatcher.updateObject(18, Byte.valueOf((byte)par1));
304        }
305    
306        /**
307         * Checks if the entity's current position is a valid location to spawn this entity.
308         */
309        public boolean getCanSpawnHere()
310        {
311            if (this.worldObj.rand.nextInt(3) == 0)
312            {
313                return false;
314            }
315            else
316            {
317                if (this.worldObj.checkIfAABBIsClear(this.boundingBox) && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() && !this.worldObj.isAnyLiquid(this.boundingBox))
318                {
319                    int var1 = MathHelper.floor_double(this.posX);
320                    int var2 = MathHelper.floor_double(this.boundingBox.minY);
321                    int var3 = MathHelper.floor_double(this.posZ);
322    
323                    if (var2 < 63)
324                    {
325                        return false;
326                    }
327    
328                    int var4 = this.worldObj.getBlockId(var1, var2 - 1, var3);
329                    Block block = Block.blocksList[var4];
330    
331                    if (var4 == Block.grass.blockID || (block != null && block.isLeaves(worldObj, var1, var2 - 1, var3)))
332                    {
333                        return true;
334                    }
335                }
336    
337                return false;
338            }
339        }
340    
341        /**
342         * Gets the username of the entity.
343         */
344        public String getEntityName()
345        {
346            return this.isTamed() ? "entity.Cat.name" : super.getEntityName();
347        }
348    
349        /**
350         * Initialize this creature.
351         */
352        public void initCreature()
353        {
354            if (this.worldObj.rand.nextInt(7) == 0)
355            {
356                for (int var1 = 0; var1 < 2; ++var1)
357                {
358                    EntityOcelot var2 = new EntityOcelot(this.worldObj);
359                    var2.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
360                    var2.setGrowingAge(-24000);
361                    this.worldObj.spawnEntityInWorld(var2);
362                }
363            }
364        }
365    }