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    }