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