001 package net.minecraft.entity.passive; 002 003 import cpw.mods.fml.common.Side; 004 import cpw.mods.fml.common.asm.SideOnly; 005 006 import java.util.ArrayList; 007 import java.util.Random; 008 import net.minecraft.block.Block; 009 import net.minecraft.entity.EntityAgeable; 010 import net.minecraft.entity.ai.EntityAIEatGrass; 011 import net.minecraft.entity.ai.EntityAIFollowParent; 012 import net.minecraft.entity.ai.EntityAILookIdle; 013 import net.minecraft.entity.ai.EntityAIMate; 014 import net.minecraft.entity.ai.EntityAIPanic; 015 import net.minecraft.entity.ai.EntityAISwimming; 016 import net.minecraft.entity.ai.EntityAITempt; 017 import net.minecraft.entity.ai.EntityAIWander; 018 import net.minecraft.entity.ai.EntityAIWatchClosest; 019 import net.minecraft.entity.item.EntityItem; 020 import net.minecraft.entity.player.EntityPlayer; 021 import net.minecraft.inventory.InventoryCrafting; 022 import net.minecraft.item.Item; 023 import net.minecraft.item.ItemStack; 024 import net.minecraft.item.crafting.CraftingManager; 025 import net.minecraft.nbt.NBTTagCompound; 026 import net.minecraft.util.MathHelper; 027 import net.minecraft.world.World; 028 029 import net.minecraftforge.common.IShearable; 030 031 public class EntitySheep extends EntityAnimal implements IShearable 032 { 033 private final InventoryCrafting field_90016_e = new InventoryCrafting(new ContainerSheep(this), 2, 1); 034 035 /** 036 * Holds the RGB table of the sheep colors - in OpenGL glColor3f values - used to render the sheep colored fleece. 037 */ 038 public static final float[][] fleeceColorTable = new float[][] {{1.0F, 1.0F, 1.0F}, {0.85F, 0.5F, 0.2F}, {0.7F, 0.3F, 0.85F}, {0.4F, 0.6F, 0.85F}, {0.9F, 0.9F, 0.2F}, {0.5F, 0.8F, 0.1F}, {0.95F, 0.5F, 0.65F}, {0.3F, 0.3F, 0.3F}, {0.6F, 0.6F, 0.6F}, {0.3F, 0.5F, 0.6F}, {0.5F, 0.25F, 0.7F}, {0.2F, 0.3F, 0.7F}, {0.4F, 0.3F, 0.2F}, {0.4F, 0.5F, 0.2F}, {0.6F, 0.2F, 0.2F}, {0.1F, 0.1F, 0.1F}}; 039 040 /** 041 * Used to control movement as well as wool regrowth. Set to 40 on handleHealthUpdate and counts down with each 042 * tick. 043 */ 044 private int sheepTimer; 045 046 /** The eat grass AI task for this mob. */ 047 private EntityAIEatGrass aiEatGrass = new EntityAIEatGrass(this); 048 049 public EntitySheep(World par1World) 050 { 051 super(par1World); 052 this.texture = "/mob/sheep.png"; 053 this.setSize(0.9F, 1.3F); 054 float var2 = 0.23F; 055 this.getNavigator().setAvoidsWater(true); 056 this.tasks.addTask(0, new EntityAISwimming(this)); 057 this.tasks.addTask(1, new EntityAIPanic(this, 0.38F)); 058 this.tasks.addTask(2, new EntityAIMate(this, var2)); 059 this.tasks.addTask(3, new EntityAITempt(this, 0.25F, Item.wheat.shiftedIndex, false)); 060 this.tasks.addTask(4, new EntityAIFollowParent(this, 0.25F)); 061 this.tasks.addTask(5, this.aiEatGrass); 062 this.tasks.addTask(6, new EntityAIWander(this, var2)); 063 this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F)); 064 this.tasks.addTask(8, new EntityAILookIdle(this)); 065 this.field_90016_e.setInventorySlotContents(0, new ItemStack(Item.dyePowder, 1, 0)); 066 this.field_90016_e.setInventorySlotContents(1, new ItemStack(Item.dyePowder, 1, 0)); 067 } 068 069 /** 070 * Returns true if the newer Entity AI code should be run 071 */ 072 protected boolean isAIEnabled() 073 { 074 return true; 075 } 076 077 protected void updateAITasks() 078 { 079 this.sheepTimer = this.aiEatGrass.getEatGrassTick(); 080 super.updateAITasks(); 081 } 082 083 /** 084 * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons 085 * use this to react to sunlight and start to burn. 086 */ 087 public void onLivingUpdate() 088 { 089 if (this.worldObj.isRemote) 090 { 091 this.sheepTimer = Math.max(0, this.sheepTimer - 1); 092 } 093 094 super.onLivingUpdate(); 095 } 096 097 public int getMaxHealth() 098 { 099 return 8; 100 } 101 102 protected void entityInit() 103 { 104 super.entityInit(); 105 this.dataWatcher.addObject(16, new Byte((byte)0)); 106 } 107 108 /** 109 * Drop 0-2 items of this living's type 110 */ 111 protected void dropFewItems(boolean par1, int par2) 112 { 113 if (!this.getSheared()) 114 { 115 this.entityDropItem(new ItemStack(Block.cloth.blockID, 1, this.getFleeceColor()), 0.0F); 116 } 117 } 118 119 /** 120 * Returns the item ID for the item the mob drops on death. 121 */ 122 protected int getDropItemId() 123 { 124 return Block.cloth.blockID; 125 } 126 127 @SideOnly(Side.CLIENT) 128 public void handleHealthUpdate(byte par1) 129 { 130 if (par1 == 10) 131 { 132 this.sheepTimer = 40; 133 } 134 else 135 { 136 super.handleHealthUpdate(par1); 137 } 138 } 139 140 /** 141 * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. 142 */ 143 public boolean interact(EntityPlayer par1EntityPlayer) 144 { 145 return super.interact(par1EntityPlayer); 146 } 147 148 @SideOnly(Side.CLIENT) 149 public float func_70894_j(float par1) 150 { 151 return this.sheepTimer <= 0 ? 0.0F : (this.sheepTimer >= 4 && this.sheepTimer <= 36 ? 1.0F : (this.sheepTimer < 4 ? ((float)this.sheepTimer - par1) / 4.0F : -((float)(this.sheepTimer - 40) - par1) / 4.0F)); 152 } 153 154 @SideOnly(Side.CLIENT) 155 public float func_70890_k(float par1) 156 { 157 if (this.sheepTimer > 4 && this.sheepTimer <= 36) 158 { 159 float var2 = ((float)(this.sheepTimer - 4) - par1) / 32.0F; 160 return ((float)Math.PI / 5F) + ((float)Math.PI * 7F / 100F) * MathHelper.sin(var2 * 28.7F); 161 } 162 else 163 { 164 return this.sheepTimer > 0 ? ((float)Math.PI / 5F) : this.rotationPitch / (180F / (float)Math.PI); 165 } 166 } 167 168 /** 169 * (abstract) Protected helper method to write subclass entity data to NBT. 170 */ 171 public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 172 { 173 super.writeEntityToNBT(par1NBTTagCompound); 174 par1NBTTagCompound.setBoolean("Sheared", this.getSheared()); 175 par1NBTTagCompound.setByte("Color", (byte)this.getFleeceColor()); 176 } 177 178 /** 179 * (abstract) Protected helper method to read subclass entity data from NBT. 180 */ 181 public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 182 { 183 super.readEntityFromNBT(par1NBTTagCompound); 184 this.setSheared(par1NBTTagCompound.getBoolean("Sheared")); 185 this.setFleeceColor(par1NBTTagCompound.getByte("Color")); 186 } 187 188 /** 189 * Returns the sound this mob makes while it's alive. 190 */ 191 protected String getLivingSound() 192 { 193 return "mob.sheep.say"; 194 } 195 196 /** 197 * Returns the sound this mob makes when it is hurt. 198 */ 199 protected String getHurtSound() 200 { 201 return "mob.sheep.say"; 202 } 203 204 /** 205 * Returns the sound this mob makes on death. 206 */ 207 protected String getDeathSound() 208 { 209 return "mob.sheep.say"; 210 } 211 212 /** 213 * Plays step sound at given x, y, z for the entity 214 */ 215 protected void playStepSound(int par1, int par2, int par3, int par4) 216 { 217 this.func_85030_a("mob.sheep.step", 0.15F, 1.0F); 218 } 219 220 public int getFleeceColor() 221 { 222 return this.dataWatcher.getWatchableObjectByte(16) & 15; 223 } 224 225 public void setFleeceColor(int par1) 226 { 227 byte var2 = this.dataWatcher.getWatchableObjectByte(16); 228 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & 240 | par1 & 15))); 229 } 230 231 /** 232 * returns true if a sheeps wool has been sheared 233 */ 234 public boolean getSheared() 235 { 236 return (this.dataWatcher.getWatchableObjectByte(16) & 16) != 0; 237 } 238 239 /** 240 * make a sheep sheared if set to true 241 */ 242 public void setSheared(boolean par1) 243 { 244 byte var2 = this.dataWatcher.getWatchableObjectByte(16); 245 246 if (par1) 247 { 248 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 | 16))); 249 } 250 else 251 { 252 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & -17))); 253 } 254 } 255 256 /** 257 * This method is called when a sheep spawns in the world to select the color of sheep fleece. 258 */ 259 public static int getRandomFleeceColor(Random par0Random) 260 { 261 int var1 = par0Random.nextInt(100); 262 return var1 < 5 ? 15 : (var1 < 10 ? 7 : (var1 < 15 ? 8 : (var1 < 18 ? 12 : (par0Random.nextInt(500) == 0 ? 6 : 0)))); 263 } 264 265 public EntitySheep func_90015_b(EntityAgeable par1EntityAgeable) 266 { 267 EntitySheep var2 = (EntitySheep)par1EntityAgeable; 268 EntitySheep var3 = new EntitySheep(this.worldObj); 269 int var4 = this.func_90014_a(this, var2); 270 var3.setFleeceColor(15 - var4); 271 return var3; 272 } 273 274 /** 275 * This function applies the benefits of growing back wool and faster growing up to the acting entity. (This 276 * function is used in the AIEatGrass) 277 */ 278 public void eatGrassBonus() 279 { 280 this.setSheared(false); 281 282 if (this.isChild()) 283 { 284 int var1 = this.getGrowingAge() + 1200; 285 286 if (var1 > 0) 287 { 288 var1 = 0; 289 } 290 291 this.setGrowingAge(var1); 292 } 293 } 294 295 /** 296 * Initialize this creature. 297 */ 298 public void initCreature() 299 { 300 this.setFleeceColor(getRandomFleeceColor(this.worldObj.rand)); 301 } 302 303 private int func_90014_a(EntityAnimal par1EntityAnimal, EntityAnimal par2EntityAnimal) 304 { 305 int var3 = this.func_90013_b(par1EntityAnimal); 306 int var4 = this.func_90013_b(par2EntityAnimal); 307 this.field_90016_e.getStackInSlot(0).setItemDamage(var3); 308 this.field_90016_e.getStackInSlot(1).setItemDamage(var4); 309 ItemStack var5 = CraftingManager.getInstance().findMatchingRecipe(this.field_90016_e, ((EntitySheep)par1EntityAnimal).worldObj); 310 int var6; 311 312 if (var5 != null && var5.getItem().shiftedIndex == Item.dyePowder.shiftedIndex) 313 { 314 var6 = var5.getItemDamage(); 315 } 316 else 317 { 318 var6 = this.worldObj.rand.nextBoolean() ? var3 : var4; 319 } 320 321 return var6; 322 } 323 324 private int func_90013_b(EntityAnimal par1EntityAnimal) 325 { 326 return 15 - ((EntitySheep)par1EntityAnimal).getFleeceColor(); 327 } 328 329 public EntityAgeable func_90011_a(EntityAgeable par1EntityAgeable) 330 { 331 return this.func_90015_b(par1EntityAgeable); 332 } 333 334 @Override 335 public boolean isShearable(ItemStack item, World world, int X, int Y, int Z) 336 { 337 return !getSheared() && !isChild(); 338 } 339 340 @Override 341 public ArrayList<ItemStack> onSheared(ItemStack item, World world, int X, int Y, int Z, int fortune) 342 { 343 ArrayList<ItemStack> ret = new ArrayList<ItemStack>(); 344 setSheared(true); 345 int i = 1 + rand.nextInt(3); 346 for (int j = 0; j < i; j++) 347 { 348 ret.add(new ItemStack(Block.cloth.blockID, 1, getFleeceColor())); 349 } 350 this.worldObj.playSoundAtEntity(this, "mob.sheep.shear", 1.0F, 1.0F); 351 return ret; 352 } 353 }