/* * Minecraft Forge * Copyright (c) 2016-2020. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package net.minecraftforge.common.extensions; import java.util.Set; import javax.annotation.Nullable; import net.minecraft.entity.monster.EndermanEntity; import net.minecraft.util.CachedBlockInfo; import net.minecraft.block.BlockState; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.Entity; import net.minecraft.entity.MobEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; import net.minecraft.nbt.CompoundNBT; import net.minecraft.stats.Stats; import net.minecraft.util.ActionResultType; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.ITextComponent; import net.minecraft.world.World; import net.minecraftforge.common.ToolType; import net.minecraftforge.common.capabilities.ICapabilitySerializable; /* * Extension added to ItemStack that bounces to ItemSack sensitive Item methods. Typically this is just for convince. */ public interface IForgeItemStack extends ICapabilitySerializable { // Helpers for accessing Item data default ItemStack getStack() { return (ItemStack)this; } /** * ItemStack sensitive version of getContainerItem. Returns a full ItemStack * instance of the result. * * @param itemStack The current ItemStack * @return The resulting ItemStack */ default ItemStack getContainerItem() { return getStack().getItem().getContainerItem(getStack()); } /** * ItemStack sensitive version of hasContainerItem * * @param stack The current item stack * @return True if this item has a 'container' */ default boolean hasContainerItem() { return getStack().getItem().hasContainerItem(getStack()); } /** * @return the fuel burn time for this itemStack in a furnace. Return 0 to make * it not act as a fuel. Return -1 to let the default vanilla logic * decide. */ default int getBurnTime() { return getStack().getItem().getBurnTime(getStack()); } /** * Queries the harvest level of this item stack for the specified tool class, * Returns -1 if this tool is not of the specified type * * @param tool the tool type of the item * @param player The player trying to harvest the given blockstate * @param state The block to harvest * @return Harvest level, or -1 if not the specified tool type. */ default int getHarvestLevel(ToolType tool, @Nullable PlayerEntity player, @Nullable BlockState state) { return getStack().getItem().getHarvestLevel(getStack(), tool, player, state); } default Set getToolTypes() { return getStack().getItem().getToolTypes(getStack()); } default ActionResultType onItemUseFirst(ItemUseContext context) { PlayerEntity entityplayer = context.getPlayer(); BlockPos blockpos = context.getPos(); CachedBlockInfo blockworldstate = new CachedBlockInfo(context.getWorld(), blockpos, false); if (entityplayer != null && !entityplayer.abilities.allowEdit && !getStack().canPlaceOn(context.getWorld().getTags(), blockworldstate)) { return ActionResultType.PASS; } else { Item item = getStack().getItem(); ActionResultType enumactionresult = item.onItemUseFirst(getStack(), context); if (entityplayer != null && enumactionresult == ActionResultType.SUCCESS) { entityplayer.addStat(Stats.ITEM_USED.get(item)); } return enumactionresult; } } default CompoundNBT serializeNBT() { CompoundNBT ret = new CompoundNBT(); getStack().write(ret); return ret; } /** * Called before a block is broken. Return true to prevent default block * harvesting. * * Note: In SMP, this is called on both client and server sides! * * @param pos Block's position in world * @param player The Player that is wielding the item * @return True to prevent harvesting, false to continue as normal */ default boolean onBlockStartBreak(BlockPos pos, PlayerEntity player) { return !getStack().isEmpty() && getStack().getItem().onBlockStartBreak(getStack(), pos, player); } /** * Called when the player is mining a block and the item in his hand changes. * Allows to not reset blockbreaking if only NBT or similar changes. * * @param newStack The new stack * @return True to reset block break progress */ default boolean shouldCauseBlockBreakReset(ItemStack newStack) { return getStack().getItem().shouldCauseBlockBreakReset(getStack(), newStack); } /** * Checks whether an item can be enchanted with a certain enchantment. This * applies specifically to enchanting an item in the enchanting table and is * called when retrieving the list of possible enchantments for an item. * Enchantments may additionally (or exclusively) be doing their own checks in * {@link net.minecraft.enchantment.Enchantment#canApplyAtEnchantingTable(ItemStack)}; * check the individual implementation for reference. By default this will check * if the enchantment type is valid for this item type. * * @param stack the item stack to be enchanted * @param enchantment the enchantment to be applied * @return true if the enchantment can be applied to this item */ default boolean canApplyAtEnchantingTable(Enchantment enchantment) { return getStack().getItem().canApplyAtEnchantingTable(getStack(), enchantment); } /** * ItemStack sensitive version of getItemEnchantability * * @return the item echantability value */ default int getItemEnchantability() { return getStack().getItem().getItemEnchantability(getStack()); } /** * Override this to set a non-default armor slot for an ItemStack, but do * not use this to get the armor slot of said stack; for that, use * {@link net.minecraft.entity.EntityLiving#getSlotForItemStack(ItemStack)}. * * @return the armor slot of the ItemStack, or {@code null} to let the default * vanilla logic as per {@code EntityLiving.getSlotForItemStack(stack)} * decide */ @Nullable default EquipmentSlotType getEquipmentSlot() { return getStack().getItem().getEquipmentSlot(getStack()); } /** * Can this Item disable a shield * * @param shield The shield in question * @param entity The EntityLivingBase holding the shield * @param attacker The EntityLivingBase holding the ItemStack * @retrun True if this ItemStack can disable the shield in question. */ default boolean canDisableShield(ItemStack shield, LivingEntity entity, LivingEntity attacker) { return getStack().getItem().canDisableShield(getStack(), shield, entity, attacker); } /** * Is this Item a shield * * @param entity The Entity holding the ItemStack * @return True if the ItemStack is considered a shield */ default boolean isShield(@Nullable LivingEntity entity) { return getStack().getItem().isShield(getStack(), entity); } /** * Called when a entity tries to play the 'swing' animation. * * @param entity The entity swinging the item. * @return True to cancel any further processing by EntityLiving */ default boolean onEntitySwing(LivingEntity entity) { return getStack().getItem().onEntitySwing(getStack(), entity); } /** * Called each tick while using an item. * * @param player The Player using the item * @param count The amount of time in tick the item has been used for * continuously */ default void onUsingTick(LivingEntity player, int count) { getStack().getItem().onUsingTick(getStack(), player, count); } /** * Retrieves the normal 'lifespan' of this item when it is dropped on the ground * as a EntityItem. This is in ticks, standard result is 6000, or 5 mins. * * @param world The world the entity is in * @return The normal lifespan in ticks. */ default int getEntityLifespan(World world) { return getStack().getItem().getEntityLifespan(getStack(), world); } /** * Called by the default implemetation of EntityItem's onUpdate method, allowing * for cleaner control over the update of the item without having to write a * subclass. * * @param entity The entity Item * @return Return true to skip any further update code. */ default boolean onEntityItemUpdate(ItemEntity entity) { return getStack().getItem().onEntityItemUpdate(getStack(), entity); } /** * Determines the amount of durability the mending enchantment * will repair, on average, per point of experience. */ default float getXpRepairRatio() { return getStack().getItem().getXpRepairRatio(getStack()); } /** * Called to tick armor in the armor slot. Override to do something */ default void onArmorTick(World world, PlayerEntity player) { getStack().getItem().onArmorTick(getStack(), world, player); } /** * Called every tick from {@link EntityHorse#onUpdate()} on the item in the * armor slot. * * @param world the world the horse is in * @param horse the horse wearing this armor */ default void onHorseArmorTick(World world, MobEntity horse) { getStack().getItem().onHorseArmorTick(getStack(), world, horse); } /** * Determines if the specific ItemStack can be placed in the specified armor * slot, for the entity. * * @param armorType Armor slot to be verified. * @param entity The entity trying to equip the armor * @return True if the given ItemStack can be inserted in the slot */ default boolean canEquip(EquipmentSlotType armorType, Entity entity) { return getStack().getItem().canEquip(getStack(), armorType, entity); } /** * Allow or forbid the specific book/item combination as an anvil enchant * * @param stack The item * @param book The book * @return if the enchantment is allowed */ default boolean isBookEnchantable(ItemStack book) { return getStack().getItem().isBookEnchantable(getStack(), book); } /** * Called when a player drops the item into the world, returning false from this * will prevent the item from being removed from the players inventory and * spawning in the world * * @param player The player that dropped the item * @param item The item stack, before the item is removed. */ default boolean onDroppedByPlayer(PlayerEntity player) { return getStack().getItem().onDroppedByPlayer(getStack(), player); } /** * Allow the item one last chance to modify its name used for the tool highlight * useful for adding something extra that can't be removed by a user in the * displayed name, such as a mode of operation. * * @param displayName the name that will be displayed unless it is changed in * this method. */ default ITextComponent getHighlightTip(ITextComponent displayName) { return getStack().getItem().getHighlightTip(getStack(), displayName); } /** * Get the NBT data to be sent to the client. The Item can control what data is kept in the tag. * * Note that this will sometimes be applied multiple times, the following MUST * be supported: * Item item = stack.getItem(); * NBTTagCompound nbtShare1 = item.getNBTShareTag(stack); * stack.setTagCompound(nbtShare1); * NBTTagCompound nbtShare2 = item.getNBTShareTag(stack); * assert nbtShare1.equals(nbtShare2); * * @return The NBT tag */ @Nullable default CompoundNBT getShareTag() { return getStack().getItem().getShareTag(getStack()); } /** * Override this method to decide what to do with the NBT data received from * getNBTShareTag(). * * @param stack The stack that received NBT * @param nbt Received NBT, can be null */ default void readShareTag(@Nullable CompoundNBT nbt) { getStack().getItem().readShareTag(getStack(), nbt); } /** * * Should this item, when held, allow sneak-clicks to pass through to the underlying block? * * @param world The world * @param pos Block position in world * @param player The Player that is wielding the item * @return */ default boolean doesSneakBypassUse(net.minecraft.world.IWorldReader world, BlockPos pos, PlayerEntity player) { return getStack().isEmpty() || getStack().getItem().doesSneakBypassUse(getStack(), world, pos, player); } /** * Modeled after ItemStack.areItemStackTagsEqual * Uses Item.getNBTShareTag for comparison instead of NBT and capabilities. * Only used for comparing itemStacks that were transferred from server to client using Item.getNBTShareTag. */ default boolean areShareTagsEqual(ItemStack other) { CompoundNBT shareTagA = getStack().getShareTag(); CompoundNBT shareTagB = other.getShareTag(); if (shareTagA == null) return shareTagB == null; else return shareTagB != null && shareTagA.equals(shareTagB); } /** * Determines if the ItemStack is equal to the other item stack, including Item, Count, and NBT. * * @param other The other stack * @param limitTags True to use shareTag False to use full NBT tag * @return true if equals */ default boolean equals(ItemStack other, boolean limitTags) { if (getStack().isEmpty()) return other.isEmpty(); else return !other.isEmpty() && getStack().getCount() == other.getCount() && getStack().getItem() == other.getItem() && (limitTags ? getStack().areShareTagsEqual(other) : ItemStack.areItemStackTagsEqual(getStack(), other)); } /** * Determines if a item is reparable, used by Repair recipes and Grindstone. * * @return True if reparable */ default boolean isRepairable() { return getStack().getItem().isRepairable(getStack()); } /** * Called by Piglins when checking to see if they will give an item or something in exchange for this item. * * @return True if this item can be used as "currency" by piglins */ default boolean isPiglinCurrency() { return getStack().getItem().isPiglinCurrency(getStack()); } /** * Called by Piglins to check if a given item prevents hostility on sight. If this is true the Piglins will be neutral to the entity wearing this item, and will not * attack on sight. Note: This does not prevent Piglins from becoming hostile due to other actions, nor does it make Piglins that are already hostile stop being so. * * @param wearer The entity wearing this ItemStack * * @return True if piglins are neutral to players wearing this item in an armor slot */ default boolean makesPiglinsNeutral(LivingEntity wearer) { return getStack().getItem().makesPiglinsNeutral(getStack(), wearer); } /** * Whether this Item can be used to hide player head for enderman. * * @param player The player watching the enderman * @param endermanEntity The enderman that the player look * @return true if this Item can be used. */ default boolean isEnderMask(PlayerEntity player, EndermanEntity endermanEntity) { return getStack().getItem().isEnderMask(getStack(), player, endermanEntity); } /** * Used to determine if the player can use Elytra flight. * This is called Client and Server side. * * @param entity The entity trying to fly. * @return True if the entity can use Elytra flight. */ default boolean canElytraFly(LivingEntity entity) { return getStack().getItem().canElytraFly(getStack(), entity); } /** * Used to determine if the player can continue Elytra flight, * this is called each tick, and can be used to apply ItemStack damage, * consume Energy, or what have you. * For example the Vanilla implementation of this, applies damage to the * ItemStack every 20 ticks. * * @param entity The entity currently in Elytra flight. * @param flightTicks The number of ticks the entity has been Elytra flying for. * @return True if the entity should continue Elytra flight or False to stop. */ default boolean elytraFlightTick(LivingEntity entity, int flightTicks) { return getStack().getItem().elytraFlightTick(getStack(), entity, flightTicks); } }