001package net.minecraft.entity.passive;
002
003import cpw.mods.fml.common.registry.VillagerRegistry;
004import cpw.mods.fml.relauncher.Side;
005import cpw.mods.fml.relauncher.SideOnly;
006import java.util.Collections;
007import java.util.HashMap;
008import java.util.Iterator;
009import java.util.Map;
010import java.util.Random;
011import net.minecraft.block.Block;
012import net.minecraft.enchantment.Enchantment;
013import net.minecraft.enchantment.EnchantmentData;
014import net.minecraft.enchantment.EnchantmentHelper;
015import net.minecraft.entity.Entity;
016import net.minecraft.entity.EntityAgeable;
017import net.minecraft.entity.EntityLiving;
018import net.minecraft.entity.IMerchant;
019import net.minecraft.entity.INpc;
020import net.minecraft.entity.ai.EntityAIAvoidEntity;
021import net.minecraft.entity.ai.EntityAIFollowGolem;
022import net.minecraft.entity.ai.EntityAILookAtTradePlayer;
023import net.minecraft.entity.ai.EntityAIMoveIndoors;
024import net.minecraft.entity.ai.EntityAIMoveTwardsRestriction;
025import net.minecraft.entity.ai.EntityAIOpenDoor;
026import net.minecraft.entity.ai.EntityAIPlay;
027import net.minecraft.entity.ai.EntityAIRestrictOpenDoor;
028import net.minecraft.entity.ai.EntityAISwimming;
029import net.minecraft.entity.ai.EntityAITradePlayer;
030import net.minecraft.entity.ai.EntityAIVillagerMate;
031import net.minecraft.entity.ai.EntityAIWander;
032import net.minecraft.entity.ai.EntityAIWatchClosest;
033import net.minecraft.entity.ai.EntityAIWatchClosest2;
034import net.minecraft.entity.monster.EntityZombie;
035import net.minecraft.entity.monster.IMob;
036import net.minecraft.entity.player.EntityPlayer;
037import net.minecraft.item.Item;
038import net.minecraft.item.ItemStack;
039import net.minecraft.nbt.NBTTagCompound;
040import net.minecraft.potion.Potion;
041import net.minecraft.potion.PotionEffect;
042import net.minecraft.util.ChunkCoordinates;
043import net.minecraft.util.DamageSource;
044import net.minecraft.util.MathHelper;
045import net.minecraft.util.Tuple;
046import net.minecraft.village.MerchantRecipe;
047import net.minecraft.village.MerchantRecipeList;
048import net.minecraft.village.Village;
049import net.minecraft.world.World;
050
051public 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_92090_c[this.rand.nextInt(Enchantment.field_92090_c.length)];
520                    int var10 = MathHelper.getRandomIntegerInRange(this.rand, var8.getMinLevel(), var8.getMaxLevel());
521                    ItemStack var11 = Item.enchantedBook.func_92111_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}