001 package net.minecraft.entity.passive;
002
003 import cpw.mods.fml.common.Side;
004 import cpw.mods.fml.common.asm.SideOnly;
005 import cpw.mods.fml.common.registry.VillagerRegistry;
006
007 import java.util.Collections;
008 import java.util.HashMap;
009 import java.util.Iterator;
010 import java.util.Map;
011 import java.util.Random;
012 import net.minecraft.block.Block;
013 import net.minecraft.enchantment.EnchantmentHelper;
014 import net.minecraft.entity.Entity;
015 import net.minecraft.entity.EntityAgeable;
016 import net.minecraft.entity.EntityLiving;
017 import net.minecraft.entity.IMerchant;
018 import net.minecraft.entity.INpc;
019 import net.minecraft.entity.ai.EntityAIAvoidEntity;
020 import net.minecraft.entity.ai.EntityAIFollowGolem;
021 import net.minecraft.entity.ai.EntityAILookAtTradePlayer;
022 import net.minecraft.entity.ai.EntityAIMoveIndoors;
023 import net.minecraft.entity.ai.EntityAIMoveTwardsRestriction;
024 import net.minecraft.entity.ai.EntityAIOpenDoor;
025 import net.minecraft.entity.ai.EntityAIPlay;
026 import net.minecraft.entity.ai.EntityAIRestrictOpenDoor;
027 import net.minecraft.entity.ai.EntityAISwimming;
028 import net.minecraft.entity.ai.EntityAITradePlayer;
029 import net.minecraft.entity.ai.EntityAIVillagerMate;
030 import net.minecraft.entity.ai.EntityAIWander;
031 import net.minecraft.entity.ai.EntityAIWatchClosest;
032 import net.minecraft.entity.ai.EntityAIWatchClosest2;
033 import net.minecraft.entity.monster.EntityZombie;
034 import net.minecraft.entity.monster.IMob;
035 import net.minecraft.entity.player.EntityPlayer;
036 import net.minecraft.item.Item;
037 import net.minecraft.item.ItemStack;
038 import net.minecraft.nbt.NBTTagCompound;
039 import net.minecraft.potion.Potion;
040 import net.minecraft.potion.PotionEffect;
041 import net.minecraft.util.ChunkCoordinates;
042 import net.minecraft.util.DamageSource;
043 import net.minecraft.util.MathHelper;
044 import net.minecraft.util.Tuple;
045 import net.minecraft.village.MerchantRecipe;
046 import net.minecraft.village.MerchantRecipeList;
047 import net.minecraft.village.Village;
048 import net.minecraft.world.World;
049
050 public class EntityVillager extends EntityAgeable implements INpc, IMerchant
051 {
052 private int randomTickDivider;
053 private boolean isMating;
054 private boolean isPlaying;
055 Village villageObj;
056
057 /** This villager's current customer. */
058 private EntityPlayer buyingPlayer;
059
060 /** Initialises the MerchantRecipeList.java */
061 private MerchantRecipeList buyingList;
062 private int timeUntilReset;
063
064 /** addDefaultEquipmentAndRecipies is called if this is true */
065 private boolean needsInitilization;
066 private int wealth;
067
068 /** Last player to trade with this villager, used for aggressivity. */
069 private String lastBuyingPlayer;
070 private boolean field_82190_bM;
071 private float field_82191_bN;
072
073 /**
074 * a villagers recipe list is intialized off this list ; the 2 params are min/max amount they will trade for 1
075 * emerald
076 */
077 public static final Map villagerStockList = new HashMap();
078
079 /**
080 * Selling list of Blacksmith items. negative numbers mean 1 emerald for n items, positive numbers are n emeralds
081 * for 1 item
082 */
083 public static final Map blacksmithSellingList = new HashMap();
084
085 public EntityVillager(World par1World)
086 {
087 this(par1World, 0);
088 }
089
090 public EntityVillager(World par1World, int par2)
091 {
092 super(par1World);
093 this.randomTickDivider = 0;
094 this.isMating = false;
095 this.isPlaying = false;
096 this.villageObj = null;
097 this.setProfession(par2);
098 this.texture = "/mob/villager/villager.png";
099 this.moveSpeed = 0.5F;
100 this.getNavigator().setBreakDoors(true);
101 this.getNavigator().setAvoidsWater(true);
102 this.tasks.addTask(0, new EntityAISwimming(this));
103 this.tasks.addTask(1, new EntityAIAvoidEntity(this, EntityZombie.class, 8.0F, 0.3F, 0.35F));
104 this.tasks.addTask(1, new EntityAITradePlayer(this));
105 this.tasks.addTask(1, new EntityAILookAtTradePlayer(this));
106 this.tasks.addTask(2, new EntityAIMoveIndoors(this));
107 this.tasks.addTask(3, new EntityAIRestrictOpenDoor(this));
108 this.tasks.addTask(4, new EntityAIOpenDoor(this, true));
109 this.tasks.addTask(5, new EntityAIMoveTwardsRestriction(this, 0.3F));
110 this.tasks.addTask(6, new EntityAIVillagerMate(this));
111 this.tasks.addTask(7, new EntityAIFollowGolem(this));
112 this.tasks.addTask(8, new EntityAIPlay(this, 0.32F));
113 this.tasks.addTask(9, new EntityAIWatchClosest2(this, EntityPlayer.class, 3.0F, 1.0F));
114 this.tasks.addTask(9, new EntityAIWatchClosest2(this, EntityVillager.class, 5.0F, 0.02F));
115 this.tasks.addTask(9, new EntityAIWander(this, 0.3F));
116 this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
117 }
118
119 /**
120 * Returns true if the newer Entity AI code should be run
121 */
122 public boolean isAIEnabled()
123 {
124 return true;
125 }
126
127 /**
128 * main AI tick function, replaces updateEntityActionState
129 */
130 protected void updateAITick()
131 {
132 if (--this.randomTickDivider <= 0)
133 {
134 this.worldObj.villageCollectionObj.addVillagerPosition(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
135 this.randomTickDivider = 70 + this.rand.nextInt(50);
136 this.villageObj = this.worldObj.villageCollectionObj.findNearestVillage(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ), 32);
137
138 if (this.villageObj == null)
139 {
140 this.detachHome();
141 }
142 else
143 {
144 ChunkCoordinates var1 = this.villageObj.getCenter();
145 this.setHomeArea(var1.posX, var1.posY, var1.posZ, (int)((float)this.villageObj.getVillageRadius() * 0.6F));
146
147 if (this.field_82190_bM)
148 {
149 this.field_82190_bM = false;
150 this.villageObj.func_82683_b(5);
151 }
152 }
153 }
154
155 if (!this.isTrading() && this.timeUntilReset > 0)
156 {
157 --this.timeUntilReset;
158
159 if (this.timeUntilReset <= 0)
160 {
161 if (this.needsInitilization)
162 {
163 if (this.buyingList.size() > 1)
164 {
165 Iterator var3 = this.buyingList.iterator();
166
167 while (var3.hasNext())
168 {
169 MerchantRecipe var2 = (MerchantRecipe)var3.next();
170
171 if (var2.func_82784_g())
172 {
173 var2.func_82783_a(this.rand.nextInt(6) + this.rand.nextInt(6) + 2);
174 }
175 }
176 }
177
178 this.addDefaultEquipmentAndRecipies(1);
179 this.needsInitilization = false;
180
181 if (this.villageObj != null && this.lastBuyingPlayer != null)
182 {
183 this.worldObj.setEntityState(this, (byte)14);
184 this.villageObj.setReputationForPlayer(this.lastBuyingPlayer, 1);
185 }
186 }
187
188 this.addPotionEffect(new PotionEffect(Potion.regeneration.id, 200, 0));
189 }
190 }
191
192 super.updateAITick();
193 }
194
195 /**
196 * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
197 */
198 public boolean interact(EntityPlayer par1EntityPlayer)
199 {
200 ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
201 boolean var3 = var2 != null && var2.itemID == Item.monsterPlacer.shiftedIndex;
202
203 if (!var3 && this.isEntityAlive() && !this.isTrading() && !this.isChild())
204 {
205 if (!this.worldObj.isRemote)
206 {
207 this.setCustomer(par1EntityPlayer);
208 par1EntityPlayer.displayGUIMerchant(this);
209 }
210
211 return true;
212 }
213 else
214 {
215 return super.interact(par1EntityPlayer);
216 }
217 }
218
219 protected void entityInit()
220 {
221 super.entityInit();
222 this.dataWatcher.addObject(16, Integer.valueOf(0));
223 }
224
225 public int getMaxHealth()
226 {
227 return 20;
228 }
229
230 /**
231 * (abstract) Protected helper method to write subclass entity data to NBT.
232 */
233 public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
234 {
235 super.writeEntityToNBT(par1NBTTagCompound);
236 par1NBTTagCompound.setInteger("Profession", this.getProfession());
237 par1NBTTagCompound.setInteger("Riches", this.wealth);
238
239 if (this.buyingList != null)
240 {
241 par1NBTTagCompound.setCompoundTag("Offers", this.buyingList.getRecipiesAsTags());
242 }
243 }
244
245 /**
246 * (abstract) Protected helper method to read subclass entity data from NBT.
247 */
248 public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
249 {
250 super.readEntityFromNBT(par1NBTTagCompound);
251 this.setProfession(par1NBTTagCompound.getInteger("Profession"));
252 this.wealth = par1NBTTagCompound.getInteger("Riches");
253
254 if (par1NBTTagCompound.hasKey("Offers"))
255 {
256 NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("Offers");
257 this.buyingList = new MerchantRecipeList(var2);
258 }
259 }
260
261 @SideOnly(Side.CLIENT)
262
263 /**
264 * Returns the texture's file path as a String.
265 */
266 public String getTexture()
267 {
268 switch (this.getProfession())
269 {
270 case 0:
271 return "/mob/villager/farmer.png";
272 case 1:
273 return "/mob/villager/librarian.png";
274 case 2:
275 return "/mob/villager/priest.png";
276 case 3:
277 return "/mob/villager/smith.png";
278 case 4:
279 return "/mob/villager/butcher.png";
280 default:
281 return VillagerRegistry.getVillagerSkin(this.getProfession(), super.getTexture());
282 }
283 }
284
285 /**
286 * Determines if an entity can be despawned, used on idle far away entities
287 */
288 protected boolean canDespawn()
289 {
290 return false;
291 }
292
293 /**
294 * Returns the sound this mob makes while it's alive.
295 */
296 protected String getLivingSound()
297 {
298 return "mob.villager.default";
299 }
300
301 /**
302 * Returns the sound this mob makes when it is hurt.
303 */
304 protected String getHurtSound()
305 {
306 return "mob.villager.defaulthurt";
307 }
308
309 /**
310 * Returns the sound this mob makes on death.
311 */
312 protected String getDeathSound()
313 {
314 return "mob.villager.defaultdeath";
315 }
316
317 public void setProfession(int par1)
318 {
319 this.dataWatcher.updateObject(16, Integer.valueOf(par1));
320 }
321
322 public int getProfession()
323 {
324 return this.dataWatcher.getWatchableObjectInt(16);
325 }
326
327 public boolean isMating()
328 {
329 return this.isMating;
330 }
331
332 public void setMating(boolean par1)
333 {
334 this.isMating = par1;
335 }
336
337 public void setPlaying(boolean par1)
338 {
339 this.isPlaying = par1;
340 }
341
342 public boolean isPlaying()
343 {
344 return this.isPlaying;
345 }
346
347 public void setRevengeTarget(EntityLiving par1EntityLiving)
348 {
349 super.setRevengeTarget(par1EntityLiving);
350
351 if (this.villageObj != null && par1EntityLiving != null)
352 {
353 this.villageObj.addOrRenewAgressor(par1EntityLiving);
354
355 if (par1EntityLiving instanceof EntityPlayer)
356 {
357 byte var2 = -1;
358
359 if (this.isChild())
360 {
361 var2 = -3;
362 }
363
364 this.villageObj.setReputationForPlayer(((EntityPlayer)par1EntityLiving).getCommandSenderName(), var2);
365
366 if (this.isEntityAlive())
367 {
368 this.worldObj.setEntityState(this, (byte)13);
369 }
370 }
371 }
372 }
373
374 /**
375 * Called when the mob's health reaches 0.
376 */
377 public void onDeath(DamageSource par1DamageSource)
378 {
379 if (this.villageObj != null)
380 {
381 Entity var2 = par1DamageSource.getEntity();
382
383 if (var2 != null)
384 {
385 if (var2 instanceof EntityPlayer)
386 {
387 this.villageObj.setReputationForPlayer(((EntityPlayer)var2).getCommandSenderName(), -2);
388 }
389 else if (var2 instanceof IMob)
390 {
391 this.villageObj.func_82692_h();
392 }
393 }
394 else if (var2 == null)
395 {
396 EntityPlayer var3 = this.worldObj.getClosestPlayerToEntity(this, 16.0D);
397
398 if (var3 != null)
399 {
400 this.villageObj.func_82692_h();
401 }
402 }
403 }
404
405 super.onDeath(par1DamageSource);
406 }
407
408 public void setCustomer(EntityPlayer par1EntityPlayer)
409 {
410 this.buyingPlayer = par1EntityPlayer;
411 }
412
413 public EntityPlayer getCustomer()
414 {
415 return this.buyingPlayer;
416 }
417
418 public boolean isTrading()
419 {
420 return this.buyingPlayer != null;
421 }
422
423 public void useRecipe(MerchantRecipe par1MerchantRecipe)
424 {
425 par1MerchantRecipe.incrementToolUses();
426
427 if (par1MerchantRecipe.hasSameIDsAs((MerchantRecipe)this.buyingList.get(this.buyingList.size() - 1)))
428 {
429 this.timeUntilReset = 40;
430 this.needsInitilization = true;
431
432 if (this.buyingPlayer != null)
433 {
434 this.lastBuyingPlayer = this.buyingPlayer.getCommandSenderName();
435 }
436 else
437 {
438 this.lastBuyingPlayer = null;
439 }
440 }
441
442 if (par1MerchantRecipe.getItemToBuy().itemID == Item.emerald.shiftedIndex)
443 {
444 this.wealth += par1MerchantRecipe.getItemToBuy().stackSize;
445 }
446 }
447
448 public MerchantRecipeList getRecipes(EntityPlayer par1EntityPlayer)
449 {
450 if (this.buyingList == null)
451 {
452 this.addDefaultEquipmentAndRecipies(1);
453 }
454
455 return this.buyingList;
456 }
457
458 private float func_82188_j(float par1)
459 {
460 float var2 = par1 + this.field_82191_bN;
461 return var2 > 0.9F ? 0.9F - (var2 - 0.9F) : var2;
462 }
463
464 /**
465 * based on the villagers profession add items, equipment, and recipies adds par1 random items to the list of things
466 * that the villager wants to buy. (at most 1 of each wanted type is added)
467 */
468 private void addDefaultEquipmentAndRecipies(int par1)
469 {
470 if (this.buyingList != null)
471 {
472 this.field_82191_bN = MathHelper.sqrt_float((float)this.buyingList.size()) * 0.2F;
473 }
474 else
475 {
476 this.field_82191_bN = 0.0F;
477 }
478
479 MerchantRecipeList var2;
480 var2 = new MerchantRecipeList();
481 VillagerRegistry.manageVillagerTrades(var2, this, this.getProfession(), this.rand);
482 label48:
483
484 switch (this.getProfession())
485 {
486 case 0:
487 addMerchantItem(var2, Item.wheat.shiftedIndex, this.rand, this.func_82188_j(0.9F));
488 addMerchantItem(var2, Block.cloth.blockID, this.rand, this.func_82188_j(0.5F));
489 addMerchantItem(var2, Item.chickenRaw.shiftedIndex, this.rand, this.func_82188_j(0.5F));
490 addMerchantItem(var2, Item.fishCooked.shiftedIndex, this.rand, this.func_82188_j(0.4F));
491 addBlacksmithItem(var2, Item.bread.shiftedIndex, this.rand, this.func_82188_j(0.9F));
492 addBlacksmithItem(var2, Item.melon.shiftedIndex, this.rand, this.func_82188_j(0.3F));
493 addBlacksmithItem(var2, Item.appleRed.shiftedIndex, this.rand, this.func_82188_j(0.3F));
494 addBlacksmithItem(var2, Item.cookie.shiftedIndex, this.rand, this.func_82188_j(0.3F));
495 addBlacksmithItem(var2, Item.shears.shiftedIndex, this.rand, this.func_82188_j(0.3F));
496 addBlacksmithItem(var2, Item.flintAndSteel.shiftedIndex, this.rand, this.func_82188_j(0.3F));
497 addBlacksmithItem(var2, Item.chickenCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F));
498 addBlacksmithItem(var2, Item.arrow.shiftedIndex, this.rand, this.func_82188_j(0.5F));
499
500 if (this.rand.nextFloat() < this.func_82188_j(0.5F))
501 {
502 var2.add(new MerchantRecipe(new ItemStack(Block.gravel, 10), new ItemStack(Item.emerald), new ItemStack(Item.flint.shiftedIndex, 4 + this.rand.nextInt(2), 0)));
503 }
504
505 break;
506 case 1:
507 addMerchantItem(var2, Item.paper.shiftedIndex, this.rand, this.func_82188_j(0.8F));
508 addMerchantItem(var2, Item.book.shiftedIndex, this.rand, this.func_82188_j(0.8F));
509 addMerchantItem(var2, Item.writtenBook.shiftedIndex, this.rand, this.func_82188_j(0.3F));
510 addBlacksmithItem(var2, Block.bookShelf.blockID, this.rand, this.func_82188_j(0.8F));
511 addBlacksmithItem(var2, Block.glass.blockID, this.rand, this.func_82188_j(0.2F));
512 addBlacksmithItem(var2, Item.compass.shiftedIndex, this.rand, this.func_82188_j(0.2F));
513 addBlacksmithItem(var2, Item.pocketSundial.shiftedIndex, this.rand, this.func_82188_j(0.2F));
514 break;
515 case 2:
516 addBlacksmithItem(var2, Item.eyeOfEnder.shiftedIndex, this.rand, this.func_82188_j(0.3F));
517 addBlacksmithItem(var2, Item.expBottle.shiftedIndex, this.rand, this.func_82188_j(0.2F));
518 addBlacksmithItem(var2, Item.redstone.shiftedIndex, this.rand, this.func_82188_j(0.4F));
519 addBlacksmithItem(var2, Block.glowStone.blockID, this.rand, this.func_82188_j(0.3F));
520 int[] var3 = new int[] {Item.swordSteel.shiftedIndex, Item.swordDiamond.shiftedIndex, Item.plateSteel.shiftedIndex, Item.plateDiamond.shiftedIndex, Item.axeSteel.shiftedIndex, Item.axeDiamond.shiftedIndex, Item.pickaxeSteel.shiftedIndex, Item.pickaxeDiamond.shiftedIndex};
521 int[] var4 = var3;
522 int var5 = var3.length;
523 int var6 = 0;
524
525 while (true)
526 {
527 if (var6 >= var5)
528 {
529 break label48;
530 }
531
532 int var7 = var4[var6];
533
534 if (this.rand.nextFloat() < this.func_82188_j(0.05F))
535 {
536 var2.add(new MerchantRecipe(new ItemStack(var7, 1, 0), new ItemStack(Item.emerald, 2 + this.rand.nextInt(3), 0), EnchantmentHelper.addRandomEnchantment(this.rand, new ItemStack(var7, 1, 0), 5 + this.rand.nextInt(15))));
537 }
538
539 ++var6;
540 }
541 case 3:
542 addMerchantItem(var2, Item.coal.shiftedIndex, this.rand, this.func_82188_j(0.7F));
543 addMerchantItem(var2, Item.ingotIron.shiftedIndex, this.rand, this.func_82188_j(0.5F));
544 addMerchantItem(var2, Item.ingotGold.shiftedIndex, this.rand, this.func_82188_j(0.5F));
545 addMerchantItem(var2, Item.diamond.shiftedIndex, this.rand, this.func_82188_j(0.5F));
546 addBlacksmithItem(var2, Item.swordSteel.shiftedIndex, this.rand, this.func_82188_j(0.5F));
547 addBlacksmithItem(var2, Item.swordDiamond.shiftedIndex, this.rand, this.func_82188_j(0.5F));
548 addBlacksmithItem(var2, Item.axeSteel.shiftedIndex, this.rand, this.func_82188_j(0.3F));
549 addBlacksmithItem(var2, Item.axeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.3F));
550 addBlacksmithItem(var2, Item.pickaxeSteel.shiftedIndex, this.rand, this.func_82188_j(0.5F));
551 addBlacksmithItem(var2, Item.pickaxeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.5F));
552 addBlacksmithItem(var2, Item.shovelSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
553 addBlacksmithItem(var2, Item.shovelDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
554 addBlacksmithItem(var2, Item.hoeSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
555 addBlacksmithItem(var2, Item.hoeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
556 addBlacksmithItem(var2, Item.bootsSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
557 addBlacksmithItem(var2, Item.bootsDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
558 addBlacksmithItem(var2, Item.helmetSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
559 addBlacksmithItem(var2, Item.helmetDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
560 addBlacksmithItem(var2, Item.plateSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
561 addBlacksmithItem(var2, Item.plateDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
562 addBlacksmithItem(var2, Item.legsSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
563 addBlacksmithItem(var2, Item.legsDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
564 addBlacksmithItem(var2, Item.bootsChain.shiftedIndex, this.rand, this.func_82188_j(0.1F));
565 addBlacksmithItem(var2, Item.helmetChain.shiftedIndex, this.rand, this.func_82188_j(0.1F));
566 addBlacksmithItem(var2, Item.plateChain.shiftedIndex, this.rand, this.func_82188_j(0.1F));
567 addBlacksmithItem(var2, Item.legsChain.shiftedIndex, this.rand, this.func_82188_j(0.1F));
568 break;
569 case 4:
570 addMerchantItem(var2, Item.coal.shiftedIndex, this.rand, this.func_82188_j(0.7F));
571 addMerchantItem(var2, Item.porkRaw.shiftedIndex, this.rand, this.func_82188_j(0.5F));
572 addMerchantItem(var2, Item.beefRaw.shiftedIndex, this.rand, this.func_82188_j(0.5F));
573 addBlacksmithItem(var2, Item.saddle.shiftedIndex, this.rand, this.func_82188_j(0.1F));
574 addBlacksmithItem(var2, Item.plateLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F));
575 addBlacksmithItem(var2, Item.bootsLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F));
576 addBlacksmithItem(var2, Item.helmetLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F));
577 addBlacksmithItem(var2, Item.legsLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F));
578 addBlacksmithItem(var2, Item.porkCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F));
579 addBlacksmithItem(var2, Item.beefCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F));
580 }
581
582 if (var2.isEmpty())
583 {
584 addMerchantItem(var2, Item.ingotGold.shiftedIndex, this.rand, 1.0F);
585 }
586
587 Collections.shuffle(var2);
588
589 if (this.buyingList == null)
590 {
591 this.buyingList = new MerchantRecipeList();
592 }
593
594 for (int var8 = 0; var8 < par1 && var8 < var2.size(); ++var8)
595 {
596 this.buyingList.addToListWithCheck((MerchantRecipe)var2.get(var8));
597 }
598 }
599
600 @SideOnly(Side.CLIENT)
601 public void setRecipes(MerchantRecipeList par1MerchantRecipeList) {}
602
603 /**
604 * each recipie takes a random stack from villagerStockList and offers it for 1 emerald
605 */
606 public static void addMerchantItem(MerchantRecipeList par0MerchantRecipeList, int par1, Random par2Random, float par3)
607 {
608 if (par2Random.nextFloat() < par3)
609 {
610 par0MerchantRecipeList.add(new MerchantRecipe(getRandomSizedStack(par1, par2Random), Item.emerald));
611 }
612 }
613
614 private static ItemStack getRandomSizedStack(int par0, Random par1Random)
615 {
616 return new ItemStack(par0, getRandomCountForItem(par0, par1Random), 0);
617 }
618
619 /**
620 * default to 1, and villagerStockList contains a min/max amount for each index
621 */
622 private static int getRandomCountForItem(int par0, Random par1Random)
623 {
624 Tuple var2 = (Tuple)villagerStockList.get(Integer.valueOf(par0));
625 return var2 == null ? 1 : (((Integer)var2.getFirst()).intValue() >= ((Integer)var2.getSecond()).intValue() ? ((Integer)var2.getFirst()).intValue() : ((Integer)var2.getFirst()).intValue() + par1Random.nextInt(((Integer)var2.getSecond()).intValue() - ((Integer)var2.getFirst()).intValue()));
626 }
627
628 public static void addBlacksmithItem(MerchantRecipeList par0MerchantRecipeList, int par1, Random par2Random, float par3)
629 {
630 if (par2Random.nextFloat() < par3)
631 {
632 int var4 = getRandomCountForBlacksmithItem(par1, par2Random);
633 ItemStack var5;
634 ItemStack var6;
635
636 if (var4 < 0)
637 {
638 var5 = new ItemStack(Item.emerald.shiftedIndex, 1, 0);
639 var6 = new ItemStack(par1, -var4, 0);
640 }
641 else
642 {
643 var5 = new ItemStack(Item.emerald.shiftedIndex, var4, 0);
644 var6 = new ItemStack(par1, 1, 0);
645 }
646
647 par0MerchantRecipeList.add(new MerchantRecipe(var5, var6));
648 }
649 }
650
651 private static int getRandomCountForBlacksmithItem(int par0, Random par1Random)
652 {
653 Tuple var2 = (Tuple)blacksmithSellingList.get(Integer.valueOf(par0));
654 return var2 == null ? 1 : (((Integer)var2.getFirst()).intValue() >= ((Integer)var2.getSecond()).intValue() ? ((Integer)var2.getFirst()).intValue() : ((Integer)var2.getFirst()).intValue() + par1Random.nextInt(((Integer)var2.getSecond()).intValue() - ((Integer)var2.getFirst()).intValue()));
655 }
656
657 @SideOnly(Side.CLIENT)
658 public void handleHealthUpdate(byte par1)
659 {
660 if (par1 == 12)
661 {
662 this.generateRandomParticles("heart");
663 }
664 else if (par1 == 13)
665 {
666 this.generateRandomParticles("angryVillager");
667 }
668 else if (par1 == 14)
669 {
670 this.generateRandomParticles("happyVillager");
671 }
672 else
673 {
674 super.handleHealthUpdate(par1);
675 }
676 }
677
678 @SideOnly(Side.CLIENT)
679
680 /**
681 * par1 is the particleName
682 */
683 private void generateRandomParticles(String par1Str)
684 {
685 for (int var2 = 0; var2 < 5; ++var2)
686 {
687 double var3 = this.rand.nextGaussian() * 0.02D;
688 double var5 = this.rand.nextGaussian() * 0.02D;
689 double var7 = this.rand.nextGaussian() * 0.02D;
690 this.worldObj.spawnParticle(par1Str, this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + 1.0D + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, var3, var5, var7);
691 }
692 }
693
694 /**
695 * Initialize this creature.
696 */
697 public void initCreature()
698 {
699 VillagerRegistry.applyRandomTrade(this, worldObj.rand);
700 }
701
702 public void func_82187_q()
703 {
704 this.field_82190_bM = true;
705 }
706
707 public EntityVillager func_90012_b(EntityAgeable par1EntityAgeable)
708 {
709 EntityVillager var2 = new EntityVillager(this.worldObj);
710 var2.initCreature();
711 return var2;
712 }
713
714 public EntityAgeable func_90011_a(EntityAgeable par1EntityAgeable)
715 {
716 return this.func_90012_b(par1EntityAgeable);
717 }
718
719 static
720 {
721 villagerStockList.put(Integer.valueOf(Item.coal.shiftedIndex), new Tuple(Integer.valueOf(16), Integer.valueOf(24)));
722 villagerStockList.put(Integer.valueOf(Item.ingotIron.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
723 villagerStockList.put(Integer.valueOf(Item.ingotGold.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
724 villagerStockList.put(Integer.valueOf(Item.diamond.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
725 villagerStockList.put(Integer.valueOf(Item.paper.shiftedIndex), new Tuple(Integer.valueOf(24), Integer.valueOf(36)));
726 villagerStockList.put(Integer.valueOf(Item.book.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(13)));
727 villagerStockList.put(Integer.valueOf(Item.writtenBook.shiftedIndex), new Tuple(Integer.valueOf(1), Integer.valueOf(1)));
728 villagerStockList.put(Integer.valueOf(Item.enderPearl.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
729 villagerStockList.put(Integer.valueOf(Item.eyeOfEnder.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(3)));
730 villagerStockList.put(Integer.valueOf(Item.porkRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
731 villagerStockList.put(Integer.valueOf(Item.beefRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
732 villagerStockList.put(Integer.valueOf(Item.chickenRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
733 villagerStockList.put(Integer.valueOf(Item.fishCooked.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(13)));
734 villagerStockList.put(Integer.valueOf(Item.seeds.shiftedIndex), new Tuple(Integer.valueOf(34), Integer.valueOf(48)));
735 villagerStockList.put(Integer.valueOf(Item.melonSeeds.shiftedIndex), new Tuple(Integer.valueOf(30), Integer.valueOf(38)));
736 villagerStockList.put(Integer.valueOf(Item.pumpkinSeeds.shiftedIndex), new Tuple(Integer.valueOf(30), Integer.valueOf(38)));
737 villagerStockList.put(Integer.valueOf(Item.wheat.shiftedIndex), new Tuple(Integer.valueOf(18), Integer.valueOf(22)));
738 villagerStockList.put(Integer.valueOf(Block.cloth.blockID), new Tuple(Integer.valueOf(14), Integer.valueOf(22)));
739 villagerStockList.put(Integer.valueOf(Item.rottenFlesh.shiftedIndex), new Tuple(Integer.valueOf(36), Integer.valueOf(64)));
740 blacksmithSellingList.put(Integer.valueOf(Item.flintAndSteel.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
741 blacksmithSellingList.put(Integer.valueOf(Item.shears.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
742 blacksmithSellingList.put(Integer.valueOf(Item.swordSteel.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(11)));
743 blacksmithSellingList.put(Integer.valueOf(Item.swordDiamond.shiftedIndex), new Tuple(Integer.valueOf(12), Integer.valueOf(14)));
744 blacksmithSellingList.put(Integer.valueOf(Item.axeSteel.shiftedIndex), new Tuple(Integer.valueOf(6), Integer.valueOf(8)));
745 blacksmithSellingList.put(Integer.valueOf(Item.axeDiamond.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(12)));
746 blacksmithSellingList.put(Integer.valueOf(Item.pickaxeSteel.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(9)));
747 blacksmithSellingList.put(Integer.valueOf(Item.pickaxeDiamond.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(12)));
748 blacksmithSellingList.put(Integer.valueOf(Item.shovelSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
749 blacksmithSellingList.put(Integer.valueOf(Item.shovelDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
750 blacksmithSellingList.put(Integer.valueOf(Item.hoeSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
751 blacksmithSellingList.put(Integer.valueOf(Item.hoeDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
752 blacksmithSellingList.put(Integer.valueOf(Item.bootsSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
753 blacksmithSellingList.put(Integer.valueOf(Item.bootsDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
754 blacksmithSellingList.put(Integer.valueOf(Item.helmetSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
755 blacksmithSellingList.put(Integer.valueOf(Item.helmetDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
756 blacksmithSellingList.put(Integer.valueOf(Item.plateSteel.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(14)));
757 blacksmithSellingList.put(Integer.valueOf(Item.plateDiamond.shiftedIndex), new Tuple(Integer.valueOf(16), Integer.valueOf(19)));
758 blacksmithSellingList.put(Integer.valueOf(Item.legsSteel.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
759 blacksmithSellingList.put(Integer.valueOf(Item.legsDiamond.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(14)));
760 blacksmithSellingList.put(Integer.valueOf(Item.bootsChain.shiftedIndex), new Tuple(Integer.valueOf(5), Integer.valueOf(7)));
761 blacksmithSellingList.put(Integer.valueOf(Item.helmetChain.shiftedIndex), new Tuple(Integer.valueOf(5), Integer.valueOf(7)));
762 blacksmithSellingList.put(Integer.valueOf(Item.plateChain.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(15)));
763 blacksmithSellingList.put(Integer.valueOf(Item.legsChain.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(11)));
764 blacksmithSellingList.put(Integer.valueOf(Item.bread.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-2)));
765 blacksmithSellingList.put(Integer.valueOf(Item.melon.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-4)));
766 blacksmithSellingList.put(Integer.valueOf(Item.appleRed.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-4)));
767 blacksmithSellingList.put(Integer.valueOf(Item.cookie.shiftedIndex), new Tuple(Integer.valueOf(-10), Integer.valueOf(-7)));
768 blacksmithSellingList.put(Integer.valueOf(Block.glass.blockID), new Tuple(Integer.valueOf(-5), Integer.valueOf(-3)));
769 blacksmithSellingList.put(Integer.valueOf(Block.bookShelf.blockID), new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
770 blacksmithSellingList.put(Integer.valueOf(Item.plateLeather.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(5)));
771 blacksmithSellingList.put(Integer.valueOf(Item.bootsLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
772 blacksmithSellingList.put(Integer.valueOf(Item.helmetLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
773 blacksmithSellingList.put(Integer.valueOf(Item.legsLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
774 blacksmithSellingList.put(Integer.valueOf(Item.saddle.shiftedIndex), new Tuple(Integer.valueOf(6), Integer.valueOf(8)));
775 blacksmithSellingList.put(Integer.valueOf(Item.expBottle.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-1)));
776 blacksmithSellingList.put(Integer.valueOf(Item.redstone.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-1)));
777 blacksmithSellingList.put(Integer.valueOf(Item.compass.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(12)));
778 blacksmithSellingList.put(Integer.valueOf(Item.pocketSundial.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(12)));
779 blacksmithSellingList.put(Integer.valueOf(Block.glowStone.blockID), new Tuple(Integer.valueOf(-3), Integer.valueOf(-1)));
780 blacksmithSellingList.put(Integer.valueOf(Item.porkCooked.shiftedIndex), new Tuple(Integer.valueOf(-7), Integer.valueOf(-5)));
781 blacksmithSellingList.put(Integer.valueOf(Item.beefCooked.shiftedIndex), new Tuple(Integer.valueOf(-7), Integer.valueOf(-5)));
782 blacksmithSellingList.put(Integer.valueOf(Item.chickenCooked.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-6)));
783 blacksmithSellingList.put(Integer.valueOf(Item.eyeOfEnder.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(11)));
784 blacksmithSellingList.put(Integer.valueOf(Item.arrow.shiftedIndex), new Tuple(Integer.valueOf(-12), Integer.valueOf(-8)));
785 }
786 }