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 }