572 lines
18 KiB
Java
Executable file
572 lines
18 KiB
Java
Executable file
package game.enchantment;
|
|
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import game.collect.Lists;
|
|
import game.collect.Maps;
|
|
import game.entity.DamageSource;
|
|
import game.entity.Entity;
|
|
import game.entity.types.EntityLiving;
|
|
import game.init.Items;
|
|
import game.item.Item;
|
|
import game.item.ItemStack;
|
|
import game.nbt.NBTTagCompound;
|
|
import game.nbt.NBTTagList;
|
|
import game.rng.Random;
|
|
import game.rng.WeightedList;
|
|
|
|
public class EnchantmentHelper
|
|
{
|
|
/** Is the random seed of enchantment effects. */
|
|
private static final Random enchantmentRand = new Random();
|
|
|
|
/**
|
|
* Used to calculate the extra armor of enchantments on armors equipped on player.
|
|
*/
|
|
private static final EnchantmentHelper.ModifierDamage enchantmentModifierDamage = new EnchantmentHelper.ModifierDamage();
|
|
|
|
/**
|
|
* Used to calculate the (magic) extra damage done by enchantments on current equipped item of player.
|
|
*/
|
|
private static final EnchantmentHelper.ModifierLiving enchantmentModifierLiving = new EnchantmentHelper.ModifierLiving();
|
|
private static final EnchantmentHelper.HurtIterator ENCHANTMENT_ITERATOR_HURT = new EnchantmentHelper.HurtIterator();
|
|
private static final EnchantmentHelper.DamageIterator ENCHANTMENT_ITERATOR_DAMAGE = new EnchantmentHelper.DamageIterator();
|
|
|
|
/**
|
|
* Returns the level of enchantment on the ItemStack passed.
|
|
*/
|
|
public static int getEnchantmentLevel(int enchID, ItemStack stack)
|
|
{
|
|
if (stack == null)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
NBTTagList nbttaglist = stack.getEnchantmentTagList();
|
|
|
|
if (nbttaglist == null)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < nbttaglist.tagCount(); ++i)
|
|
{
|
|
int j = nbttaglist.getCompoundTagAt(i).getShort("id");
|
|
int k = nbttaglist.getCompoundTagAt(i).getShort("lvl");
|
|
|
|
if (j == enchID)
|
|
{
|
|
return k;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static Map<Integer, Integer> getEnchantments(ItemStack stack)
|
|
{
|
|
Map<Integer, Integer> map = Maps.<Integer, Integer>newLinkedHashMap();
|
|
NBTTagList nbttaglist = stack.getItem() == Items.enchanted_book ? Items.enchanted_book.getEnchantments(stack) : stack.getEnchantmentTagList();
|
|
|
|
if (nbttaglist != null)
|
|
{
|
|
for (int i = 0; i < nbttaglist.tagCount(); ++i)
|
|
{
|
|
int j = nbttaglist.getCompoundTagAt(i).getShort("id");
|
|
int k = nbttaglist.getCompoundTagAt(i).getShort("lvl");
|
|
map.put(j, k);
|
|
}
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
/**
|
|
* Set the enchantments for the specified stack.
|
|
*/
|
|
public static void setEnchantments(Map<Integer, Integer> enchMap, ItemStack stack)
|
|
{
|
|
NBTTagList nbttaglist = new NBTTagList();
|
|
Iterator iterator = enchMap.keySet().iterator();
|
|
|
|
while (iterator.hasNext())
|
|
{
|
|
int i = ((Integer)iterator.next()).intValue();
|
|
Enchantment enchantment = Enchantment.getEnchantmentById(i);
|
|
|
|
if (enchantment != null)
|
|
{
|
|
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
|
nbttagcompound.setShort("id", (short)i);
|
|
nbttagcompound.setShort("lvl", (short)enchMap.get(i).intValue());
|
|
nbttaglist.appendTag(nbttagcompound);
|
|
|
|
if (stack.getItem() == Items.enchanted_book)
|
|
{
|
|
Items.enchanted_book.addEnchantment(stack, new RngEnchantment(enchantment, enchMap.get(i).intValue()));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nbttaglist.tagCount() > 0)
|
|
{
|
|
if (stack.getItem() != Items.enchanted_book)
|
|
{
|
|
stack.setTagInfo("ench", nbttaglist);
|
|
}
|
|
}
|
|
else if (stack.hasTagCompound())
|
|
{
|
|
stack.getTagCompound().removeTag("ench");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the biggest level of the enchantment on the array of ItemStack passed.
|
|
*/
|
|
public static int getMaxEnchantmentLevel(int enchID, ItemStack[] stacks)
|
|
{
|
|
if (stacks == null)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
int i = 0;
|
|
|
|
for (ItemStack itemstack : stacks)
|
|
{
|
|
int j = getEnchantmentLevel(enchID, itemstack);
|
|
|
|
if (j > i)
|
|
{
|
|
i = j;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Executes the enchantment modifier on the ItemStack passed.
|
|
*/
|
|
private static void applyEnchantmentModifier(EnchantmentHelper.IModifier modifier, ItemStack stack)
|
|
{
|
|
if (stack != null)
|
|
{
|
|
NBTTagList nbttaglist = stack.getEnchantmentTagList();
|
|
|
|
if (nbttaglist != null)
|
|
{
|
|
for (int i = 0; i < nbttaglist.tagCount(); ++i)
|
|
{
|
|
int j = nbttaglist.getCompoundTagAt(i).getShort("id");
|
|
int k = nbttaglist.getCompoundTagAt(i).getShort("lvl");
|
|
|
|
if (Enchantment.getEnchantmentById(j) != null)
|
|
{
|
|
modifier.calculateModifier(Enchantment.getEnchantmentById(j), k);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Executes the enchantment modifier on the array of ItemStack passed.
|
|
*/
|
|
private static void applyEnchantmentModifierArray(EnchantmentHelper.IModifier modifier, ItemStack[] stacks)
|
|
{
|
|
for (ItemStack itemstack : stacks)
|
|
{
|
|
applyEnchantmentModifier(modifier, itemstack);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the modifier of protection enchantments on armors equipped on player.
|
|
*/
|
|
public static int getEnchantmentModifierDamage(ItemStack[] stacks, DamageSource source)
|
|
{
|
|
enchantmentModifierDamage.damageModifier = 0;
|
|
enchantmentModifierDamage.source = source;
|
|
applyEnchantmentModifierArray(enchantmentModifierDamage, stacks);
|
|
|
|
if (enchantmentModifierDamage.damageModifier > 25)
|
|
{
|
|
enchantmentModifierDamage.damageModifier = 25;
|
|
}
|
|
else if (enchantmentModifierDamage.damageModifier < 0)
|
|
{
|
|
enchantmentModifierDamage.damageModifier = 0;
|
|
}
|
|
|
|
return (enchantmentModifierDamage.damageModifier + 1 >> 1) + enchantmentRand.zrange((enchantmentModifierDamage.damageModifier >> 1) + 1);
|
|
}
|
|
|
|
public static int getDamageModifier(ItemStack p_152377_0_)
|
|
{
|
|
enchantmentModifierLiving.livingModifier = 0;
|
|
applyEnchantmentModifier(enchantmentModifierLiving, p_152377_0_);
|
|
return enchantmentModifierLiving.livingModifier;
|
|
}
|
|
|
|
public static void applyThornEnchantments(EntityLiving user, Entity attacker)
|
|
{
|
|
ENCHANTMENT_ITERATOR_HURT.attacker = attacker;
|
|
ENCHANTMENT_ITERATOR_HURT.user = user;
|
|
|
|
if (user != null)
|
|
{
|
|
applyEnchantmentModifierArray(ENCHANTMENT_ITERATOR_HURT, user.getInventory());
|
|
}
|
|
|
|
if (user != null && attacker != null) // && attacker.isPlayer())
|
|
{
|
|
applyEnchantmentModifier(ENCHANTMENT_ITERATOR_HURT, user.getHeldItem());
|
|
}
|
|
}
|
|
|
|
public static void applyArthropodEnchantments(EntityLiving user, Entity target)
|
|
{
|
|
ENCHANTMENT_ITERATOR_DAMAGE.user = user;
|
|
ENCHANTMENT_ITERATOR_DAMAGE.target = target;
|
|
|
|
if (user != null)
|
|
{
|
|
applyEnchantmentModifierArray(ENCHANTMENT_ITERATOR_DAMAGE, user.getInventory());
|
|
}
|
|
|
|
if (user != null) // && user.isPlayer())
|
|
{
|
|
applyEnchantmentModifier(ENCHANTMENT_ITERATOR_DAMAGE, user.getHeldItem());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the Knockback modifier of the enchantment on the players held item.
|
|
*/
|
|
public static int getKnockbackModifier(EntityLiving player)
|
|
{
|
|
return getEnchantmentLevel(Enchantment.knockback.effectId, player.getHeldItem());
|
|
}
|
|
|
|
/**
|
|
* Returns the fire aspect modifier of the players held item.
|
|
*/
|
|
public static int getFireAspectModifier(EntityLiving player)
|
|
{
|
|
return getEnchantmentLevel(Enchantment.fireAspect.effectId, player.getHeldItem());
|
|
}
|
|
|
|
// /**
|
|
// * Returns the 'Water Breathing' modifier of enchantments on player equipped armors.
|
|
// */
|
|
// public static int getRespiration(Entity player)
|
|
// {
|
|
// return getMaxEnchantmentLevel(Enchantment.respiration.effectId, player.getInventory());
|
|
// }
|
|
|
|
// /**
|
|
// * Returns the level of the Depth Strider enchantment.
|
|
// */
|
|
// public static int getDepthStriderModifier(Entity player)
|
|
// {
|
|
// return getMaxEnchantmentLevel(Enchantment.depthStrider.effectId, player.getInventory());
|
|
// }
|
|
|
|
/**
|
|
* Return the extra efficiency of tools based on enchantments on equipped player item.
|
|
*/
|
|
public static int getEfficiencyModifier(EntityLiving player)
|
|
{
|
|
return getEnchantmentLevel(Enchantment.efficiency.effectId, player.getHeldItem());
|
|
}
|
|
|
|
/**
|
|
* Returns the silk touch status of enchantments on current equipped item of player.
|
|
*/
|
|
public static boolean getSilkTouchModifier(EntityLiving player)
|
|
{
|
|
return getEnchantmentLevel(Enchantment.silkTouch.effectId, player.getHeldItem()) > 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the fortune enchantment modifier of the current equipped item of player.
|
|
*/
|
|
public static int getFortuneModifier(EntityLiving player)
|
|
{
|
|
return getEnchantmentLevel(Enchantment.fortune.effectId, player.getHeldItem());
|
|
}
|
|
|
|
/**
|
|
* Returns the level of the 'Luck Of The Sea' enchantment.
|
|
*/
|
|
public static int getLuckOfSeaModifier(EntityLiving player)
|
|
{
|
|
return getEnchantmentLevel(Enchantment.luckOfTheSea.effectId, player.getHeldItem());
|
|
}
|
|
|
|
/**
|
|
* Returns the level of the 'Lure' enchantment on the players held item.
|
|
*/
|
|
public static int getLureModifier(EntityLiving player)
|
|
{
|
|
return getEnchantmentLevel(Enchantment.lure.effectId, player.getHeldItem());
|
|
}
|
|
|
|
/**
|
|
* Returns the looting enchantment modifier of the current equipped item of player.
|
|
*/
|
|
public static int getLootingModifier(EntityLiving player)
|
|
{
|
|
return getEnchantmentLevel(Enchantment.looting.effectId, player.getHeldItem());
|
|
}
|
|
|
|
// /**
|
|
// * Returns the aqua affinity status of enchantments on current equipped item of player.
|
|
// */
|
|
// public static boolean getAquaAffinityModifier(EntityLivingBase player)
|
|
// {
|
|
// return getMaxEnchantmentLevel(Enchantment.aquaAffinity.effectId, player.getInventory()) > 0;
|
|
// }
|
|
|
|
public static ItemStack getEnchantedItem(Enchantment p_92099_0_, EntityLiving p_92099_1_)
|
|
{
|
|
for (ItemStack itemstack : p_92099_1_.getInventory())
|
|
{
|
|
if (itemstack != null && getEnchantmentLevel(p_92099_0_.effectId, itemstack) > 0)
|
|
{
|
|
return itemstack;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns the enchantability of itemstack, using a separate calculation for each enchantNum (0, 1 or 2), cutting to
|
|
* the max enchantability power of the table, which is locked to a max of 15.
|
|
*/
|
|
public static int calcItemStackEnchantability(Random rand, int enchantNum, int power, ItemStack stack)
|
|
{
|
|
Item item = stack.getItem();
|
|
int i = item.getItemEnchantability();
|
|
|
|
if (i <= 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
if (power > 15)
|
|
{
|
|
power = 15;
|
|
}
|
|
|
|
int j = rand.roll(8) + (power >> 1) + rand.zrange(power + 1);
|
|
return enchantNum == 0 ? Math.max(j / 3, 1) : (enchantNum == 1 ? j * 2 / 3 + 1 : Math.max(j, power * 2));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a random enchantment to the specified item. Args: random, itemStack, enchantabilityLevel
|
|
*/
|
|
public static ItemStack addRandomEnchantment(Random p_77504_0_, ItemStack p_77504_1_, int p_77504_2_)
|
|
{
|
|
List<RngEnchantment> list = buildEnchantmentList(p_77504_0_, p_77504_1_, p_77504_2_);
|
|
boolean flag = p_77504_1_.getItem() == Items.book;
|
|
|
|
if (flag)
|
|
{
|
|
p_77504_1_.setItem(Items.enchanted_book);
|
|
}
|
|
|
|
if (list != null)
|
|
{
|
|
for (RngEnchantment enchantmentdata : list)
|
|
{
|
|
if (flag)
|
|
{
|
|
Items.enchanted_book.addEnchantment(p_77504_1_, enchantmentdata);
|
|
}
|
|
else
|
|
{
|
|
p_77504_1_.addEnchantment(enchantmentdata.enchantmentobj, enchantmentdata.enchantmentLevel);
|
|
}
|
|
}
|
|
}
|
|
|
|
return p_77504_1_;
|
|
}
|
|
|
|
public static List<RngEnchantment> buildEnchantmentList(Random randomIn, ItemStack itemStackIn, int level)
|
|
{
|
|
Item item = itemStackIn.getItem();
|
|
int i = item.getItemEnchantability();
|
|
|
|
if (i <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
i = i / 2;
|
|
i = randomIn.roll((i >> 1) + 1) + randomIn.zrange((i >> 1) + 1);
|
|
int j = i + level;
|
|
float f = (randomIn.floatv() + randomIn.floatv() - 1.0F) * 0.15F;
|
|
int k = (int)((float)j * (1.0F + f) + 0.5F);
|
|
|
|
if (k < 1)
|
|
{
|
|
k = 1;
|
|
}
|
|
|
|
List<RngEnchantment> list = null;
|
|
Map<Integer, RngEnchantment> map = mapEnchantmentData(k, itemStackIn);
|
|
|
|
if (map != null && !map.isEmpty())
|
|
{
|
|
RngEnchantment enchantmentdata = (RngEnchantment)new WeightedList(map.values()).pick(randomIn);
|
|
|
|
if (enchantmentdata != null)
|
|
{
|
|
list = Lists.<RngEnchantment>newArrayList();
|
|
list.add(enchantmentdata);
|
|
|
|
for (int l = k; randomIn.zrange(50) <= l; l >>= 1)
|
|
{
|
|
Iterator<Integer> iterator = map.keySet().iterator();
|
|
|
|
while (iterator.hasNext())
|
|
{
|
|
Integer integer = (Integer)iterator.next();
|
|
boolean flag = true;
|
|
|
|
for (RngEnchantment enchantmentdata1 : list)
|
|
{
|
|
if (!enchantmentdata1.enchantmentobj.canApplyTogether(Enchantment.getEnchantmentById(integer.intValue())))
|
|
{
|
|
flag = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!flag)
|
|
{
|
|
iterator.remove();
|
|
}
|
|
}
|
|
|
|
if (!map.isEmpty())
|
|
{
|
|
RngEnchantment enchantmentdata2 = (RngEnchantment)new WeightedList(map.values()).pick(randomIn);
|
|
list.add(enchantmentdata2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
}
|
|
|
|
public static Map<Integer, RngEnchantment> mapEnchantmentData(int p_77505_0_, ItemStack p_77505_1_)
|
|
{
|
|
Item item = p_77505_1_.getItem();
|
|
Map<Integer, RngEnchantment> map = null;
|
|
boolean flag = p_77505_1_.getItem() == Items.book;
|
|
|
|
for (Enchantment enchantment : Enchantment.enchantmentsBookList)
|
|
{
|
|
if (enchantment != null && (enchantment.type.canEnchantItem(item) || flag))
|
|
{
|
|
for (int i = enchantment.getMinLevel(); i <= enchantment.getMaxLevel(); ++i)
|
|
{
|
|
if (p_77505_0_ >= enchantment.getMinEnchantability(i) && p_77505_0_ <= enchantment.getMaxEnchantability(i))
|
|
{
|
|
if (map == null)
|
|
{
|
|
map = Maps.<Integer, RngEnchantment>newHashMap();
|
|
}
|
|
|
|
map.put(enchantment.effectId, new RngEnchantment(enchantment, i));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
static final class DamageIterator implements EnchantmentHelper.IModifier
|
|
{
|
|
public EntityLiving user;
|
|
public Entity target;
|
|
|
|
private DamageIterator()
|
|
{
|
|
}
|
|
|
|
public void calculateModifier(Enchantment enchantmentIn, int enchantmentLevel)
|
|
{
|
|
enchantmentIn.onEntityDamaged(this.user, this.target, enchantmentLevel);
|
|
}
|
|
}
|
|
|
|
static final class HurtIterator implements EnchantmentHelper.IModifier
|
|
{
|
|
public EntityLiving user;
|
|
public Entity attacker;
|
|
|
|
private HurtIterator()
|
|
{
|
|
}
|
|
|
|
public void calculateModifier(Enchantment enchantmentIn, int enchantmentLevel)
|
|
{
|
|
enchantmentIn.onUserHurt(this.user, this.attacker, enchantmentLevel);
|
|
}
|
|
}
|
|
|
|
interface IModifier
|
|
{
|
|
void calculateModifier(Enchantment enchantmentIn, int enchantmentLevel);
|
|
}
|
|
|
|
static final class ModifierDamage implements EnchantmentHelper.IModifier
|
|
{
|
|
public int damageModifier;
|
|
public DamageSource source;
|
|
|
|
private ModifierDamage()
|
|
{
|
|
}
|
|
|
|
public void calculateModifier(Enchantment enchantmentIn, int enchantmentLevel)
|
|
{
|
|
this.damageModifier += enchantmentIn.calcDamageReduction(enchantmentLevel, this.source);
|
|
}
|
|
}
|
|
|
|
static final class ModifierLiving implements EnchantmentHelper.IModifier
|
|
{
|
|
public int livingModifier;
|
|
|
|
private ModifierLiving()
|
|
{
|
|
}
|
|
|
|
public void calculateModifier(Enchantment enchantmentIn, int enchantmentLevel)
|
|
{
|
|
this.livingModifier += enchantmentIn.calcAdditionalDamage(enchantmentLevel);
|
|
}
|
|
}
|
|
}
|