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 }