    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}