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