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