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"; 170 } 171 172 /** 173 * Returns the sound this mob makes when it is hurt. 174 */ 175 protected String getHurtSound() 176 { 177 return "mob.sheep"; 178 } 179 180 /** 181 * Returns the sound this mob makes on death. 182 */ 183 protected String getDeathSound() 184 { 185 return "mob.sheep"; 186 } 187 188 public int getFleeceColor() 189 { 190 return this.dataWatcher.getWatchableObjectByte(16) & 15; 191 } 192 193 public void setFleeceColor(int par1) 194 { 195 byte var2 = this.dataWatcher.getWatchableObjectByte(16); 196 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & 240 | par1 & 15))); 197 } 198 199 /** 200 * returns true if a sheeps wool has been sheared 201 */ 202 public boolean getSheared() 203 { 204 return (this.dataWatcher.getWatchableObjectByte(16) & 16) != 0; 205 } 206 207 /** 208 * make a sheep sheared if set to true 209 */ 210 public void setSheared(boolean par1) 211 { 212 byte var2 = this.dataWatcher.getWatchableObjectByte(16); 213 214 if (par1) 215 { 216 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 | 16))); 217 } 218 else 219 { 220 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & -17))); 221 } 222 } 223 224 /** 225 * This method is called when a sheep spawns in the world to select the color of sheep fleece. 226 */ 227 public static int getRandomFleeceColor(Random par0Random) 228 { 229 int var1 = par0Random.nextInt(100); 230 return var1 < 5 ? 15 : (var1 < 10 ? 7 : (var1 < 15 ? 8 : (var1 < 18 ? 12 : (par0Random.nextInt(500) == 0 ? 6 : 0)))); 231 } 232 233 /** 234 * This function is used when two same-species animals in 'love mode' breed to generate the new baby animal. 235 */ 236 public EntityAnimal spawnBabyAnimal(EntityAnimal par1EntityAnimal) 237 { 238 EntitySheep var2 = (EntitySheep)par1EntityAnimal; 239 EntitySheep var3 = new EntitySheep(this.worldObj); 240 241 if (this.rand.nextBoolean()) 242 { 243 var3.setFleeceColor(this.getFleeceColor()); 244 } 245 else 246 { 247 var3.setFleeceColor(var2.getFleeceColor()); 248 } 249 250 return var3; 251 } 252 253 /** 254 * This function applies the benefits of growing back wool and faster growing up to the acting entity. (This 255 * function is used in the AIEatGrass) 256 */ 257 public void eatGrassBonus() 258 { 259 this.setSheared(false); 260 261 if (this.isChild()) 262 { 263 int var1 = this.getGrowingAge() + 1200; 264 265 if (var1 > 0) 266 { 267 var1 = 0; 268 } 269 270 this.setGrowingAge(var1); 271 } 272 } 273 274 @Override 275 public boolean isShearable(ItemStack item, World world, int X, int Y, int Z) 276 { 277 return !getSheared() && !isChild(); 278 } 279 280 @Override 281 public ArrayList<ItemStack> onSheared(ItemStack item, World world, int X, int Y, int Z, int fortune) 282 { 283 ArrayList<ItemStack> ret = new ArrayList<ItemStack>(); 284 setSheared(true); 285 int i = 1 + rand.nextInt(3); 286 for (int j = 0; j < i; j++) 287 { 288 ret.add(new ItemStack(Block.cloth.blockID, 1, getFleeceColor())); 289 } 290 return ret; 291 } 292 }