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 }