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