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 }