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