001    package net.minecraft.src;
002    
003    public class EntityAIOcelotSit extends EntityAIBase
004    {
005        private final EntityOcelot theOcelot;
006        private final float field_75404_b;
007    
008        /** Tracks for how long the task has been executing */
009        private int currentTick = 0;
010        private int field_75402_d = 0;
011    
012        /** For how long the Ocelot should be sitting */
013        private int maxSittingTicks = 0;
014    
015        /** X Coordinate of a nearby sitable block */
016        private int sitableBlockX = 0;
017    
018        /** Y Coordinate of a nearby sitable block */
019        private int sitableBlockY = 0;
020    
021        /** Z Coordinate of a nearby sitable block */
022        private int sitableBlockZ = 0;
023    
024        public EntityAIOcelotSit(EntityOcelot par1EntityOcelot, float par2)
025        {
026            this.theOcelot = par1EntityOcelot;
027            this.field_75404_b = par2;
028            this.setMutexBits(5);
029        }
030    
031        /**
032         * Returns whether the EntityAIBase should begin execution.
033         */
034        public boolean shouldExecute()
035        {
036            return this.theOcelot.isTamed() && !this.theOcelot.isSitting() && this.theOcelot.getRNG().nextDouble() <= 0.006500000134110451D && this.getNearbySitableBlockDistance();
037        }
038    
039        /**
040         * Returns whether an in-progress EntityAIBase should continue executing
041         */
042        public boolean continueExecuting()
043        {
044            return this.currentTick <= this.maxSittingTicks && this.field_75402_d <= 60 && this.isSittableBlock(this.theOcelot.worldObj, this.sitableBlockX, this.sitableBlockY, this.sitableBlockZ);
045        }
046    
047        /**
048         * Execute a one shot task or start executing a continuous task
049         */
050        public void startExecuting()
051        {
052            this.theOcelot.getNavigator().tryMoveToXYZ((double)((float)this.sitableBlockX) + 0.5D, (double)(this.sitableBlockY + 1), (double)((float)this.sitableBlockZ) + 0.5D, this.field_75404_b);
053            this.currentTick = 0;
054            this.field_75402_d = 0;
055            this.maxSittingTicks = this.theOcelot.getRNG().nextInt(this.theOcelot.getRNG().nextInt(1200) + 1200) + 1200;
056            this.theOcelot.func_70907_r().setSitting(false);
057        }
058    
059        /**
060         * Resets the task
061         */
062        public void resetTask()
063        {
064            this.theOcelot.setSitting(false);
065        }
066    
067        /**
068         * Updates the task
069         */
070        public void updateTask()
071        {
072            ++this.currentTick;
073            this.theOcelot.func_70907_r().setSitting(false);
074    
075            if (this.theOcelot.getDistanceSq((double)this.sitableBlockX, (double)(this.sitableBlockY + 1), (double)this.sitableBlockZ) > 1.0D)
076            {
077                this.theOcelot.setSitting(false);
078                this.theOcelot.getNavigator().tryMoveToXYZ((double)((float)this.sitableBlockX) + 0.5D, (double)(this.sitableBlockY + 1), (double)((float)this.sitableBlockZ) + 0.5D, this.field_75404_b);
079                ++this.field_75402_d;
080            }
081            else if (!this.theOcelot.isSitting())
082            {
083                this.theOcelot.setSitting(true);
084            }
085            else
086            {
087                --this.field_75402_d;
088            }
089        }
090    
091        /**
092         * Searches for a block to sit on within a 8 block range, returns 0 if none found
093         */
094        protected boolean getNearbySitableBlockDistance()
095        {
096            int var1 = (int)this.theOcelot.posY;
097            double var2 = 2.147483647E9D;
098    
099            for (int var4 = (int)this.theOcelot.posX - 8; (double)var4 < this.theOcelot.posX + 8.0D; ++var4)
100            {
101                for (int var5 = (int)this.theOcelot.posZ - 8; (double)var5 < this.theOcelot.posZ + 8.0D; ++var5)
102                {
103                    if (this.isSittableBlock(this.theOcelot.worldObj, var4, var1, var5) && this.theOcelot.worldObj.isAirBlock(var4, var1 + 1, var5))
104                    {
105                        double var6 = this.theOcelot.getDistanceSq((double)var4, (double)var1, (double)var5);
106    
107                        if (var6 < var2)
108                        {
109                            this.sitableBlockX = var4;
110                            this.sitableBlockY = var1;
111                            this.sitableBlockZ = var5;
112                            var2 = var6;
113                        }
114                    }
115                }
116            }
117    
118            return var2 < 2.147483647E9D;
119        }
120    
121        /**
122         * Determines wheter the Ocelot wants to sit on the block at given coordinate
123         */
124        protected boolean isSittableBlock(World par1World, int par2, int par3, int par4)
125        {
126            int var5 = par1World.getBlockId(par2, par3, par4);
127            int var6 = par1World.getBlockMetadata(par2, par3, par4);
128    
129            if (var5 == Block.chest.blockID)
130            {
131                TileEntityChest var7 = (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4);
132    
133                if (var7.numUsingPlayers < 1)
134                {
135                    return true;
136                }
137            }
138            else
139            {
140                if (var5 == Block.stoneOvenActive.blockID)
141                {
142                    return true;
143                }
144    
145                if (var5 == Block.bed.blockID && !BlockBed.isBlockHeadOfBed(var6))
146                {
147                    return true;
148                }
149            }
150    
151            return false;
152        }
153    }