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