package gtPlusPlus.xmod.gregtech.api.items; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import cpw.mods.fml.common.Optional; import net.minecraft.block.Block; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.item.EntityMinecart; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.Potion; import net.minecraft.stats.AchievementList; import net.minecraft.stats.StatList; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import gregtech.api.enchants.Enchantment_Radioactivity; import gregtech.api.enums.Materials; import gregtech.api.interfaces.IDamagableItem; import gregtech.api.interfaces.IToolStats; import gregtech.api.items.GT_MetaGenerated_Tool; import gregtech.api.util.GT_ModHandler; import gregtech.api.util.GT_Utility; import buildcraft.api.tools.IToolWrench; import gtPlusPlus.core.creative.AddToCreativeTab; import gtPlusPlus.xmod.gregtech.api.interfaces.internal.Interface_ToolStats; import mods.railcraft.api.core.items.IToolCrowbar; import net.minecraftforge.event.world.BlockEvent; /** * This is an example on how you can create a Tool ItemStack, in this case a Bismuth Wrench: * GT_MetaGenerated_Tool.sInstances.get("gt.metatool.01").getToolWithStats(16, 1, Materials.Bismuth, Materials.Bismuth, null); */ @Optional.InterfaceList({@Optional.Interface(iface = "forestry.api.arboriculture.IToolGrafter", modid = "Forestry"), @Optional.Interface(iface = "mods.railcraft.api.core.items.IToolCrowbar", modid = "Railcraft"), @Optional.Interface(iface = "buildcraft.api.tools.IToolWrench", modid = "BuildCraft"), @Optional.Interface(iface = "crazypants.enderio.api.tool.ITool", modid = "EnderIO")}) public abstract class Gregtech_MetaTool extends GT_MetaGenerated_Tool implements IDamagableItem, IToolCrowbar, IToolWrench { /** * All instances of this Item Class are listed here. * This gets used to register the Renderer to all Items of this Type, if useStandardMetaItemRenderer() returns true. * <p/> * You can also use the unlocalized Name gotten from getUnlocalizedName() as Key if you want to get a specific Item. */ public static final HashMap<String, Gregtech_MetaTool> sInstances = new HashMap<>(); /* ---------- CONSTRUCTOR AND MEMBER VARIABLES ---------- */ public final HashMap<Short, IToolStats> mToolStats = new HashMap<>(); /** * Creates the Item using these Parameters. * * @param aUnlocalized The Unlocalized Name of this Item. */ public Gregtech_MetaTool(final String aUnlocalized) { super(aUnlocalized); GT_ModHandler.registerBoxableItemToToolBox(this); this.setCreativeTab(AddToCreativeTab.tabMachines); this.setMaxStackSize(1); sInstances.put(this.getUnlocalizedName(), this); } /** * Called by the Block Harvesting Event within the GT_Proxy */ @Override public void onHarvestBlockEvent(final ArrayList<ItemStack> aDrops, final ItemStack aStack, final EntityPlayer aPlayer, final Block aBlock, final int aX, final int aY, final int aZ, final byte aMetaData, final int aFortune, final boolean aSilkTouch, final BlockEvent.HarvestDropsEvent aEvent) { final IToolStats tStats = this.getToolStats(aStack); if (this.isItemStackUsable(aStack) && (this.getDigSpeed(aStack, aBlock, aMetaData) > 0.0F)) { this.doDamage(aStack, tStats.convertBlockDrops(aDrops, aStack, aPlayer, aBlock, aX, aY, aZ, aMetaData, aFortune, aSilkTouch, aEvent) * tStats.getToolDamagePerDropConversion()); } } @Override public boolean onLeftClickEntity(final ItemStack aStack, final EntityPlayer aPlayer, final Entity aEntity) { final IToolStats tStats = this.getToolStats(aStack); if ((tStats == null) || !this.isItemStackUsable(aStack)) { return true; } GT_Utility.doSoundAtClient(tStats.getEntityHitSound(), 1, 1.0F); if (super.onLeftClickEntity(aStack, aPlayer, aEntity)) { return true; } if (aEntity.canAttackWithItem() && !aEntity.hitByEntity(aPlayer)) { final float tMagicDamage = tStats.getMagicDamageAgainstEntity(aEntity instanceof EntityLivingBase ? EnchantmentHelper.getEnchantmentModifierLiving(aPlayer, (EntityLivingBase) aEntity) : 0.0F, aEntity, aStack, aPlayer); float tDamage = tStats.getNormalDamageAgainstEntity((float) aPlayer.getEntityAttribute(SharedMonsterAttributes.attackDamage).getAttributeValue() + this.getToolCombatDamage(aStack), aEntity, aStack, aPlayer); if ((tDamage + tMagicDamage) > 0.0F) { final boolean tCriticalHit = (aPlayer.fallDistance > 0.0F) && !aPlayer.onGround && !aPlayer.isOnLadder() && !aPlayer.isInWater() && !aPlayer.isPotionActive(Potion.blindness) && (aPlayer.ridingEntity == null) && (aEntity instanceof EntityLivingBase); if (tCriticalHit && (tDamage > 0.0F)) { tDamage *= 1.5F; } tDamage += tMagicDamage; if (aEntity.attackEntityFrom(tStats.getDamageSource(aPlayer, aEntity), tDamage)) { if (aEntity instanceof EntityLivingBase) { aEntity.setFire(EnchantmentHelper.getFireAspectModifier(aPlayer) * 4); } final int tKnockcack = (aPlayer.isSprinting() ? 1 : 0) + (aEntity instanceof EntityLivingBase ? EnchantmentHelper.getKnockbackModifier(aPlayer, (EntityLivingBase) aEntity) : 0); if (tKnockcack > 0) { aEntity.addVelocity(-MathHelper.sin((aPlayer.rotationYaw * (float) Math.PI) / 180.0F) * tKnockcack * 0.5F, 0.1D, MathHelper.cos((aPlayer.rotationYaw * (float) Math.PI) / 180.0F) * tKnockcack * 0.5F); aPlayer.motionX *= 0.6D; aPlayer.motionZ *= 0.6D; aPlayer.setSprinting(false); } if (tCriticalHit) { aPlayer.onCriticalHit(aEntity); } if (tMagicDamage > 0.0F) { aPlayer.onEnchantmentCritical(aEntity); } if (tDamage >= 18.0F) { aPlayer.triggerAchievement(AchievementList.overkill); } aPlayer.setLastAttacker(aEntity); if (aEntity instanceof EntityLivingBase) { EnchantmentHelper.func_151384_a((EntityLivingBase) aEntity, aPlayer); } EnchantmentHelper.func_151385_b(aPlayer, aEntity); if (aEntity instanceof EntityLivingBase) { aPlayer.addStat(StatList.damageDealtStat, Math.round(tDamage * 10.0F)); } aEntity.hurtResistantTime = Math.max(1, tStats.getHurtResistanceTime(aEntity.hurtResistantTime, aEntity)); aPlayer.addExhaustion(0.3F); this.doDamage(aStack, tStats.getToolDamagePerEntityAttack()); } } } if (aStack.stackSize <= 0) { aPlayer.destroyCurrentEquippedItem(); } return true; } @Override public ItemStack onItemRightClick(final ItemStack aStack, final World aWorld, final EntityPlayer aPlayer) { final IToolStats tStats = this.getToolStats(aStack); if ((tStats != null) && tStats.canBlock()) { aPlayer.setItemInUse(aStack, 72000); } return super.onItemRightClick(aStack, aWorld, aPlayer); } @SuppressWarnings("unchecked") public void addAdditionalToolTips(final List aList, final ItemStack aStack) { final long tMaxDamage = getToolMaxDamage(aStack); final Materials tMaterial = getPrimaryMaterial(aStack); final IToolStats tStats = this.getToolStats(aStack); final int tOffset = this.getElectricStats(aStack) != null ? 2 : 1; if (tStats != null) { final String name = aStack.getUnlocalizedName(); if (name.equals("gt.metatool.01.170") || name.equals("gt.metatool.01.172") || name.equals("gt.metatool.01.174") || name.equals("gt.metatool.01.176")) { aList.add(tOffset + 0, EnumChatFormatting.WHITE + "Durability: " + EnumChatFormatting.GREEN + (tMaxDamage - getToolDamage(aStack)) + " / " + tMaxDamage + EnumChatFormatting.GRAY); aList.add(tOffset + 1, EnumChatFormatting.WHITE + tMaterial.mDefaultLocalName + EnumChatFormatting.YELLOW + " lvl " + this.getHarvestLevel(aStack, "") + EnumChatFormatting.GRAY); aList.add(tOffset + 2, EnumChatFormatting.WHITE + "Turbine Efficency: " + EnumChatFormatting.BLUE + (50.0F + (10.0F * this.getToolCombatDamage(aStack))) + EnumChatFormatting.GRAY); aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Optimal Steam flow: " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed * 1000) + EnumChatFormatting.GRAY + "L/sec"); aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Optimal Gas flow(EU burnvalue per tick): " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed * 25) + EnumChatFormatting.GRAY + "EU/t"); aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Optimal Plasma flow(Plasma energyvalue per tick): " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed * 1000) + EnumChatFormatting.GRAY + "EU/t"); } else { aList.add(tOffset + 0, EnumChatFormatting.WHITE + "Durability: " + EnumChatFormatting.GREEN + (tMaxDamage - getToolDamage(aStack)) + " / " + tMaxDamage + EnumChatFormatting.GRAY); aList.add(tOffset + 1, EnumChatFormatting.WHITE + tMaterial.mDefaultLocalName + EnumChatFormatting.YELLOW + " lvl " + this.getHarvestLevel(aStack, "") + EnumChatFormatting.GRAY); aList.add(tOffset + 2, EnumChatFormatting.WHITE + "Attack Damage: " + EnumChatFormatting.BLUE + this.getToolCombatDamage(aStack) + EnumChatFormatting.GRAY); aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Mining Speed: " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed) + EnumChatFormatting.GRAY); } } } @SuppressWarnings("unchecked") public void addAdditionalToolTips(final List aList, final ItemStack aStack, final EntityPlayer aPlayer) { final long tMaxDamage = getToolMaxDamage(aStack); final Materials tMaterial = getPrimaryMaterial(aStack); final IToolStats tStats = this.getToolStats(aStack); final int tOffset = this.getElectricStats(aStack) != null ? 2 : 1; if (tStats != null) { final String name = aStack.getUnlocalizedName(); if (name.equals("gt.metatool.01.170") || name.equals("gt.metatool.01.172") || name.equals("gt.metatool.01.174") || name.equals("gt.metatool.01.176")) { aList.add(tOffset + 0, EnumChatFormatting.WHITE + "Durability: " + EnumChatFormatting.GREEN + (tMaxDamage - getToolDamage(aStack)) + " / " + tMaxDamage + EnumChatFormatting.GRAY); aList.add(tOffset + 1, EnumChatFormatting.WHITE + tMaterial.mDefaultLocalName + EnumChatFormatting.YELLOW + " lvl " + this.getHarvestLevel(aStack, "") + EnumChatFormatting.GRAY); aList.add(tOffset + 2, EnumChatFormatting.WHITE + "Turbine Efficency: " + EnumChatFormatting.BLUE + (50.0F + (10.0F * this.getToolCombatDamage(aStack))) + EnumChatFormatting.GRAY); aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Optimal Steam flow: " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed * 1000) + EnumChatFormatting.GRAY + "L/sec"); aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Optimal Gas flow(EU burnvalue per tick): " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed * 50) + EnumChatFormatting.GRAY + "EU/t"); aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Optimal Plasma flow(Plasma energyvalue per tick): " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed * 1000) + EnumChatFormatting.GRAY + "EU/t"); } else { aList.add(tOffset + 0, EnumChatFormatting.WHITE + "Durability: " + EnumChatFormatting.GREEN + (tMaxDamage - getToolDamage(aStack)) + " / " + tMaxDamage + EnumChatFormatting.GRAY); aList.add(tOffset + 1, EnumChatFormatting.WHITE + tMaterial.mDefaultLocalName + EnumChatFormatting.YELLOW + " lvl " + this.getHarvestLevel(aStack, "") + EnumChatFormatting.GRAY); aList.add(tOffset + 2, EnumChatFormatting.WHITE + "Attack Damage: " + EnumChatFormatting.BLUE + this.getToolCombatDamage(aStack) + EnumChatFormatting.GRAY); aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Mining Speed: " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed) + EnumChatFormatting.GRAY); NBTTagCompound aNBT = aStack.getTagCompound(); if (aNBT != null) { aNBT = aNBT.getCompoundTag("GT.ToolStats"); if ((aNBT != null) && aNBT.hasKey("Heat")){ int tHeat = aNBT.getInteger("Heat"); final long tWorldTime = aPlayer.getEntityWorld().getWorldTime(); if(aNBT.hasKey("HeatTime")){ final long tHeatTime = aNBT.getLong("HeatTime"); if(tWorldTime>(tHeatTime+10)){ tHeat = (int) (tHeat - ((tWorldTime-tHeatTime)/10)); if((tHeat<300)&&(tHeat>-10000)) { tHeat=300; } } aNBT.setLong("HeatTime", tWorldTime); if(tHeat>-10000) { aNBT.setInteger("Heat", tHeat); } } aList.add(tOffset + 3, EnumChatFormatting.RED + "Heat: " + aNBT.getInteger("Heat")+" K" + EnumChatFormatting.GRAY); } } } } } @Override public Long[] getFluidContainerStats(final ItemStack aStack) { return null; } @Override public Long[] getElectricStats(final ItemStack aStack) { NBTTagCompound aNBT = aStack.getTagCompound(); if (aNBT != null) { aNBT = aNBT.getCompoundTag("GT.ToolStats"); if ((aNBT != null) && aNBT.getBoolean("Electric")) { return new Long[]{aNBT.getLong("MaxCharge"), aNBT.getLong("Voltage"), aNBT.getLong("Tier"), aNBT.getLong("SpecialData")}; } } return new Long[] {}; } @Override public float getToolCombatDamage(final ItemStack aStack) { final IToolStats tStats = this.getToolStats(aStack); if (tStats == null) { return 0; } return tStats.getBaseDamage() + getPrimaryMaterial(aStack).mToolQuality; } @Override public float getDigSpeed(final ItemStack aStack, final Block aBlock, final int aMetaData) { if (!this.isItemStackUsable(aStack)) { return 0.0F; } final IToolStats tStats = this.getToolStats(aStack); if ((tStats == null) || (Math.max(0, this.getHarvestLevel(aStack, "")) < aBlock.getHarvestLevel(aMetaData))) { return 0.0F; } return tStats.isMinableBlock(aBlock, (byte) aMetaData) ? Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed) : 0.0F; } @Override public boolean onBlockDestroyed(final ItemStack aStack, final World aWorld, final Block aBlock, final int aX, final int aY, final int aZ, final EntityLivingBase aPlayer) { if (!this.isItemStackUsable(aStack)) { return false; } final IToolStats tStats = this.getToolStats(aStack); if (tStats == null) { return false; } GT_Utility.doSoundAtClient(tStats.getMiningSound(), 1, 1.0F); this.doDamage(aStack, (int) Math.max(1, aBlock.getBlockHardness(aWorld, aX, aY, aZ) * tStats.getToolDamagePerBlockBreak())); return this.getDigSpeed(aStack, aBlock, aWorld.getBlockMetadata(aX, aY, aZ)) > 0.0F; } private ItemStack getContainerItem(ItemStack aStack, final boolean playSound) { if (!this.isItemStackUsable(aStack)) { return null; } aStack = GT_Utility.copyAmount(1, aStack); final IToolStats tStats = this.getToolStats(aStack); if (tStats == null) { return null; } this.doDamage(aStack, tStats.getToolDamagePerContainerCraft()); aStack = aStack.stackSize > 0 ? aStack : null; if (playSound) { //String sound = (aStack == null) ? tStats.getBreakingSound() : tStats.getCraftingSound(); //GT_Utility.doSoundAtClient(sound, 1, 1.0F); } return aStack; } @Override public Interface_ToolStats getToolStats(final ItemStack aStack) { this.isItemStackUsable(aStack); return this.getToolStatsInternal(aStack); } private Interface_ToolStats getToolStatsInternal(final ItemStack aStack) { return (Interface_ToolStats) (aStack == null ? null : this.mToolStats.get((short) aStack.getItemDamage())); } @Override public boolean canWhack(final EntityPlayer aPlayer, final ItemStack aStack, final int aX, final int aY, final int aZ) { if (!this.isItemStackUsable(aStack)) { return false; } final IToolStats tStats = this.getToolStats(aStack); return (tStats != null) && tStats.isCrowbar(); } @Override public void onWhack(final EntityPlayer aPlayer, final ItemStack aStack, final int aX, final int aY, final int aZ) { final IToolStats tStats = this.getToolStats(aStack); if (tStats != null) { this.doDamage(aStack, tStats.getToolDamagePerEntityAttack()); } } @Override public boolean canWrench(final EntityPlayer player, final int x, final int y, final int z) { //System.out.println("canWrench"); if(player==null) { return false; } if(player.getCurrentEquippedItem()==null) { return false; } if (!this.isItemStackUsable(player.getCurrentEquippedItem())) { return false; } final Interface_ToolStats tStats = this.getToolStats(player.getCurrentEquippedItem()); return (tStats != null) && tStats.isWrench(); } @Override public void wrenchUsed(final EntityPlayer player, final int x, final int y, final int z) { if(player==null) { return; } if(player.getCurrentEquippedItem()==null) { return; } final IToolStats tStats = this.getToolStats(player.getCurrentEquippedItem()); if (tStats != null) { this.doDamage(player.getCurrentEquippedItem(), tStats.getToolDamagePerEntityAttack()); } } @Override public boolean canLink(final EntityPlayer aPlayer, final ItemStack aStack, final EntityMinecart cart) { if (!this.isItemStackUsable(aStack)) { return false; } final IToolStats tStats = this.getToolStats(aStack); return (tStats != null) && tStats.isCrowbar(); } @Override public void onLink(final EntityPlayer aPlayer, final ItemStack aStack, final EntityMinecart cart) { final IToolStats tStats = this.getToolStats(aStack); if (tStats != null) { this.doDamage(aStack, tStats.getToolDamagePerEntityAttack()); } } @Override public boolean canBoost(final EntityPlayer aPlayer, final ItemStack aStack, final EntityMinecart cart) { if (!this.isItemStackUsable(aStack)) { return false; } final IToolStats tStats = this.getToolStats(aStack); return (tStats != null) && tStats.isCrowbar(); } @Override public void onBoost(final EntityPlayer aPlayer, final ItemStack aStack, final EntityMinecart cart) { final IToolStats tStats = this.getToolStats(aStack); if (tStats != null) { this.doDamage(aStack, tStats.getToolDamagePerEntityAttack()); } } @Override public void onCreated(final ItemStack aStack, final World aWorld, final EntityPlayer aPlayer) { final IToolStats tStats = this.getToolStats(aStack); if ((tStats != null) && (aPlayer != null)) { tStats.onToolCrafted(aStack, aPlayer); } super.onCreated(aStack, aWorld, aPlayer); } @Override public boolean isFull3D() { return true; } @Override public boolean isItemStackUsable(final ItemStack aStack) { final IToolStats tStats = this.getToolStatsInternal(aStack); if (((aStack.getItemDamage() % 2) == 1) || (tStats == null)) { final NBTTagCompound aNBT = aStack.getTagCompound(); if (aNBT != null) { aNBT.removeTag("ench"); } return false; } final Materials aMaterial = getPrimaryMaterial(aStack); final HashMap<Integer, Integer> tMap = new HashMap<>(), tResult = new HashMap<>(); if (aMaterial.mEnchantmentTools != null) { tMap.put(aMaterial.mEnchantmentTools.effectId, (int) aMaterial.mEnchantmentToolsLevel); if (aMaterial.mEnchantmentTools == Enchantment.fortune) { tMap.put(Enchantment.looting.effectId, (int) aMaterial.mEnchantmentToolsLevel); } if (aMaterial.mEnchantmentTools == Enchantment.knockback) { tMap.put(Enchantment.power.effectId, (int) aMaterial.mEnchantmentToolsLevel); } if (aMaterial.mEnchantmentTools == Enchantment.fireAspect) { tMap.put(Enchantment.flame.effectId, (int) aMaterial.mEnchantmentToolsLevel); } } final Enchantment[] tEnchants = tStats.getEnchantments(aStack); final int[] tLevels = tStats.getEnchantmentLevels(aStack); for (int i = 0; i < tEnchants.length; i++) { if (tLevels[i] > 0) { final Integer tLevel = tMap.get(tEnchants[i].effectId); tMap.put(tEnchants[i].effectId, tLevel == null ? tLevels[i] : tLevel == tLevels[i] ? tLevel + 1 : Math.max(tLevel, tLevels[i])); } } for (final Entry<Integer, Integer> tEntry : tMap.entrySet()) { if ((tEntry.getKey() == 33) || ((tEntry.getKey() == 20) && (tEntry.getValue() > 2)) || (tEntry.getKey() == Enchantment_Radioactivity.INSTANCE.effectId)) { tResult.put(tEntry.getKey(), tEntry.getValue()); } else { switch (Enchantment.enchantmentsList[tEntry.getKey()].type) { case weapon: if (tStats.isWeapon()) { tResult.put(tEntry.getKey(), tEntry.getValue()); } break; case all: tResult.put(tEntry.getKey(), tEntry.getValue()); break; case armor: case armor_feet: case armor_head: case armor_legs: case armor_torso: break; case bow: if (tStats.isRangedWeapon()) { tResult.put(tEntry.getKey(), tEntry.getValue()); } break; case breakable: break; case fishing_rod: break; case digger: if (tStats.isMiningTool()) { tResult.put(tEntry.getKey(), tEntry.getValue()); } break; } } } EnchantmentHelper.setEnchantments(tResult, aStack); return true; } @Override public short getChargedMetaData(final ItemStack aStack) { return (short) (aStack.getItemDamage() - (aStack.getItemDamage() % 2)); } @Override public short getEmptyMetaData(final ItemStack aStack) { final NBTTagCompound aNBT = aStack.getTagCompound(); if (aNBT != null) { aNBT.removeTag("ench"); } return (short) ((aStack.getItemDamage() + 1) - (aStack.getItemDamage() % 2)); } @Override public int getItemEnchantability() { return 0; } @Override public boolean isBookEnchantable(final ItemStack aStack, final ItemStack aBook) { return false; } @Override public boolean getIsRepairable(final ItemStack aStack, final ItemStack aMaterial) { return false; } }