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.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 106 if (var2.tagCount() > 0) 107 { 108 par1ItemStack.setTagInfo("ench", var2); 109 } 110 else if (par1ItemStack.hasTagCompound()) 111 { 112 par1ItemStack.getTagCompound().removeTag("ench"); 113 } 114 } 115 116 /** 117 * Returns the biggest level of the enchantment on the array of ItemStack passed. 118 */ 119 private static int getMaxEnchantmentLevel(int par0, ItemStack[] par1ArrayOfItemStack) 120 { 121 int var2 = 0; 122 ItemStack[] var3 = par1ArrayOfItemStack; 123 int var4 = par1ArrayOfItemStack.length; 124 125 for (int var5 = 0; var5 < var4; ++var5) 126 { 127 ItemStack var6 = var3[var5]; 128 int var7 = getEnchantmentLevel(par0, var6); 129 130 if (var7 > var2) 131 { 132 var2 = var7; 133 } 134 } 135 136 return var2; 137 } 138 139 /** 140 * Executes the enchantment modifier on the ItemStack passed. 141 */ 142 private static void applyEnchantmentModifier(IEnchantmentModifier par0IEnchantmentModifier, ItemStack par1ItemStack) 143 { 144 if (par1ItemStack != null) 145 { 146 NBTTagList var2 = par1ItemStack.getEnchantmentTagList(); 147 148 if (var2 != null) 149 { 150 for (int var3 = 0; var3 < var2.tagCount(); ++var3) 151 { 152 short var4 = ((NBTTagCompound)var2.tagAt(var3)).getShort("id"); 153 short var5 = ((NBTTagCompound)var2.tagAt(var3)).getShort("lvl"); 154 155 if (Enchantment.enchantmentsList[var4] != null) 156 { 157 par0IEnchantmentModifier.calculateModifier(Enchantment.enchantmentsList[var4], var5); 158 } 159 } 160 } 161 } 162 } 163 164 /** 165 * Executes the enchantment modifier on the array of ItemStack passed. 166 */ 167 private static void applyEnchantmentModifierArray(IEnchantmentModifier par0IEnchantmentModifier, ItemStack[] par1ArrayOfItemStack) 168 { 169 ItemStack[] var2 = par1ArrayOfItemStack; 170 int var3 = par1ArrayOfItemStack.length; 171 172 for (int var4 = 0; var4 < var3; ++var4) 173 { 174 ItemStack var5 = var2[var4]; 175 applyEnchantmentModifier(par0IEnchantmentModifier, var5); 176 } 177 } 178 179 /** 180 * Returns the modifier of protection enchantments on armors equipped on player. 181 */ 182 public static int getEnchantmentModifierDamage(ItemStack[] par0ArrayOfItemStack, DamageSource par1DamageSource) 183 { 184 enchantmentModifierDamage.damageModifier = 0; 185 enchantmentModifierDamage.source = par1DamageSource; 186 applyEnchantmentModifierArray(enchantmentModifierDamage, par0ArrayOfItemStack); 187 188 if (enchantmentModifierDamage.damageModifier > 25) 189 { 190 enchantmentModifierDamage.damageModifier = 25; 191 } 192 193 return (enchantmentModifierDamage.damageModifier + 1 >> 1) + enchantmentRand.nextInt((enchantmentModifierDamage.damageModifier >> 1) + 1); 194 } 195 196 /** 197 * Return the (magic) extra damage of the enchantments on player equipped item. 198 */ 199 public static int getEnchantmentModifierLiving(EntityLiving par0EntityLiving, EntityLiving par1EntityLiving) 200 { 201 enchantmentModifierLiving.livingModifier = 0; 202 enchantmentModifierLiving.entityLiving = par1EntityLiving; 203 applyEnchantmentModifier(enchantmentModifierLiving, par0EntityLiving.getHeldItem()); 204 return enchantmentModifierLiving.livingModifier > 0 ? 1 + enchantmentRand.nextInt(enchantmentModifierLiving.livingModifier) : 0; 205 } 206 207 /** 208 * Returns the knockback value of enchantments on equipped player item. 209 */ 210 public static int getKnockbackModifier(EntityLiving par0EntityLiving, EntityLiving par1EntityLiving) 211 { 212 return getEnchantmentLevel(Enchantment.knockback.effectId, par0EntityLiving.getHeldItem()); 213 } 214 215 public static int func_90036_a(EntityLiving par0EntityLiving) 216 { 217 return getEnchantmentLevel(Enchantment.fireAspect.effectId, par0EntityLiving.getHeldItem()); 218 } 219 220 /** 221 * Returns the 'Water Breathing' modifier of enchantments on player equipped armors. 222 */ 223 public static int getRespiration(EntityLiving par0EntityLiving) 224 { 225 return getMaxEnchantmentLevel(Enchantment.respiration.effectId, par0EntityLiving.getLastActiveItems()); 226 } 227 228 /** 229 * Return the extra efficiency of tools based on enchantments on equipped player item. 230 */ 231 public static int getEfficiencyModifier(EntityLiving par0EntityLiving) 232 { 233 return getEnchantmentLevel(Enchantment.efficiency.effectId, par0EntityLiving.getHeldItem()); 234 } 235 236 /** 237 * Returns the unbreaking enchantment modifier on current equipped item of player. 238 */ 239 public static int getUnbreakingModifier(EntityLiving par0EntityLiving) 240 { 241 return getEnchantmentLevel(Enchantment.unbreaking.effectId, par0EntityLiving.getHeldItem()); 242 } 243 244 /** 245 * Returns the silk touch status of enchantments on current equipped item of player. 246 */ 247 public static boolean getSilkTouchModifier(EntityLiving par0EntityLiving) 248 { 249 return getEnchantmentLevel(Enchantment.silkTouch.effectId, par0EntityLiving.getHeldItem()) > 0; 250 } 251 252 /** 253 * Returns the fortune enchantment modifier of the current equipped item of player. 254 */ 255 public static int getFortuneModifier(EntityLiving par0EntityLiving) 256 { 257 return getEnchantmentLevel(Enchantment.fortune.effectId, par0EntityLiving.getHeldItem()); 258 } 259 260 /** 261 * Returns the looting enchantment modifier of the current equipped item of player. 262 */ 263 public static int getLootingModifier(EntityLiving par0EntityLiving) 264 { 265 return getEnchantmentLevel(Enchantment.looting.effectId, par0EntityLiving.getHeldItem()); 266 } 267 268 /** 269 * Returns the aqua affinity status of enchantments on current equipped item of player. 270 */ 271 public static boolean getAquaAffinityModifier(EntityLiving par0EntityLiving) 272 { 273 return getMaxEnchantmentLevel(Enchantment.aquaAffinity.effectId, par0EntityLiving.getLastActiveItems()) > 0; 274 } 275 276 /** 277 * Returns the enchantability of itemstack, it's uses a singular formula for each index (2nd parameter: 0, 1 and 2), 278 * cutting to the max enchantability power of the table (3rd parameter) 279 */ 280 public static int calcItemStackEnchantability(Random par0Random, int par1, int par2, ItemStack par3ItemStack) 281 { 282 Item var4 = par3ItemStack.getItem(); 283 int var5 = var4.getItemEnchantability(); 284 285 if (var5 <= 0) 286 { 287 return 0; 288 } 289 else 290 { 291 if (par2 > 15) 292 { 293 par2 = 15; 294 } 295 296 int var6 = par0Random.nextInt(8) + 1 + (par2 >> 1) + par0Random.nextInt(par2 + 1); 297 return par1 == 0 ? Math.max(var6 / 3, 1) : (par1 == 1 ? var6 * 2 / 3 + 1 : Math.max(var6, par2 * 2)); 298 } 299 } 300 301 /** 302 * Adds a random enchantment to the specified item. Args: random, itemStack, enchantabilityLevel 303 */ 304 public static ItemStack addRandomEnchantment(Random par0Random, ItemStack par1ItemStack, int par2) 305 { 306 List var3 = buildEnchantmentList(par0Random, par1ItemStack, par2); 307 308 if (var3 != null) 309 { 310 Iterator var4 = var3.iterator(); 311 312 while (var4.hasNext()) 313 { 314 EnchantmentData var5 = (EnchantmentData)var4.next(); 315 par1ItemStack.addEnchantment(var5.enchantmentobj, var5.enchantmentLevel); 316 } 317 } 318 319 return par1ItemStack; 320 } 321 322 /** 323 * Create a list of random EnchantmentData (enchantments) that can be added together to the ItemStack, the 3rd 324 * parameter is the total enchantability level. 325 */ 326 public static List buildEnchantmentList(Random par0Random, ItemStack par1ItemStack, int par2) 327 { 328 Item var3 = par1ItemStack.getItem(); 329 int var4 = var3.getItemEnchantability(); 330 331 if (var4 <= 0) 332 { 333 return null; 334 } 335 else 336 { 337 var4 /= 2; 338 var4 = 1 + par0Random.nextInt((var4 >> 1) + 1) + par0Random.nextInt((var4 >> 1) + 1); 339 int var5 = var4 + par2; 340 float var6 = (par0Random.nextFloat() + par0Random.nextFloat() - 1.0F) * 0.15F; 341 int var7 = (int)((float)var5 * (1.0F + var6) + 0.5F); 342 343 if (var7 < 1) 344 { 345 var7 = 1; 346 } 347 348 ArrayList var8 = null; 349 Map var9 = mapEnchantmentData(var7, par1ItemStack); 350 351 if (var9 != null && !var9.isEmpty()) 352 { 353 EnchantmentData var10 = (EnchantmentData)WeightedRandom.getRandomItem(par0Random, var9.values()); 354 355 if (var10 != null) 356 { 357 var8 = new ArrayList(); 358 var8.add(var10); 359 360 for (int var11 = var7; par0Random.nextInt(50) <= var11; var11 >>= 1) 361 { 362 Iterator var12 = var9.keySet().iterator(); 363 364 while (var12.hasNext()) 365 { 366 Integer var13 = (Integer)var12.next(); 367 boolean var14 = true; 368 Iterator var15 = var8.iterator(); 369 370 while (true) 371 { 372 if (var15.hasNext()) 373 { 374 EnchantmentData var16 = (EnchantmentData)var15.next(); 375 376 if (var16.enchantmentobj.canApplyTogether(Enchantment.enchantmentsList[var13.intValue()])) 377 { 378 continue; 379 } 380 381 var14 = false; 382 } 383 384 if (!var14) 385 { 386 var12.remove(); 387 } 388 389 break; 390 } 391 } 392 393 if (!var9.isEmpty()) 394 { 395 EnchantmentData var17 = (EnchantmentData)WeightedRandom.getRandomItem(par0Random, var9.values()); 396 var8.add(var17); 397 } 398 } 399 } 400 } 401 402 return var8; 403 } 404 } 405 406 /** 407 * Creates a 'Map' of EnchantmentData (enchantments) possible to add on the ItemStack and the enchantability level 408 * passed. 409 */ 410 public static Map mapEnchantmentData(int par0, ItemStack par1ItemStack) 411 { 412 Item var2 = par1ItemStack.getItem(); 413 HashMap var3 = null; 414 Enchantment[] var4 = Enchantment.enchantmentsList; 415 int var5 = var4.length; 416 417 for (int var6 = 0; var6 < var5; ++var6) 418 { 419 Enchantment var7 = var4[var6]; 420 421 if (var7 != null && var7.canEnchantItem(par1ItemStack)) 422 { 423 for (int var8 = var7.getMinLevel(); var8 <= var7.getMaxLevel(); ++var8) 424 { 425 if (par0 >= var7.getMinEnchantability(var8) && par0 <= var7.getMaxEnchantability(var8)) 426 { 427 if (var3 == null) 428 { 429 var3 = new HashMap(); 430 } 431 432 var3.put(Integer.valueOf(var7.effectId), new EnchantmentData(var7, var8)); 433 } 434 } 435 } 436 } 437 438 return var3; 439 } 440 }