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 }