    001    package net.minecraft.enchantment;
    002
    003    import java.util.ArrayList;
    004    import java.util.HashMap;
    005    import java.util.Iterator;
    006    import java.util.LinkedHashMap;
    007    import java.util.List;
    008    import java.util.Map;
    009    import java.util.Random;
    010    import net.minecraft.entity.EntityLiving;
    011    import net.minecraft.item.Item;
    012    import net.minecraft.item.ItemStack;
    013    import net.minecraft.nbt.NBTTagCompound;
    014    import net.minecraft.nbt.NBTTagList;
    015    import net.minecraft.util.DamageSource;
    016    import net.minecraft.util.WeightedRandom;
    017
    018    public class EnchantmentHelper
    019    {
    020        /** Is the random seed of enchantment effects. */
    021        private static final Random enchantmentRand = new Random();
    022
    023        /**
    024         * Used to calculate the extra armor of enchantments on armors equipped on player.
    025         */
    026        private static final EnchantmentModifierDamage enchantmentModifierDamage = new EnchantmentModifierDamage((Empty3)null);
    027
    028        /**
    029         * Used to calculate the (magic) extra damage done by enchantments on current equipped item of player.
    030         */
    031        private static final EnchantmentModifierLiving enchantmentModifierLiving = new EnchantmentModifierLiving((Empty3)null);
    032
    033        /**
    034         * Returns the level of enchantment on the ItemStack passed.
    035         */
    036        public static int getEnchantmentLevel(int par0, ItemStack par1ItemStack)
    037        {
    038            if (par1ItemStack == null)
    039            {
    040                return 0;
    041            }
    042            else
    043            {
    044                NBTTagList var2 = par1ItemStack.getEnchantmentTagList();
    045
    046                if (var2 == null)
    047                {
    048                    return 0;
    049                }
    050                else
    051                {
    052                    for (int var3 = 0; var3 < var2.tagCount(); ++var3)
    053                    {
    054                        short var4 = ((NBTTagCompound)var2.tagAt(var3)).getShort("id");
    055                        short var5 = ((NBTTagCompound)var2.tagAt(var3)).getShort("lvl");
    056
    057                        if (var4 == par0)
    058                        {
    059                            return var5;
    060                        }
    061                    }
    062
    063                    return 0;
    064                }
    065            }
    066        }
    067
    068        /**
    069         * Return the enchantments for the specified stack.
    070         */
    071        public static Map getEnchantments(ItemStack par0ItemStack)
    072        {
    073            LinkedHashMap var1 = new LinkedHashMap();
    074            NBTTagList var2 = par0ItemStack.itemID == Item.field_92053_bW.shiftedIndex ? Item.field_92053_bW.func_92056_g(par0ItemStack) : par0ItemStack.getEnchantmentTagList();
    075
    076            if (var2 != null)
    077            {
    078                for (int var3 = 0; var3 < var2.tagCount(); ++var3)
    079                {
    080                    short var4 = ((NBTTagCompound)var2.tagAt(var3)).getShort("id");
    081                    short var5 = ((NBTTagCompound)var2.tagAt(var3)).getShort("lvl");
    082                    var1.put(Integer.valueOf(var4), Integer.valueOf(var5));
    083                }
    084            }
    085
    086            return var1;
    087        }
    088
    089        /**
    090         * Set the enchantments for the specified stack.
    091         */
    092        public static void setEnchantments(Map par0Map, ItemStack par1ItemStack)
    093        {
    094            NBTTagList var2 = new NBTTagList();
    095            Iterator var3 = par0Map.keySet().iterator();
    096
    097            while (var3.hasNext())
    098            {
    099                int var4 = ((Integer)var3.next()).intValue();
    100                NBTTagCompound var5 = new NBTTagCompound();
    101                var5.setShort("id", (short)var4);
    102                var5.setShort("lvl", (short)((Integer)par0Map.get(Integer.valueOf(var4))).intValue());
    103                var2.appendTag(var5);
    104
    105                if (par1ItemStack.itemID == Item.field_92053_bW.shiftedIndex)
    106                {
    107                    Item.field_92053_bW.func_92060_a(par1ItemStack, new EnchantmentData(var4, ((Integer)par0Map.get(Integer.valueOf(var4))).intValue()));
    108                }
    109            }
    110
    111            if (var2.tagCount() > 0)
    112            {
    113                if (par1ItemStack.itemID != Item.field_92053_bW.shiftedIndex)
    114                {
    115                    par1ItemStack.setTagInfo("ench", var2);
    116                }
    117            }
    118            else if (par1ItemStack.hasTagCompound())
    119            {
    120                par1ItemStack.getTagCompound().removeTag("ench");
    121            }
    122        }
    123
    124        /**
    125         * Returns the biggest level of the enchantment on the array of ItemStack passed.
    126         */
    127        public static int getMaxEnchantmentLevel(int par0, ItemStack[] par1ArrayOfItemStack)
    128        {
    129            if (par1ArrayOfItemStack == null)
    130            {
    131                return 0;
    132            }
    133            else
    134            {
    135                int var2 = 0;
    136                ItemStack[] var3 = par1ArrayOfItemStack;
    137                int var4 = par1ArrayOfItemStack.length;
    138
    139                for (int var5 = 0; var5 < var4; ++var5)
    140                {
    141                    ItemStack var6 = var3[var5];
    142                    int var7 = getEnchantmentLevel(par0, var6);
    143
    144                    if (var7 > var2)
    145                    {
    146                        var2 = var7;
    147                    }
    148                }
    149
    150                return var2;
    151            }
    152        }
    153
    154        /**
    155         * Executes the enchantment modifier on the ItemStack passed.
    156         */
    157        private static void applyEnchantmentModifier(IEnchantmentModifier par0IEnchantmentModifier, ItemStack par1ItemStack)
    158        {
    159            if (par1ItemStack != null)
    160            {
    161                NBTTagList var2 = par1ItemStack.getEnchantmentTagList();
    162
    163                if (var2 != null)
    164                {
    165                    for (int var3 = 0; var3 < var2.tagCount(); ++var3)
    166                    {
    167                        short var4 = ((NBTTagCompound)var2.tagAt(var3)).getShort("id");
    168                        short var5 = ((NBTTagCompound)var2.tagAt(var3)).getShort("lvl");
    169
    170                        if (Enchantment.enchantmentsList[var4] != null)
    171                        {
    172                            par0IEnchantmentModifier.calculateModifier(Enchantment.enchantmentsList[var4], var5);
    173                        }
    174                    }
    175                }
    176            }
    177        }
    178
    179        /**
    180         * Executes the enchantment modifier on the array of ItemStack passed.
    181         */
    182        private static void applyEnchantmentModifierArray(IEnchantmentModifier par0IEnchantmentModifier, ItemStack[] par1ArrayOfItemStack)
    183        {
    184            ItemStack[] var2 = par1ArrayOfItemStack;
    185            int var3 = par1ArrayOfItemStack.length;
    186
    187            for (int var4 = 0; var4 < var3; ++var4)
    188            {
    189                ItemStack var5 = var2[var4];
    190                applyEnchantmentModifier(par0IEnchantmentModifier, var5);
    191            }
    192        }
    193
    194        /**
    195         * Returns the modifier of protection enchantments on armors equipped on player.
    196         */
    197        public static int getEnchantmentModifierDamage(ItemStack[] par0ArrayOfItemStack, DamageSource par1DamageSource)
    198        {
    199            enchantmentModifierDamage.damageModifier = 0;
    200            enchantmentModifierDamage.source = par1DamageSource;
    201            applyEnchantmentModifierArray(enchantmentModifierDamage, par0ArrayOfItemStack);
    202
    203            if (enchantmentModifierDamage.damageModifier > 25)
    204            {
    205                enchantmentModifierDamage.damageModifier = 25;
    206            }
    207
    208            return (enchantmentModifierDamage.damageModifier + 1 >> 1) + enchantmentRand.nextInt((enchantmentModifierDamage.damageModifier >> 1) + 1);
    209        }
    210
    211        /**
    212         * Return the (magic) extra damage of the enchantments on player equipped item.
    213         */
    214        public static int getEnchantmentModifierLiving(EntityLiving par0EntityLiving, EntityLiving par1EntityLiving)
    215        {
    216            enchantmentModifierLiving.livingModifier = 0;
    217            enchantmentModifierLiving.entityLiving = par1EntityLiving;
    218            applyEnchantmentModifier(enchantmentModifierLiving, par0EntityLiving.getHeldItem());
    219            return enchantmentModifierLiving.livingModifier > 0 ? 1 + enchantmentRand.nextInt(enchantmentModifierLiving.livingModifier) : 0;
    220        }
    221
    222        /**
    223         * Returns the knockback value of enchantments on equipped player item.
    224         */
    225        public static int getKnockbackModifier(EntityLiving par0EntityLiving, EntityLiving par1EntityLiving)
    226        {
    227            return getEnchantmentLevel(Enchantment.knockback.effectId, par0EntityLiving.getHeldItem());
    228        }
    229
    230        public static int getFireAspectModifier(EntityLiving par0EntityLiving)
    231        {
    232            return getEnchantmentLevel(Enchantment.fireAspect.effectId, par0EntityLiving.getHeldItem());
    233        }
    234
    235        /**
    236         * Returns the 'Water Breathing' modifier of enchantments on player equipped armors.
    237         */
    238        public static int getRespiration(EntityLiving par0EntityLiving)
    239        {
    240            return getMaxEnchantmentLevel(Enchantment.respiration.effectId, par0EntityLiving.getLastActiveItems());
    241        }
    242
    243        /**
    244         * Return the extra efficiency of tools based on enchantments on equipped player item.
    245         */
    246        public static int getEfficiencyModifier(EntityLiving par0EntityLiving)
    247        {
    248            return getEnchantmentLevel(Enchantment.efficiency.effectId, par0EntityLiving.getHeldItem());
    249        }
    250
    251        /**
    252         * Returns the silk touch status of enchantments on current equipped item of player.
    253         */
    254        public static boolean getSilkTouchModifier(EntityLiving par0EntityLiving)
    255        {
    256            return getEnchantmentLevel(Enchantment.silkTouch.effectId, par0EntityLiving.getHeldItem()) > 0;
    257        }
    258
    259        /**
    260         * Returns the fortune enchantment modifier of the current equipped item of player.
    261         */
    262        public static int getFortuneModifier(EntityLiving par0EntityLiving)
    263        {
    264            return getEnchantmentLevel(Enchantment.fortune.effectId, par0EntityLiving.getHeldItem());
    265        }
    266
    267        /**
    268         * Returns the looting enchantment modifier of the current equipped item of player.
    269         */
    270        public static int getLootingModifier(EntityLiving par0EntityLiving)
    271        {
    272            return getEnchantmentLevel(Enchantment.looting.effectId, par0EntityLiving.getHeldItem());
    273        }
    274
    275        /**
    276         * Returns the aqua affinity status of enchantments on current equipped item of player.
    277         */
    278        public static boolean getAquaAffinityModifier(EntityLiving par0EntityLiving)
    279        {
    280            return getMaxEnchantmentLevel(Enchantment.aquaAffinity.effectId, par0EntityLiving.getLastActiveItems()) > 0;
    281        }
    282
    283        public static int func_92046_i(EntityLiving par0EntityLiving)
    284        {
    285            return getMaxEnchantmentLevel(Enchantment.field_92039_k.effectId, par0EntityLiving.getLastActiveItems());
    286        }
    287
    288        public static ItemStack func_92047_a(Enchantment par0Enchantment, EntityLiving par1EntityLiving)
    289        {
    290            ItemStack[] var2 = par1EntityLiving.getLastActiveItems();
    291            int var3 = var2.length;
    292
    293            for (int var4 = 0; var4 < var3; ++var4)
    294            {
    295                ItemStack var5 = var2[var4];
    296
    297                if (var5 != null && getEnchantmentLevel(par0Enchantment.effectId, var5) > 0)
    298                {
    299                    return var5;
    300                }
    301            }
    302
    303            return null;
    304        }
    305
    306        /**
    307         * Returns the enchantability of itemstack, it's uses a singular formula for each index (2nd parameter: 0, 1 and 2),
    308         * cutting to the max enchantability power of the table (3rd parameter)
    309         */
    310        public static int calcItemStackEnchantability(Random par0Random, int par1, int par2, ItemStack par3ItemStack)
    311        {
    312            Item var4 = par3ItemStack.getItem();
    313            int var5 = var4.getItemEnchantability();
    314
    315            if (var5 <= 0)
    316            {
    317                return 0;
    318            }
    319            else
    320            {
    321                if (par2 > 15)
    322                {
    323                    par2 = 15;
    324                }
    325
    326                int var6 = par0Random.nextInt(8) + 1 + (par2 >> 1) + par0Random.nextInt(par2 + 1);
    327                return par1 == 0 ? Math.max(var6 / 3, 1) : (par1 == 1 ? var6 * 2 / 3 + 1 : Math.max(var6, par2 * 2));
    328            }
    329        }
    330
    331        /**
    332         * Adds a random enchantment to the specified item. Args: random, itemStack, enchantabilityLevel
    333         */
    334        public static ItemStack addRandomEnchantment(Random par0Random, ItemStack par1ItemStack, int par2)
    335        {
    336            List var3 = buildEnchantmentList(par0Random, par1ItemStack, par2);
    337            boolean var4 = par1ItemStack.itemID == Item.book.shiftedIndex;
    338
    339            if (var4)
    340            {
    341                par1ItemStack.itemID = Item.field_92053_bW.shiftedIndex;
    342            }
    343
    344            if (var3 != null)
    345            {
    346                Iterator var5 = var3.iterator();
    347
    348                while (var5.hasNext())
    349                {
    350                    EnchantmentData var6 = (EnchantmentData)var5.next();
    351
    352                    if (var4)
    353                    {
    354                        Item.field_92053_bW.func_92060_a(par1ItemStack, var6);
    355                    }
    356                    else
    357                    {
    358                        par1ItemStack.addEnchantment(var6.enchantmentobj, var6.enchantmentLevel);
    359                    }
    360                }
    361            }
    362
    363            return par1ItemStack;
    364        }
    365
    366        /**
    367         * Create a list of random EnchantmentData (enchantments) that can be added together to the ItemStack, the 3rd
    368         * parameter is the total enchantability level.
    369         */
    370        public static List buildEnchantmentList(Random par0Random, ItemStack par1ItemStack, int par2)
    371        {
    372            Item var3 = par1ItemStack.getItem();
    373            int var4 = var3.getItemEnchantability();
    374
    375            if (var4 <= 0)
    376            {
    377                return null;
    378            }
    379            else
    380            {
    381                var4 /= 2;
    382                var4 = 1 + par0Random.nextInt((var4 >> 1) + 1) + par0Random.nextInt((var4 >> 1) + 1);
    383                int var5 = var4 + par2;
    384                float var6 = (par0Random.nextFloat() + par0Random.nextFloat() - 1.0F) * 0.15F;
    385                int var7 = (int)((float)var5 * (1.0F + var6) + 0.5F);
    386
    387                if (var7 < 1)
    388                {
    389                    var7 = 1;
    390                }
    391
    392                ArrayList var8 = null;
    393                Map var9 = mapEnchantmentData(var7, par1ItemStack);
    394
    395                if (var9 != null && !var9.isEmpty())
    396                {
    397                    EnchantmentData var10 = (EnchantmentData)WeightedRandom.getRandomItem(par0Random, var9.values());
    398
    399                    if (var10 != null)
    400                    {
    401                        var8 = new ArrayList();
    402                        var8.add(var10);
    403
    404                        for (int var11 = var7; par0Random.nextInt(50) <= var11; var11 >>= 1)
    405                        {
    406                            Iterator var12 = var9.keySet().iterator();
    407
    408                            while (var12.hasNext())
    409                            {
    410                                Integer var13 = (Integer)var12.next();
    411                                boolean var14 = true;
    412                                Iterator var15 = var8.iterator();
    413
    414                                while (true)
    415                                {
    416                                    if (var15.hasNext())
    417                                    {
    418                                        EnchantmentData var16 = (EnchantmentData)var15.next();
    419
    420                                        if (var16.enchantmentobj.canApplyTogether(Enchantment.enchantmentsList[var13.intValue()]))
    421                                        {
    422                                            continue;
    423                                        }
    424
    425                                        var14 = false;
    426                                    }
    427
    428                                    if (!var14)
    429                                    {
    430                                        var12.remove();
    431                                    }
    432
    433                                    break;
    434                                }
    435                            }
    436
    437                            if (!var9.isEmpty())
    438                            {
    439                                EnchantmentData var17 = (EnchantmentData)WeightedRandom.getRandomItem(par0Random, var9.values());
    440                                var8.add(var17);
    441                            }
    442                        }
    443                    }
    444                }
    445
    446                return var8;
    447            }
    448        }
    449
    450        /**
    451         * Creates a 'Map' of EnchantmentData (enchantments) possible to add on the ItemStack and the enchantability level
    452         * passed.
    453         */
    454        public static Map mapEnchantmentData(int par0, ItemStack par1ItemStack)
    455        {
    456            Item var2 = par1ItemStack.getItem();
    457            HashMap var3 = null;
    458            boolean var4 = par1ItemStack.itemID == Item.book.shiftedIndex;
    459            Enchantment[] var5 = Enchantment.enchantmentsList;
    460            int var6 = var5.length;
    461
    462            for (int var7 = 0; var7 < var6; ++var7)
    463            {
    464                Enchantment var8 = var5[var7];
    465
    466                if (var8 != null && (var8.canApplyAtEnchantingTable(par1ItemStack) || var4))
    467                {
    468                    for (int var9 = var8.getMinLevel(); var9 <= var8.getMaxLevel(); ++var9)
    469                    {
    470                        if (par0 >= var8.getMinEnchantability(var9) && par0 <= var8.getMaxEnchantability(var9))
    471                        {
    472                            if (var3 == null)
    473                            {
    474                                var3 = new HashMap();
    475                            }
    476
    477                            var3.put(Integer.valueOf(var8.effectId), new EnchantmentData(var8, var9));
    478                        }
    479                    }
    480                }
    481            }
    482
    483            return var3;
    484        }
    485    }