    001    package net.minecraft.entity.passive;
    002
    003    import cpw.mods.fml.common.registry.VillagerRegistry;
    004    import cpw.mods.fml.relauncher.Side;
    005    import cpw.mods.fml.relauncher.SideOnly;
    006    import java.util.Collections;
    007    import java.util.HashMap;
    008    import java.util.Iterator;
    009    import java.util.Map;
    010    import java.util.Random;
    011    import net.minecraft.block.Block;
    012    import net.minecraft.enchantment.Enchantment;
    013    import net.minecraft.enchantment.EnchantmentData;
    014    import net.minecraft.enchantment.EnchantmentHelper;
    015    import net.minecraft.entity.Entity;
    016    import net.minecraft.entity.EntityAgeable;
    017    import net.minecraft.entity.EntityLiving;
    018    import net.minecraft.entity.IMerchant;
    019    import net.minecraft.entity.INpc;
    020    import net.minecraft.entity.ai.EntityAIAvoidEntity;
    021    import net.minecraft.entity.ai.EntityAIFollowGolem;
    022    import net.minecraft.entity.ai.EntityAILookAtTradePlayer;
    023    import net.minecraft.entity.ai.EntityAIMoveIndoors;
    024    import net.minecraft.entity.ai.EntityAIMoveTwardsRestriction;
    025    import net.minecraft.entity.ai.EntityAIOpenDoor;
    026    import net.minecraft.entity.ai.EntityAIPlay;
    027    import net.minecraft.entity.ai.EntityAIRestrictOpenDoor;
    028    import net.minecraft.entity.ai.EntityAISwimming;
    029    import net.minecraft.entity.ai.EntityAITradePlayer;
    030    import net.minecraft.entity.ai.EntityAIVillagerMate;
    031    import net.minecraft.entity.ai.EntityAIWander;
    032    import net.minecraft.entity.ai.EntityAIWatchClosest;
    033    import net.minecraft.entity.ai.EntityAIWatchClosest2;
    034    import net.minecraft.entity.monster.EntityZombie;
    035    import net.minecraft.entity.monster.IMob;
    036    import net.minecraft.entity.player.EntityPlayer;
    037    import net.minecraft.item.Item;
    038    import net.minecraft.item.ItemStack;
    039    import net.minecraft.nbt.NBTTagCompound;
    040    import net.minecraft.potion.Potion;
    041    import net.minecraft.potion.PotionEffect;
    042    import net.minecraft.util.ChunkCoordinates;
    043    import net.minecraft.util.DamageSource;
    044    import net.minecraft.util.MathHelper;
    045    import net.minecraft.util.Tuple;
    046    import net.minecraft.village.MerchantRecipe;
    047    import net.minecraft.village.MerchantRecipeList;
    048    import net.minecraft.village.Village;
    049    import net.minecraft.world.World;
    050
    051    public 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.shiftedIndex;
    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.func_82692_h();
    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.func_82692_h();
    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.shiftedIndex)
    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.shiftedIndex, 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.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    492                    addMerchantItem(var2, Item.fishCooked.shiftedIndex, this.rand, this.func_82188_j(0.4F));
    493                    addBlacksmithItem(var2, Item.bread.shiftedIndex, this.rand, this.func_82188_j(0.9F));
    494                    addBlacksmithItem(var2, Item.melon.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    495                    addBlacksmithItem(var2, Item.appleRed.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    496                    addBlacksmithItem(var2, Item.cookie.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    497                    addBlacksmithItem(var2, Item.shears.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    498                    addBlacksmithItem(var2, Item.flintAndSteel.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    499                    addBlacksmithItem(var2, Item.chickenCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    500                    addBlacksmithItem(var2, Item.arrow.shiftedIndex, 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.shiftedIndex, 4 + this.rand.nextInt(2), 0)));
    505                    }
    506
    507                    break;
    508                case 1:
    509                    addMerchantItem(var2, Item.paper.shiftedIndex, this.rand, this.func_82188_j(0.8F));
    510                    addMerchantItem(var2, Item.book.shiftedIndex, this.rand, this.func_82188_j(0.8F));
    511                    addMerchantItem(var2, Item.writtenBook.shiftedIndex, 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.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    515                    addBlacksmithItem(var2, Item.pocketSundial.shiftedIndex, 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_92038_c[this.rand.nextInt(Enchantment.field_92038_c.length)];
    520                        int var10 = MathHelper.getRandomIntegerInRange(this.rand, var8.getMinLevel(), var8.getMaxLevel());
    521                        ItemStack var11 = Item.field_92053_bW.func_92057_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.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    529                    addBlacksmithItem(var2, Item.expBottle.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    530                    addBlacksmithItem(var2, Item.redstone.shiftedIndex, 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.shiftedIndex, Item.swordDiamond.shiftedIndex, Item.plateSteel.shiftedIndex, Item.plateDiamond.shiftedIndex, Item.axeSteel.shiftedIndex, Item.axeDiamond.shiftedIndex, Item.pickaxeSteel.shiftedIndex, Item.pickaxeDiamond.shiftedIndex};
    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.shiftedIndex, this.rand, this.func_82188_j(0.7F));
    555                    addMerchantItem(var2, Item.ingotIron.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    556                    addMerchantItem(var2, Item.ingotGold.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    557                    addMerchantItem(var2, Item.diamond.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    558                    addBlacksmithItem(var2, Item.swordSteel.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    559                    addBlacksmithItem(var2, Item.swordDiamond.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    560                    addBlacksmithItem(var2, Item.axeSteel.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    561                    addBlacksmithItem(var2, Item.axeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    562                    addBlacksmithItem(var2, Item.pickaxeSteel.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    563                    addBlacksmithItem(var2, Item.pickaxeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    564                    addBlacksmithItem(var2, Item.shovelSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    565                    addBlacksmithItem(var2, Item.shovelDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    566                    addBlacksmithItem(var2, Item.hoeSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    567                    addBlacksmithItem(var2, Item.hoeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    568                    addBlacksmithItem(var2, Item.bootsSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    569                    addBlacksmithItem(var2, Item.bootsDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    570                    addBlacksmithItem(var2, Item.helmetSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    571                    addBlacksmithItem(var2, Item.helmetDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    572                    addBlacksmithItem(var2, Item.plateSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    573                    addBlacksmithItem(var2, Item.plateDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    574                    addBlacksmithItem(var2, Item.legsSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    575                    addBlacksmithItem(var2, Item.legsDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F));
    576                    addBlacksmithItem(var2, Item.bootsChain.shiftedIndex, this.rand, this.func_82188_j(0.1F));
    577                    addBlacksmithItem(var2, Item.helmetChain.shiftedIndex, this.rand, this.func_82188_j(0.1F));
    578                    addBlacksmithItem(var2, Item.plateChain.shiftedIndex, this.rand, this.func_82188_j(0.1F));
    579                    addBlacksmithItem(var2, Item.legsChain.shiftedIndex, this.rand, this.func_82188_j(0.1F));
    580                    break;
    581                case 4:
    582                    addMerchantItem(var2, Item.coal.shiftedIndex, this.rand, this.func_82188_j(0.7F));
    583                    addMerchantItem(var2, Item.porkRaw.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    584                    addMerchantItem(var2, Item.beefRaw.shiftedIndex, this.rand, this.func_82188_j(0.5F));
    585                    addBlacksmithItem(var2, Item.saddle.shiftedIndex, this.rand, this.func_82188_j(0.1F));
    586                    addBlacksmithItem(var2, Item.plateLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    587                    addBlacksmithItem(var2, Item.bootsLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    588                    addBlacksmithItem(var2, Item.helmetLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    589                    addBlacksmithItem(var2, Item.legsLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    590                    addBlacksmithItem(var2, Item.porkCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    591                    addBlacksmithItem(var2, Item.beefCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F));
    592            }
    593
    594            if (var2.isEmpty())
    595            {
    596                addMerchantItem(var2, Item.ingotGold.shiftedIndex, 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.shiftedIndex, 1, 0);
    651                    var6 = new ItemStack(par1, -var4, 0);
    652                }
    653                else
    654                {
    655                    var5 = new ItemStack(Item.emerald.shiftedIndex, 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 func_90011_a(EntityAgeable par1EntityAgeable)
    727        {
    728            return this.func_90012_b(par1EntityAgeable);
    729        }
    730
    731        static
    732        {
    733            villagerStockList.put(Integer.valueOf(Item.coal.shiftedIndex), new Tuple(Integer.valueOf(16), Integer.valueOf(24)));
    734            villagerStockList.put(Integer.valueOf(Item.ingotIron.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
    735            villagerStockList.put(Integer.valueOf(Item.ingotGold.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
    736            villagerStockList.put(Integer.valueOf(Item.diamond.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
    737            villagerStockList.put(Integer.valueOf(Item.paper.shiftedIndex), new Tuple(Integer.valueOf(24), Integer.valueOf(36)));
    738            villagerStockList.put(Integer.valueOf(Item.book.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(13)));
    739            villagerStockList.put(Integer.valueOf(Item.writtenBook.shiftedIndex), new Tuple(Integer.valueOf(1), Integer.valueOf(1)));
    740            villagerStockList.put(Integer.valueOf(Item.enderPearl.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
    741            villagerStockList.put(Integer.valueOf(Item.eyeOfEnder.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(3)));
    742            villagerStockList.put(Integer.valueOf(Item.porkRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
    743            villagerStockList.put(Integer.valueOf(Item.beefRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
    744            villagerStockList.put(Integer.valueOf(Item.chickenRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
    745            villagerStockList.put(Integer.valueOf(Item.fishCooked.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(13)));
    746            villagerStockList.put(Integer.valueOf(Item.seeds.shiftedIndex), new Tuple(Integer.valueOf(34), Integer.valueOf(48)));
    747            villagerStockList.put(Integer.valueOf(Item.melonSeeds.shiftedIndex), new Tuple(Integer.valueOf(30), Integer.valueOf(38)));
    748            villagerStockList.put(Integer.valueOf(Item.pumpkinSeeds.shiftedIndex), new Tuple(Integer.valueOf(30), Integer.valueOf(38)));
    749            villagerStockList.put(Integer.valueOf(Item.wheat.shiftedIndex), 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.shiftedIndex), new Tuple(Integer.valueOf(36), Integer.valueOf(64)));
    752            blacksmithSellingList.put(Integer.valueOf(Item.flintAndSteel.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
    753            blacksmithSellingList.put(Integer.valueOf(Item.shears.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
    754            blacksmithSellingList.put(Integer.valueOf(Item.swordSteel.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(11)));
    755            blacksmithSellingList.put(Integer.valueOf(Item.swordDiamond.shiftedIndex), new Tuple(Integer.valueOf(12), Integer.valueOf(14)));
    756            blacksmithSellingList.put(Integer.valueOf(Item.axeSteel.shiftedIndex), new Tuple(Integer.valueOf(6), Integer.valueOf(8)));
    757            blacksmithSellingList.put(Integer.valueOf(Item.axeDiamond.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(12)));
    758            blacksmithSellingList.put(Integer.valueOf(Item.pickaxeSteel.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(9)));
    759            blacksmithSellingList.put(Integer.valueOf(Item.pickaxeDiamond.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(12)));
    760            blacksmithSellingList.put(Integer.valueOf(Item.shovelSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
    761            blacksmithSellingList.put(Integer.valueOf(Item.shovelDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
    762            blacksmithSellingList.put(Integer.valueOf(Item.hoeSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
    763            blacksmithSellingList.put(Integer.valueOf(Item.hoeDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
    764            blacksmithSellingList.put(Integer.valueOf(Item.bootsSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
    765            blacksmithSellingList.put(Integer.valueOf(Item.bootsDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
    766            blacksmithSellingList.put(Integer.valueOf(Item.helmetSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
    767            blacksmithSellingList.put(Integer.valueOf(Item.helmetDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
    768            blacksmithSellingList.put(Integer.valueOf(Item.plateSteel.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(14)));
    769            blacksmithSellingList.put(Integer.valueOf(Item.plateDiamond.shiftedIndex), new Tuple(Integer.valueOf(16), Integer.valueOf(19)));
    770            blacksmithSellingList.put(Integer.valueOf(Item.legsSteel.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
    771            blacksmithSellingList.put(Integer.valueOf(Item.legsDiamond.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(14)));
    772            blacksmithSellingList.put(Integer.valueOf(Item.bootsChain.shiftedIndex), new Tuple(Integer.valueOf(5), Integer.valueOf(7)));
    773            blacksmithSellingList.put(Integer.valueOf(Item.helmetChain.shiftedIndex), new Tuple(Integer.valueOf(5), Integer.valueOf(7)));
    774            blacksmithSellingList.put(Integer.valueOf(Item.plateChain.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(15)));
    775            blacksmithSellingList.put(Integer.valueOf(Item.legsChain.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(11)));
    776            blacksmithSellingList.put(Integer.valueOf(Item.bread.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-2)));
    777            blacksmithSellingList.put(Integer.valueOf(Item.melon.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-4)));
    778            blacksmithSellingList.put(Integer.valueOf(Item.appleRed.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-4)));
    779            blacksmithSellingList.put(Integer.valueOf(Item.cookie.shiftedIndex), 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.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(5)));
    783            blacksmithSellingList.put(Integer.valueOf(Item.bootsLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
    784            blacksmithSellingList.put(Integer.valueOf(Item.helmetLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
    785            blacksmithSellingList.put(Integer.valueOf(Item.legsLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
    786            blacksmithSellingList.put(Integer.valueOf(Item.saddle.shiftedIndex), new Tuple(Integer.valueOf(6), Integer.valueOf(8)));
    787            blacksmithSellingList.put(Integer.valueOf(Item.expBottle.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-1)));
    788            blacksmithSellingList.put(Integer.valueOf(Item.redstone.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-1)));
    789            blacksmithSellingList.put(Integer.valueOf(Item.compass.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(12)));
    790            blacksmithSellingList.put(Integer.valueOf(Item.pocketSundial.shiftedIndex), 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.shiftedIndex), new Tuple(Integer.valueOf(-7), Integer.valueOf(-5)));
    793            blacksmithSellingList.put(Integer.valueOf(Item.beefCooked.shiftedIndex), new Tuple(Integer.valueOf(-7), Integer.valueOf(-5)));
    794            blacksmithSellingList.put(Integer.valueOf(Item.chickenCooked.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-6)));
    795            blacksmithSellingList.put(Integer.valueOf(Item.eyeOfEnder.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(11)));
    796            blacksmithSellingList.put(Integer.valueOf(Item.arrow.shiftedIndex), new Tuple(Integer.valueOf(-12), Integer.valueOf(-8)));
    797        }
    798    }