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