diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItem.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItem.java index f53546fc6a..65bdcec4fc 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItem.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItem.java @@ -17,6 +17,8 @@ package net.fabricmc.fabric.api.item.v1; import com.google.common.collect.Multimap; +import org.jetbrains.annotations.Nullable; + import net.minecraft.block.BlockState; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.attribute.EntityAttribute; @@ -26,7 +28,6 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.Hand; -import org.jetbrains.annotations.Nullable; /** * General-purpose Fabric-provided extensions for {@link Item} subclasses. @@ -37,97 +38,101 @@ * to be evaluated on a case-by-case basis. Otherwise, they are better suited for more specialized APIs. */ public interface FabricItem { + /** + * When the NBT of an item stack in the main hand or off hand changes, vanilla runs an "update animation". + * This function is called on the client side when the NBT or count of the stack has changed, but not the item, + * and returning false cancels this animation. + * + * @param player the current player; this may be safely cast to {@link net.minecraft.client.network.ClientPlayerEntity} in client-only code + * @param hand the hand; this function applies both to the main hand and the off hand + * @param oldStack the previous stack, of this item + * @param newStack the new stack, also of this item + * @return true to run the vanilla animation, false to cancel it. + */ + default boolean allowNbtUpdateAnimation(PlayerEntity player, Hand hand, ItemStack oldStack, ItemStack newStack) { + return true; + } - /** - * When the NBT of an item stack in the main hand or off hand changes, vanilla runs an "update animation". - * This function is called on the client side when the NBT or count of the stack has changed, but not the item, - * and returning false cancels this animation. - * @param player the current player; this may be safely cast to {@link net.minecraft.client.network.ClientPlayerEntity} in client-only code - * @param hand the hand; this function applies both to the main hand and the off hand - * @param oldStack the previous stack, of this item - * @param newStack the new stack, also of this item - * @return true to run the vanilla animation, false to cancel it. - */ - default boolean allowNbtUpdateAnimation(PlayerEntity player, Hand hand, ItemStack oldStack, ItemStack newStack) { - return true; - } - - /** - * When the NBT of the selected stack changes, block breaking progress is reset. - * This function is called when the NBT of the selected stack has changed, - * and returning true allows the block breaking progress to continue. - * @param player the player breaking the block - * @param oldStack the previous stack, of this item - * @param newStack the new stack, also of this item - * @return true to allow continuing block breaking, false to reset the progress. - */ - default boolean allowContinuingBlockBreaking(PlayerEntity player, ItemStack oldStack, ItemStack newStack) { - return false; - } - - /** - * Return the attribute modifiers to apply when this stack is worn in a living entity equipment slot. - * Stack-aware version of {@link Item#getAttributeModifiers(EquipmentSlot)}. - * - *

Note that attribute modifiers are only updated when the stack changes, i.e. when {@code ItemStack.areEqual(old, new)} is false. - * @param stack the current stack - * @param slot the equipment slot this stack is in - * @return the attribute modifiers - */ - default Multimap getAttributeModifiers(ItemStack stack, EquipmentSlot slot) { - return ((Item) this).getAttributeModifiers(slot); - } + /** + * When the NBT of the selected stack changes, block breaking progress is reset. + * This function is called when the NBT of the selected stack has changed, + * and returning true allows the block breaking progress to continue. + * + * @param player the player breaking the block + * @param oldStack the previous stack, of this item + * @param newStack the new stack, also of this item + * @return true to allow continuing block breaking, false to reset the progress. + */ + default boolean allowContinuingBlockBreaking(PlayerEntity player, ItemStack oldStack, ItemStack newStack) { + return false; + } - /** - * Determines if mining with this item allows drops to be harvested from the specified block state. - * Stack-aware version of {@link Item#isSuitableFor(BlockState)}. - * @param stack the current stack - * @param state the block state of the targeted block - * @return true if drops can be harvested - */ - default boolean isSuitableFor(ItemStack stack, BlockState state) { - return ((Item) this).isSuitableFor(state); - } + /** + * Return the attribute modifiers to apply when this stack is worn in a living entity equipment slot. + * Stack-aware version of {@link Item#getAttributeModifiers(EquipmentSlot)}. + * + *

Note that attribute modifiers are only updated when the stack changes, i.e. when {@code ItemStack.areEqual(old, new)} is false. + * + * @param stack the current stack + * @param slot the equipment slot this stack is in + * @return the attribute modifiers + */ + default Multimap getAttributeModifiers(ItemStack stack, EquipmentSlot slot) { + return ((Item) this).getAttributeModifiers(slot); + } - /** - * Returns a leftover item stack after {@code stack} is consumed in a recipe. - * (This is also known as "recipe remainder".) - * For example, using a lava bucket in a furnace as fuel will leave an empty bucket. - * - *

Here is an example for a recipe remainder that increments the item's damage. - * - *

{@code
-     *  if (stack.getDamage() < stack.getMaxDamage() - 1) {
-     *  	ItemStack moreDamaged = stack.copy();
-     *  	moreDamaged.setDamage(stack.getDamage() + 1);
-     *  	return moreDamaged;
-     *  }
-     *
-     *  return ItemStack.EMPTY;
-     * }
- * - * - *

This is a stack-aware version of {@link Item#getRecipeRemainder()}. - * - *

Note that simple item remainders can also be set via {@link Item.Settings#recipeRemainder(Item)}. - * - *

If you want to get a remainder for a stack, - * is recommended to use the stack version of this method: {@link FabricItemStack#getRecipeRemainder()}. - * @param stack the consumed {@link ItemStack} - * @return the leftover item stack - */ - default ItemStack getRecipeRemainder(ItemStack stack) { - return ((Item) this).hasRecipeRemainder() ? ((Item) this).getRecipeRemainder().getDefaultStack() : ItemStack.EMPTY; - } + /** + * Determines if mining with this item allows drops to be harvested from the specified block state. + * Stack-aware version of {@link Item#isSuitableFor(BlockState)}. + * + * @param stack the current stack + * @param state the block state of the targeted block + * @return true if drops can be harvested + */ + default boolean isSuitableFor(ItemStack stack, BlockState state) { + return ((Item) this).isSuitableFor(state); + } - /** - * This is a stack-aware version of {@link Item#getFoodComponent()}. - * Note that simple item remainders can also be set via {@link Item.Settings#food(FoodComponent)}. - * If you want to get a remainder for a stack, is recommended to use the stack version of this method: {@link FabricItemStack#getFoodComponent()}. - * @return this item's {@link FoodComponent}, or {@code null} if none was set. - */ - default @Nullable FoodComponent getFoodComponent(ItemStack stack) { - return ((Item) this).getFoodComponent(); - } + /** + * Returns a leftover item stack after {@code stack} is consumed in a recipe. + * (This is also known as "recipe remainder".) + * For example, using a lava bucket in a furnace as fuel will leave an empty bucket. + * + *

Here is an example for a recipe remainder that increments the item's damage. + * + *

{@code
+	 *  if (stack.getDamage() < stack.getMaxDamage() - 1) {
+	 *  	ItemStack moreDamaged = stack.copy();
+	 *  	moreDamaged.setDamage(stack.getDamage() + 1);
+	 *  	return moreDamaged;
+	 *  }
+	 *
+	 *  return ItemStack.EMPTY;
+	 * }
+ * + * + *

This is a stack-aware version of {@link Item#getRecipeRemainder()}. + * + *

Note that simple item remainders can also be set via {@link Item.Settings#recipeRemainder(Item)}. + * + *

If you want to get a remainder for a stack, + * is recommended to use the stack version of this method: {@link FabricItemStack#getRecipeRemainder()}. + * + * @param stack the consumed {@link ItemStack} + * @return the leftover item stack + */ + default ItemStack getRecipeRemainder(ItemStack stack) { + return ((Item) this).hasRecipeRemainder() ? ((Item) this).getRecipeRemainder().getDefaultStack() : ItemStack.EMPTY; + } + /** + * This is a stack-aware version of {@link Item#getFoodComponent()}. + * Note that simple item remainders can also be set via {@link Item.Settings#food(FoodComponent)}. + * If you want to get a remainder for a stack, is recommended to use the stack version of this method: {@link FabricItemStack#getFoodComponent()}. + * + * @return this item's {@link FoodComponent}, or {@code null} if none was set. + */ + default @Nullable FoodComponent getFoodComponent(ItemStack stack) { + return ((Item) this).getFoodComponent(); + } } diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItemStack.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItemStack.java index 66f0d06f87..8ab3681663 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItemStack.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItemStack.java @@ -16,10 +16,11 @@ package net.fabricmc.fabric.api.item.v1; +import org.jetbrains.annotations.Nullable; + import net.minecraft.item.FoodComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import org.jetbrains.annotations.Nullable; /* * Fabric-provided extensions for {@link ItemStack}. @@ -42,6 +43,7 @@ default ItemStack getRecipeRemainder() { /** * Stack-aware version of {@link Item#getFoodComponent()}. * See {@link FabricItem#getFoodComponent(ItemStack)} for a more in depth description. + * * @return this itemStack's {@link FoodComponent}, or {@code null} if none was set. */ default @Nullable FoodComponent getFoodComponent() { diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/CatEntityMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/CatEntityMixin.java index 2e68aec743..76c988ad6c 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/CatEntityMixin.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/CatEntityMixin.java @@ -1,21 +1,36 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.fabricmc.fabric.mixin.item; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + import net.minecraft.entity.passive.CatEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.FoodComponent; import net.minecraft.item.Item; import net.minecraft.util.Hand; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(CatEntity.class) class CatEntityMixin { - - @Redirect(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) - private @Nullable FoodComponent getStackAwareFoodComponent(Item instance, PlayerEntity player, Hand hand) { - return player.getStackInHand(hand).getFoodComponent(); - } - + @Redirect(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) + private @Nullable FoodComponent getStackAwareFoodComponent(Item instance, PlayerEntity player, Hand hand) { + return player.getStackInHand(hand).getFoodComponent(); + } } diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/HungerManagerMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/HungerManagerMixin.java index 6470eae4b9..dbddfd687a 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/HungerManagerMixin.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/HungerManagerMixin.java @@ -1,22 +1,35 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.fabricmc.fabric.mixin.item; -import net.minecraft.entity.player.HungerManager; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.FoodComponent; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Hand; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import net.minecraft.entity.player.HungerManager; +import net.minecraft.item.FoodComponent; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + @Mixin(HungerManager.class) class HungerManagerMixin { - - @Redirect(method = "eat", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) - private @Nullable FoodComponent getStackAwareFoodComponent(Item instance,Item item, ItemStack stack) { - return stack.getFoodComponent(); - } - + @Redirect(method = "eat", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) + private @Nullable FoodComponent getStackAwareFoodComponent(Item instance, Item item, ItemStack stack) { + return stack.getFoodComponent(); + } } diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ItemMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ItemMixin.java index cd19560e9f..b51602b43b 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ItemMixin.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ItemMixin.java @@ -16,11 +16,6 @@ package net.fabricmc.fabric.mixin.item; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.FoodComponent; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Hand; -import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -29,7 +24,12 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.FoodComponent; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.world.World; import net.fabricmc.fabric.api.item.v1.CustomDamageHandler; import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider; diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/LivingEntityMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/LivingEntityMixin.java index bb667de883..f4e0d18f8d 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/LivingEntityMixin.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/LivingEntityMixin.java @@ -16,9 +16,6 @@ package net.fabricmc.fabric.mixin.item; -import net.minecraft.item.FoodComponent; -import net.minecraft.item.Item; -import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -29,15 +26,18 @@ import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LivingEntity; +import net.minecraft.item.FoodComponent; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.world.World; import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider; import net.fabricmc.fabric.impl.item.ItemExtensions; @Mixin(LivingEntity.class) abstract class LivingEntityMixin { - - @Shadow protected ItemStack activeItemStack; + @Shadow + protected ItemStack activeItemStack; @Inject(method = "getPreferredEquipmentSlot", at = @At(value = "HEAD"), cancellable = true) private static void onGetPreferredEquipmentSlot(ItemStack stack, CallbackInfoReturnable info) { @@ -48,12 +48,12 @@ private static void onGetPreferredEquipmentSlot(ItemStack stack, CallbackInfoRet } } - @Redirect(method = "shouldSpawnConsumptionEffects",at = @At(value = "INVOKE",target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) + @Redirect(method = "shouldSpawnConsumptionEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) private @Nullable FoodComponent getStackAwareFoodComponent(Item instance) { return this.activeItemStack.getFoodComponent(); } - @Redirect(method = "applyFoodEffects",at = @At(value = "INVOKE",target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) + @Redirect(method = "applyFoodEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) private @Nullable FoodComponent getStackAwareFoodComponent(Item instance, ItemStack stack, World world, LivingEntity targetEntity) { return stack.getFoodComponent(); } diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/WolfEntityMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/WolfEntityMixin.java index 4e007a1f53..0d53df3a74 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/WolfEntityMixin.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/WolfEntityMixin.java @@ -1,27 +1,42 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.fabricmc.fabric.mixin.item; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + import net.minecraft.entity.passive.WolfEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.FoodComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.Hand; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(WolfEntity.class) class WolfEntityMixin { + @Redirect(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) + private @Nullable FoodComponent getStackAwareFoodComponent(Item instance, PlayerEntity player, Hand hand) { + return player.getStackInHand(hand).getFoodComponent(); + } - @Redirect(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) - private @Nullable FoodComponent getStackAwareFoodComponent(Item instance, PlayerEntity player, Hand hand) { - return player.getStackInHand(hand).getFoodComponent(); - } - - @Redirect(method = "isBreedingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) - private @Nullable FoodComponent getStackAwareFoodComponent(Item instance, ItemStack stack) { - return stack.getFoodComponent(); - } - + @Redirect(method = "isBreedingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;getFoodComponent()Lnet/minecraft/item/FoodComponent;")) + private @Nullable FoodComponent getStackAwareFoodComponent(Item instance, ItemStack stack) { + return stack.getFoodComponent(); + } }