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