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 }