    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.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
    106            if (var2.tagCount() > 0)
    107            {
    108                par1ItemStack.setTagInfo("ench", var2);
    109            }
    110            else if (par1ItemStack.hasTagCompound())
    111            {
    112                par1ItemStack.getTagCompound().removeTag("ench");
    113            }
    114        }
    115
    116        /**
    117         * Returns the biggest level of the enchantment on the array of ItemStack passed.
    118         */
    119        private static int getMaxEnchantmentLevel(int par0, ItemStack[] par1ArrayOfItemStack)
    120        {
    121            int var2 = 0;
    122            ItemStack[] var3 = par1ArrayOfItemStack;
    123            int var4 = par1ArrayOfItemStack.length;
    124
    125            for (int var5 = 0; var5 < var4; ++var5)
    126            {
    127                ItemStack var6 = var3[var5];
    128                int var7 = getEnchantmentLevel(par0, var6);
    129
    130                if (var7 > var2)
    131                {
    132                    var2 = var7;
    133                }
    134            }
    135
    136            return var2;
    137        }
    138
    139        /**
    140         * Executes the enchantment modifier on the ItemStack passed.
    141         */
    142        private static void applyEnchantmentModifier(IEnchantmentModifier par0IEnchantmentModifier, ItemStack par1ItemStack)
    143        {
    144            if (par1ItemStack != null)
    145            {
    146                NBTTagList var2 = par1ItemStack.getEnchantmentTagList();
    147
    148                if (var2 != null)
    149                {
    150                    for (int var3 = 0; var3 < var2.tagCount(); ++var3)
    151                    {
    152                        short var4 = ((NBTTagCompound)var2.tagAt(var3)).getShort("id");
    153                        short var5 = ((NBTTagCompound)var2.tagAt(var3)).getShort("lvl");
    154
    155                        if (Enchantment.enchantmentsList[var4] != null)
    156                        {
    157                            par0IEnchantmentModifier.calculateModifier(Enchantment.enchantmentsList[var4], var5);
    158                        }
    159                    }
    160                }
    161            }
    162        }
    163
    164        /**
    165         * Executes the enchantment modifier on the array of ItemStack passed.
    166         */
    167        private static void applyEnchantmentModifierArray(IEnchantmentModifier par0IEnchantmentModifier, ItemStack[] par1ArrayOfItemStack)
    168        {
    169            ItemStack[] var2 = par1ArrayOfItemStack;
    170            int var3 = par1ArrayOfItemStack.length;
    171
    172            for (int var4 = 0; var4 < var3; ++var4)
    173            {
    174                ItemStack var5 = var2[var4];
    175                applyEnchantmentModifier(par0IEnchantmentModifier, var5);
    176            }
    177        }
    178
    179        /**
    180         * Returns the modifier of protection enchantments on armors equipped on player.
    181         */
    182        public static int getEnchantmentModifierDamage(ItemStack[] par0ArrayOfItemStack, DamageSource par1DamageSource)
    183        {
    184            enchantmentModifierDamage.damageModifier = 0;
    185            enchantmentModifierDamage.source = par1DamageSource;
    186            applyEnchantmentModifierArray(enchantmentModifierDamage, par0ArrayOfItemStack);
    187
    188            if (enchantmentModifierDamage.damageModifier > 25)
    189            {
    190                enchantmentModifierDamage.damageModifier = 25;
    191            }
    192
    193            return (enchantmentModifierDamage.damageModifier + 1 >> 1) + enchantmentRand.nextInt((enchantmentModifierDamage.damageModifier >> 1) + 1);
    194        }
    195
    196        /**
    197         * Return the (magic) extra damage of the enchantments on player equipped item.
    198         */
    199        public static int getEnchantmentModifierLiving(EntityLiving par0EntityLiving, EntityLiving par1EntityLiving)
    200        {
    201            enchantmentModifierLiving.livingModifier = 0;
    202            enchantmentModifierLiving.entityLiving = par1EntityLiving;
    203            applyEnchantmentModifier(enchantmentModifierLiving, par0EntityLiving.getHeldItem());
    204            return enchantmentModifierLiving.livingModifier > 0 ? 1 + enchantmentRand.nextInt(enchantmentModifierLiving.livingModifier) : 0;
    205        }
    206
    207        /**
    208         * Returns the knockback value of enchantments on equipped player item.
    209         */
    210        public static int getKnockbackModifier(EntityLiving par0EntityLiving, EntityLiving par1EntityLiving)
    211        {
    212            return getEnchantmentLevel(Enchantment.knockback.effectId, par0EntityLiving.getHeldItem());
    213        }
    214
    215        public static int func_90036_a(EntityLiving par0EntityLiving)
    216        {
    217            return getEnchantmentLevel(Enchantment.fireAspect.effectId, par0EntityLiving.getHeldItem());
    218        }
    219
    220        /**
    221         * Returns the 'Water Breathing' modifier of enchantments on player equipped armors.
    222         */
    223        public static int getRespiration(EntityLiving par0EntityLiving)
    224        {
    225            return getMaxEnchantmentLevel(Enchantment.respiration.effectId, par0EntityLiving.getLastActiveItems());
    226        }
    227
    228        /**
    229         * Return the extra efficiency of tools based on enchantments on equipped player item.
    230         */
    231        public static int getEfficiencyModifier(EntityLiving par0EntityLiving)
    232        {
    233            return getEnchantmentLevel(Enchantment.efficiency.effectId, par0EntityLiving.getHeldItem());
    234        }
    235
    236        /**
    237         * Returns the unbreaking enchantment modifier on current equipped item of player.
    238         */
    239        public static int getUnbreakingModifier(EntityLiving par0EntityLiving)
    240        {
    241            return getEnchantmentLevel(Enchantment.unbreaking.effectId, par0EntityLiving.getHeldItem());
    242        }
    243
    244        /**
    245         * Returns the silk touch status of enchantments on current equipped item of player.
    246         */
    247        public static boolean getSilkTouchModifier(EntityLiving par0EntityLiving)
    248        {
    249            return getEnchantmentLevel(Enchantment.silkTouch.effectId, par0EntityLiving.getHeldItem()) > 0;
    250        }
    251
    252        /**
    253         * Returns the fortune enchantment modifier of the current equipped item of player.
    254         */
    255        public static int getFortuneModifier(EntityLiving par0EntityLiving)
    256        {
    257            return getEnchantmentLevel(Enchantment.fortune.effectId, par0EntityLiving.getHeldItem());
    258        }
    259
    260        /**
    261         * Returns the looting enchantment modifier of the current equipped item of player.
    262         */
    263        public static int getLootingModifier(EntityLiving par0EntityLiving)
    264        {
    265            return getEnchantmentLevel(Enchantment.looting.effectId, par0EntityLiving.getHeldItem());
    266        }
    267
    268        /**
    269         * Returns the aqua affinity status of enchantments on current equipped item of player.
    270         */
    271        public static boolean getAquaAffinityModifier(EntityLiving par0EntityLiving)
    272        {
    273            return getMaxEnchantmentLevel(Enchantment.aquaAffinity.effectId, par0EntityLiving.getLastActiveItems()) > 0;
    274        }
    275
    276        /**
    277         * Returns the enchantability of itemstack, it's uses a singular formula for each index (2nd parameter: 0, 1 and 2),
    278         * cutting to the max enchantability power of the table (3rd parameter)
    279         */
    280        public static int calcItemStackEnchantability(Random par0Random, int par1, int par2, ItemStack par3ItemStack)
    281        {
    282            Item var4 = par3ItemStack.getItem();
    283            int var5 = var4.getItemEnchantability();
    284
    285            if (var5 <= 0)
    286            {
    287                return 0;
    288            }
    289            else
    290            {
    291                if (par2 > 15)
    292                {
    293                    par2 = 15;
    294                }
    295
    296                int var6 = par0Random.nextInt(8) + 1 + (par2 >> 1) + par0Random.nextInt(par2 + 1);
    297                return par1 == 0 ? Math.max(var6 / 3, 1) : (par1 == 1 ? var6 * 2 / 3 + 1 : Math.max(var6, par2 * 2));
    298            }
    299        }
    300
    301        /**
    302         * Adds a random enchantment to the specified item. Args: random, itemStack, enchantabilityLevel
    303         */
    304        public static ItemStack addRandomEnchantment(Random par0Random, ItemStack par1ItemStack, int par2)
    305        {
    306            List var3 = buildEnchantmentList(par0Random, par1ItemStack, par2);
    307
    308            if (var3 != null)
    309            {
    310                Iterator var4 = var3.iterator();
    311
    312                while (var4.hasNext())
    313                {
    314                    EnchantmentData var5 = (EnchantmentData)var4.next();
    315                    par1ItemStack.addEnchantment(var5.enchantmentobj, var5.enchantmentLevel);
    316                }
    317            }
    318
    319            return par1ItemStack;
    320        }
    321
    322        /**
    323         * Create a list of random EnchantmentData (enchantments) that can be added together to the ItemStack, the 3rd
    324         * parameter is the total enchantability level.
    325         */
    326        public static List buildEnchantmentList(Random par0Random, ItemStack par1ItemStack, int par2)
    327        {
    328            Item var3 = par1ItemStack.getItem();
    329            int var4 = var3.getItemEnchantability();
    330
    331            if (var4 <= 0)
    332            {
    333                return null;
    334            }
    335            else
    336            {
    337                var4 /= 2;
    338                var4 = 1 + par0Random.nextInt((var4 >> 1) + 1) + par0Random.nextInt((var4 >> 1) + 1);
    339                int var5 = var4 + par2;
    340                float var6 = (par0Random.nextFloat() + par0Random.nextFloat() - 1.0F) * 0.15F;
    341                int var7 = (int)((float)var5 * (1.0F + var6) + 0.5F);
    342
    343                if (var7 < 1)
    344                {
    345                    var7 = 1;
    346                }
    347
    348                ArrayList var8 = null;
    349                Map var9 = mapEnchantmentData(var7, par1ItemStack);
    350
    351                if (var9 != null && !var9.isEmpty())
    352                {
    353                    EnchantmentData var10 = (EnchantmentData)WeightedRandom.getRandomItem(par0Random, var9.values());
    354
    355                    if (var10 != null)
    356                    {
    357                        var8 = new ArrayList();
    358                        var8.add(var10);
    359
    360                        for (int var11 = var7; par0Random.nextInt(50) <= var11; var11 >>= 1)
    361                        {
    362                            Iterator var12 = var9.keySet().iterator();
    363
    364                            while (var12.hasNext())
    365                            {
    366                                Integer var13 = (Integer)var12.next();
    367                                boolean var14 = true;
    368                                Iterator var15 = var8.iterator();
    369
    370                                while (true)
    371                                {
    372                                    if (var15.hasNext())
    373                                    {
    374                                        EnchantmentData var16 = (EnchantmentData)var15.next();
    375
    376                                        if (var16.enchantmentobj.canApplyTogether(Enchantment.enchantmentsList[var13.intValue()]))
    377                                        {
    378                                            continue;
    379                                        }
    380
    381                                        var14 = false;
    382                                    }
    383
    384                                    if (!var14)
    385                                    {
    386                                        var12.remove();
    387                                    }
    388
    389                                    break;
    390                                }
    391                            }
    392
    393                            if (!var9.isEmpty())
    394                            {
    395                                EnchantmentData var17 = (EnchantmentData)WeightedRandom.getRandomItem(par0Random, var9.values());
    396                                var8.add(var17);
    397                            }
    398                        }
    399                    }
    400                }
    401
    402                return var8;
    403            }
    404        }
    405
    406        /**
    407         * Creates a 'Map' of EnchantmentData (enchantments) possible to add on the ItemStack and the enchantability level
    408         * passed.
    409         */
    410        public static Map mapEnchantmentData(int par0, ItemStack par1ItemStack)
    411        {
    412            Item var2 = par1ItemStack.getItem();
    413            HashMap var3 = null;
    414            Enchantment[] var4 = Enchantment.enchantmentsList;
    415            int var5 = var4.length;
    416
    417            for (int var6 = 0; var6 < var5; ++var6)
    418            {
    419                Enchantment var7 = var4[var6];
    420
    421                if (var7 != null && var7.canEnchantItem(par1ItemStack))
    422                {
    423                    for (int var8 = var7.getMinLevel(); var8 <= var7.getMaxLevel(); ++var8)
    424                    {
    425                        if (par0 >= var7.getMinEnchantability(var8) && par0 <= var7.getMaxEnchantability(var8))
    426                        {
    427                            if (var3 == null)
    428                            {
    429                                var3 = new HashMap();
    430                            }
    431
    432                            var3.put(Integer.valueOf(var7.effectId), new EnchantmentData(var7, var8));
    433                        }
    434                    }
    435                }
    436            }
    437
    438            return var3;
    439        }
    440    }