Remove FabricItem and add an item setting instead

This commit is contained in:
Technici4n 2021-11-18 14:25:13 +01:00
parent fd42517cb8
commit a93205c927
8 changed files with 93 additions and 53 deletions
checkstyle.xml
fabric-item-api-v1/src
main/java/net/fabricmc/fabric
testmod/java/net/fabricmc/fabric/test/item

View file

@ -199,7 +199,10 @@
<!--<module name="InvalidJavadocPosition"/>-->
<module name="JavadocParagraph"/>
<module name="JavadocStyle"/>
<module name="JavadocStyle">
<!-- "First sentence should end with a period." conflicts with the new Java 16 {@return ...}. -->
<property name="checkFirstSentence" value="false"/>
</module>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param,@return,@throws,@deprecated"/>
</module>

View file

@ -53,6 +53,15 @@ public class FabricItemSettings extends Item.Settings {
return this;
}
/**
* Allow cancelling the client-side animation when the NBT or count of this stack changes.
* @see UpdateAnimationHandler
*/
public FabricItemSettings nbtUpdateAnimation(UpdateAnimationHandler handler) {
FabricItemInternals.computeExtraData(this).nbtUpdateAnimation(handler);
return this;
}
// Overrides of vanilla methods
@Override

View file

@ -18,33 +18,25 @@ package net.fabricmc.fabric.api.item.v1;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
/**
* General-purpose Fabric-provided extensions for {@link Item} subclasses.
* When the NBT of an item stack in the main hand or off hand changes, vanilla runs an "update animation".
* If registered, an instance is called on the client side when the NBT or count of the stack has changed, but not the item,
* and returning true allows canceling this animation.
*
* <p>Note: This interface is automatically implemented on all items via Mixin,
* however it has to be implemented explicitly by modders to be able to override functions.
* In the future, it is planned that {@code public class Item implements FabricItem} will be visible in a development environment.
*
* <p>Note to maintainers: Functions should only be added to this interface if they are general-purpose enough,
* to be evaluated on a case-by-case basis. Otherwise they are better suited for more specialized APIs.
* <p>Can be set with {@link FabricItemSettings#nbtUpdateAnimation}.
*/
public interface FabricItem {
@FunctionalInterface
public interface UpdateAnimationHandler {
/**
* 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 true allows canceling this animation.
* {@return true to run the vanilla NBT update animation, false to cancel it}
*
* @param player the current player; this may be safely cast to {@link 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;
}
boolean allowNbtUpdateAnimation(PlayerEntity player, Hand hand, ItemStack oldStack, ItemStack newStack);
}

View file

@ -18,10 +18,13 @@ package net.fabricmc.fabric.impl.item;
import java.util.WeakHashMap;
import org.jetbrains.annotations.Nullable;
import net.minecraft.item.Item;
import net.fabricmc.fabric.api.item.v1.CustomDamageHandler;
import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider;
import net.fabricmc.fabric.api.item.v1.UpdateAnimationHandler;
public final class FabricItemInternals {
private static final WeakHashMap<Item.Settings, ExtraData> extraData = new WeakHashMap<>();
@ -39,12 +42,17 @@ public final class FabricItemInternals {
if (data != null) {
((ItemExtensions) item).fabric_setEquipmentSlotProvider(data.equipmentSlotProvider);
((ItemExtensions) item).fabric_setCustomDamageHandler(data.customDamageHandler);
((ItemExtensions) item).fabric_setUpdateAnimationHandler(data.updateAnimationHandler);
}
}
public static final class ExtraData {
private /* @Nullable */ EquipmentSlotProvider equipmentSlotProvider;
private /* @Nullable */ CustomDamageHandler customDamageHandler;
@Nullable
private EquipmentSlotProvider equipmentSlotProvider;
@Nullable
private CustomDamageHandler customDamageHandler;
@Nullable
private UpdateAnimationHandler updateAnimationHandler;
public void equipmentSlot(EquipmentSlotProvider equipmentSlotProvider) {
this.equipmentSlotProvider = equipmentSlotProvider;
@ -53,5 +61,9 @@ public final class FabricItemInternals {
public void customDamage(CustomDamageHandler handler) {
this.customDamageHandler = handler;
}
public void nbtUpdateAnimation(UpdateAnimationHandler handler) {
this.updateAnimationHandler = handler;
}
}
}

View file

@ -16,12 +16,22 @@
package net.fabricmc.fabric.impl.item;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.fabric.api.item.v1.CustomDamageHandler;
import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider;
import net.fabricmc.fabric.api.item.v1.UpdateAnimationHandler;
public interface ItemExtensions {
/* @Nullable */ EquipmentSlotProvider fabric_getEquipmentSlotProvider();
@Nullable
EquipmentSlotProvider fabric_getEquipmentSlotProvider();
void fabric_setEquipmentSlotProvider(EquipmentSlotProvider equipmentSlotProvider);
/* @Nullable */ CustomDamageHandler fabric_getCustomDamageHandler();
@Nullable
CustomDamageHandler fabric_getCustomDamageHandler();
void fabric_setCustomDamageHandler(CustomDamageHandler handler);
@Nullable
UpdateAnimationHandler fabric_getUpdateAnimationHandler();
void fabric_setUpdateAnimationHandler(UpdateAnimationHandler handler);
}

View file

@ -16,6 +16,7 @@
package net.fabricmc.fabric.mixin.item;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@ -26,17 +27,20 @@ import net.minecraft.item.Item;
import net.fabricmc.fabric.api.item.v1.CustomDamageHandler;
import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider;
import net.fabricmc.fabric.api.item.v1.FabricItem;
import net.fabricmc.fabric.api.item.v1.UpdateAnimationHandler;
import net.fabricmc.fabric.impl.item.FabricItemInternals;
import net.fabricmc.fabric.impl.item.ItemExtensions;
@Mixin(Item.class)
abstract class ItemMixin implements ItemExtensions, FabricItem {
abstract class ItemMixin implements ItemExtensions {
@Unique
private EquipmentSlotProvider equipmentSlotProvider;
private EquipmentSlotProvider fabric_equipmentSlotProvider;
@Unique
private CustomDamageHandler customDamageHandler;
private CustomDamageHandler fabric_customDamageHandler;
@Unique
private UpdateAnimationHandler fabric_updateAnimationHandler;
@Inject(method = "<init>", at = @At("RETURN"))
private void onConstruct(Item.Settings settings, CallbackInfo info) {
@ -45,21 +49,31 @@ abstract class ItemMixin implements ItemExtensions, FabricItem {
@Override
public EquipmentSlotProvider fabric_getEquipmentSlotProvider() {
return equipmentSlotProvider;
return fabric_equipmentSlotProvider;
}
@Override
public void fabric_setEquipmentSlotProvider(EquipmentSlotProvider equipmentSlotProvider) {
this.equipmentSlotProvider = equipmentSlotProvider;
this.fabric_equipmentSlotProvider = equipmentSlotProvider;
}
@Override
public CustomDamageHandler fabric_getCustomDamageHandler() {
return customDamageHandler;
return fabric_customDamageHandler;
}
@Override
public void fabric_setCustomDamageHandler(CustomDamageHandler handler) {
this.customDamageHandler = handler;
this.fabric_customDamageHandler = handler;
}
@Override
public @Nullable UpdateAnimationHandler fabric_getUpdateAnimationHandler() {
return fabric_updateAnimationHandler;
}
@Override
public void fabric_setUpdateAnimationHandler(UpdateAnimationHandler handler) {
this.fabric_updateAnimationHandler = handler;
}
}

View file

@ -19,20 +19,21 @@ package net.fabricmc.fabric.mixin.item.client;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.fabricmc.fabric.api.item.v1.FabricItem;
import net.fabricmc.fabric.api.item.v1.UpdateAnimationHandler;
import net.fabricmc.fabric.impl.item.ItemExtensions;
/**
* Allow canceling the held item update animation if {@link FabricItem#allowNbtUpdateAnimation} returns false.
* Allow canceling the held item update animation if {@link UpdateAnimationHandler#allowNbtUpdateAnimation} returns false.
*/
@Mixin(HeldItemRenderer.class)
public class HeldItemRendererMixin {
@ -51,19 +52,28 @@ public class HeldItemRendererMixin {
// Modify main hand
ItemStack newMainStack = client.player.getMainHandStack();
if (mainHand.getItem() == newMainStack.getItem()) {
if (!((FabricItem) mainHand.getItem()).allowNbtUpdateAnimation(client.player, Hand.MAIN_HAND, mainHand, newMainStack)) {
mainHand = newMainStack;
}
if (suppressUpdate(Hand.MAIN_HAND, mainHand, newMainStack)) {
mainHand = newMainStack;
}
// Modify off hand
ItemStack newOffStack = client.player.getOffHandStack();
if (offHand.getItem() == newOffStack.getItem()) {
if (!((FabricItem) offHand.getItem()).allowNbtUpdateAnimation(client.player, Hand.OFF_HAND, offHand, newOffStack)) {
offHand = newOffStack;
}
if (suppressUpdate(Hand.OFF_HAND, offHand, newOffStack)) {
offHand = newOffStack;
}
}
@Unique
private boolean suppressUpdate(Hand hand, ItemStack oldStack, ItemStack newStack) {
if (oldStack.getItem() == newStack.getItem()) {
UpdateAnimationHandler handler = ((ItemExtensions) oldStack.getItem()).fabric_getUpdateAnimationHandler();
if (handler != null) {
return !handler.allowNbtUpdateAnimation(client.player, hand, oldStack, newStack);
}
}
return false;
}
}

View file

@ -17,22 +17,17 @@
package net.fabricmc.fabric.test.item;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.Hand;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.item.v1.FabricItem;
public class UpdatingItem extends Item implements FabricItem {
private final boolean allowUpdateAnimation;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
public class UpdatingItem extends Item {
public UpdatingItem(boolean allowUpdateAnimation) {
super(new Settings().group(ItemGroup.MISC));
this.allowUpdateAnimation = allowUpdateAnimation;
super(new FabricItemSettings().group(ItemGroup.MISC).nbtUpdateAnimation((p, h, o, n) -> allowUpdateAnimation));
}
@Override
@ -42,9 +37,4 @@ public class UpdatingItem extends Item implements FabricItem {
tag.putLong("ticks", tag.getLong("ticks")+1);
}
}
@Override
public boolean allowNbtUpdateAnimation(PlayerEntity player, Hand hand, ItemStack originalStack, ItemStack updatedStack) {
return allowUpdateAnimation;
}
}