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    }