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