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