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