001package net.minecraft.entity.ai; 002 003import net.minecraft.block.Block; 004import net.minecraft.block.BlockHalfSlab; 005import net.minecraft.entity.EntityCreature; 006import net.minecraft.entity.EntityLiving; 007import net.minecraft.entity.player.EntityPlayer; 008import net.minecraft.item.Item; 009import net.minecraft.item.ItemStack; 010import net.minecraft.pathfinding.PathFinder; 011import net.minecraft.pathfinding.PathPoint; 012import net.minecraft.util.MathHelper; 013 014public class EntityAIControlledByPlayer extends EntityAIBase 015{ 016 private final EntityLiving thisEntity; 017 private final float maxSpeed; 018 private float currentSpeed = 0.0F; 019 020 /** Whether the entity's speed is boosted. */ 021 private boolean speedBoosted = false; 022 023 /** 024 * Counter for speed boosting, upon reaching maxSpeedBoostTime the speed boost will be disabled 025 */ 026 private int speedBoostTime = 0; 027 028 /** Maximum time the entity's speed should be boosted for. */ 029 private int maxSpeedBoostTime = 0; 030 031 public EntityAIControlledByPlayer(EntityLiving par1EntityLiving, float par2) 032 { 033 this.thisEntity = par1EntityLiving; 034 this.maxSpeed = par2; 035 this.setMutexBits(7); 036 } 037 038 /** 039 * Execute a one shot task or start executing a continuous task 040 */ 041 public void startExecuting() 042 { 043 this.currentSpeed = 0.0F; 044 } 045 046 /** 047 * Resets the task 048 */ 049 public void resetTask() 050 { 051 this.speedBoosted = false; 052 this.currentSpeed = 0.0F; 053 } 054 055 /** 056 * Returns whether the EntityAIBase should begin execution. 057 */ 058 public boolean shouldExecute() 059 { 060 return this.thisEntity.isEntityAlive() && this.thisEntity.riddenByEntity != null && this.thisEntity.riddenByEntity instanceof EntityPlayer && (this.speedBoosted || this.thisEntity.canBeSteered()); 061 } 062 063 /** 064 * Updates the task 065 */ 066 public void updateTask() 067 { 068 EntityPlayer entityplayer = (EntityPlayer)this.thisEntity.riddenByEntity; 069 EntityCreature entitycreature = (EntityCreature)this.thisEntity; 070 float f = MathHelper.wrapAngleTo180_float(entityplayer.rotationYaw - this.thisEntity.rotationYaw) * 0.5F; 071 072 if (f > 5.0F) 073 { 074 f = 5.0F; 075 } 076 077 if (f < -5.0F) 078 { 079 f = -5.0F; 080 } 081 082 this.thisEntity.rotationYaw = MathHelper.wrapAngleTo180_float(this.thisEntity.rotationYaw + f); 083 084 if (this.currentSpeed < this.maxSpeed) 085 { 086 this.currentSpeed += (this.maxSpeed - this.currentSpeed) * 0.01F; 087 } 088 089 if (this.currentSpeed > this.maxSpeed) 090 { 091 this.currentSpeed = this.maxSpeed; 092 } 093 094 int i = MathHelper.floor_double(this.thisEntity.posX); 095 int j = MathHelper.floor_double(this.thisEntity.posY); 096 int k = MathHelper.floor_double(this.thisEntity.posZ); 097 float f1 = this.currentSpeed; 098 099 if (this.speedBoosted) 100 { 101 if (this.speedBoostTime++ > this.maxSpeedBoostTime) 102 { 103 this.speedBoosted = false; 104 } 105 106 f1 += f1 * 1.15F * MathHelper.sin((float)this.speedBoostTime / (float)this.maxSpeedBoostTime * (float)Math.PI); 107 } 108 109 float f2 = 0.91F; 110 111 if (this.thisEntity.onGround) 112 { 113 f2 = 0.54600006F; 114 int l = this.thisEntity.worldObj.getBlockId(MathHelper.floor_float((float)i), MathHelper.floor_float((float)j) - 1, MathHelper.floor_float((float)k)); 115 116 if (l > 0) 117 { 118 f2 = Block.blocksList[l].slipperiness * 0.91F; 119 } 120 } 121 122 float f3 = 0.16277136F / (f2 * f2 * f2); 123 float f4 = MathHelper.sin(entitycreature.rotationYaw * (float)Math.PI / 180.0F); 124 float f5 = MathHelper.cos(entitycreature.rotationYaw * (float)Math.PI / 180.0F); 125 float f6 = entitycreature.getAIMoveSpeed() * f3; 126 float f7 = Math.max(f1, 1.0F); 127 f7 = f6 / f7; 128 float f8 = f1 * f7; 129 float f9 = -(f8 * f4); 130 float f10 = f8 * f5; 131 132 if (MathHelper.abs(f9) > MathHelper.abs(f10)) 133 { 134 if (f9 < 0.0F) 135 { 136 f9 -= this.thisEntity.width / 2.0F; 137 } 138 139 if (f9 > 0.0F) 140 { 141 f9 += this.thisEntity.width / 2.0F; 142 } 143 144 f10 = 0.0F; 145 } 146 else 147 { 148 f9 = 0.0F; 149 150 if (f10 < 0.0F) 151 { 152 f10 -= this.thisEntity.width / 2.0F; 153 } 154 155 if (f10 > 0.0F) 156 { 157 f10 += this.thisEntity.width / 2.0F; 158 } 159 } 160 161 int i1 = MathHelper.floor_double(this.thisEntity.posX + (double)f9); 162 int j1 = MathHelper.floor_double(this.thisEntity.posZ + (double)f10); 163 PathPoint pathpoint = new PathPoint(MathHelper.floor_float(this.thisEntity.width + 1.0F), MathHelper.floor_float(this.thisEntity.height + entityplayer.height + 1.0F), MathHelper.floor_float(this.thisEntity.width + 1.0F)); 164 165 if (i != i1 || k != j1) 166 { 167 int k1 = this.thisEntity.worldObj.getBlockId(i, j, k); 168 int l1 = this.thisEntity.worldObj.getBlockId(i, j - 1, k); 169 boolean flag = this.func_98216_b(k1) || Block.blocksList[k1] == null && this.func_98216_b(l1); 170 171 if (!flag && PathFinder.func_82565_a(this.thisEntity, i1, j, j1, pathpoint, false, false, true) == 0 && PathFinder.func_82565_a(this.thisEntity, i, j + 1, k, pathpoint, false, false, true) == 1 && PathFinder.func_82565_a(this.thisEntity, i1, j + 1, j1, pathpoint, false, false, true) == 1) 172 { 173 entitycreature.getJumpHelper().setJumping(); 174 } 175 } 176 177 if (!entityplayer.capabilities.isCreativeMode && this.currentSpeed >= this.maxSpeed * 0.5F && this.thisEntity.getRNG().nextFloat() < 0.006F && !this.speedBoosted) 178 { 179 ItemStack itemstack = entityplayer.getHeldItem(); 180 181 if (itemstack != null && itemstack.itemID == Item.carrotOnAStick.itemID) 182 { 183 itemstack.damageItem(1, entityplayer); 184 185 if (itemstack.stackSize == 0) 186 { 187 ItemStack itemstack1 = new ItemStack(Item.fishingRod); 188 itemstack1.setTagCompound(itemstack.stackTagCompound); 189 entityplayer.inventory.mainInventory[entityplayer.inventory.currentItem] = itemstack1; 190 } 191 } 192 } 193 194 this.thisEntity.moveEntityWithHeading(0.0F, f1); 195 } 196 197 private boolean func_98216_b(int par1) 198 { 199 return Block.blocksList[par1] != null && (Block.blocksList[par1].getRenderType() == 10 || Block.blocksList[par1] instanceof BlockHalfSlab); 200 } 201 202 /** 203 * Return whether the entity's speed is boosted. 204 */ 205 public boolean isSpeedBoosted() 206 { 207 return this.speedBoosted; 208 } 209 210 /** 211 * Boost the entity's movement speed. 212 */ 213 public void boostSpeed() 214 { 215 this.speedBoosted = true; 216 this.speedBoostTime = 0; 217 this.maxSpeedBoostTime = this.thisEntity.getRNG().nextInt(841) + 140; 218 } 219 220 /** 221 * Return whether the entity is being controlled by a player. 222 */ 223 public boolean isControlledByPlayer() 224 { 225 return !this.isSpeedBoosted() && this.currentSpeed > this.maxSpeed * 0.3F; 226 } 227}