001package net.minecraft.entity.ai;
002
003import net.minecraft.block.Block;
004import net.minecraft.block.BlockBed;
005import net.minecraft.entity.passive.EntityOcelot;
006import net.minecraft.tileentity.TileEntityChest;
007import net.minecraft.world.World;
008
009public 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}