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