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