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 }