    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 wheter 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    }