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