From 9319dbc00f434dee2197587d870fadf35bf36218 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sat, 3 Apr 2021 15:28:30 +0800 Subject: [PATCH] Fix item nbt being reset when dragging (#206) --- .../bridge/bukkit/CraftItemStackBridge.java | 8 +++ .../mixin/bukkit/CraftItemStackMixin.java | 70 ++++++++++++++++++- .../mixin/bukkit/CraftMetaItemMixin.java | 7 ++ 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/CraftItemStackBridge.java diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/CraftItemStackBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/CraftItemStackBridge.java new file mode 100644 index 00000000..52d290aa --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/CraftItemStackBridge.java @@ -0,0 +1,8 @@ +package io.izzel.arclight.common.bridge.bukkit; + +import net.minecraft.item.ItemStack; + +public interface CraftItemStackBridge { + + ItemStack bridge$getHandle(); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftItemStackMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftItemStackMixin.java index 09f57524..bc7c72e6 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftItemStackMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftItemStackMixin.java @@ -1,5 +1,6 @@ package io.izzel.arclight.common.mixin.bukkit; +import io.izzel.arclight.common.bridge.bukkit.CraftItemStackBridge; import io.izzel.arclight.common.bridge.bukkit.ItemMetaBridge; import io.izzel.arclight.common.bridge.bukkit.MaterialBridge; import io.izzel.arclight.common.bridge.item.ItemStackBridge; @@ -10,19 +11,27 @@ import org.bukkit.Material; import org.bukkit.craftbukkit.v.inventory.CraftItemFactory; import org.bukkit.craftbukkit.v.inventory.CraftItemStack; import org.bukkit.craftbukkit.v.inventory.CraftMetaItem; +import org.bukkit.craftbukkit.v.legacy.CraftLegacy; import org.bukkit.inventory.meta.ItemMeta; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Objects; + @Mixin(value = CraftItemStack.class, remap = false) -public abstract class CraftItemStackMixin { +public abstract class CraftItemStackMixin implements CraftItemStackBridge { // @formatter:off @Shadow static Material getType(ItemStack item) { return null; } @Shadow static boolean hasItemMeta(ItemStack item) { return false; } + @Shadow ItemStack handle; + @Shadow public abstract Material getType(); + @Shadow public abstract short getDurability(); + @Shadow public abstract boolean hasItemMeta(); // @formatter:on @Inject(method = "getItemMeta(Lnet/minecraft/item/ItemStack;)Lorg/bukkit/inventory/meta/ItemMeta;", @@ -31,8 +40,14 @@ public abstract class CraftItemStackMixin { Material type = getType(item); if (((MaterialBridge) (Object) type).bridge$getType() != MaterialPropertySpec.MaterialType.VANILLA) { if (hasItemMeta(item)) { - CraftMetaItem metaItem = new CraftMetaItem(item.getTag()); - ((ItemMetaBridge) metaItem).bridge$offerUnhandledTags(item.getTag()); + CompoundNBT tag = item.getTag(); + CraftMetaItem metaItem; + if (tag != null) { + metaItem = new CraftMetaItem(tag); + ((ItemMetaBridge) metaItem).bridge$offerUnhandledTags(tag); + } else { + metaItem = new CraftMetaItem(new CompoundNBT()); + } ((ItemMetaBridge) metaItem).bridge$setForgeCaps(((ItemStackBridge) (Object) item).bridge$getForgeCaps()); cir.setReturnValue(metaItem); } else { @@ -49,4 +64,53 @@ public abstract class CraftItemStackMixin { ((ItemStackBridge)(Object) item).bridge$setForgeCaps(forgeCaps.copy()); } } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public boolean isSimilar(org.bukkit.inventory.ItemStack stack) { + if (stack == null) { + return false; + } + if (stack == (Object) this) { + return true; + } + if (!(stack instanceof CraftItemStack)) { + return stack.getClass() == org.bukkit.inventory.ItemStack.class && stack.isSimilar((org.bukkit.inventory.ItemStack) (Object) this); + } + + CraftItemStack that = (CraftItemStack) stack; + if (handle == ((CraftItemStackBridge) (Object) that).bridge$getHandle()) { + return true; + } + if (handle == null || ((CraftItemStackBridge) (Object) that).bridge$getHandle() == null) { + return false; + } + Material comparisonType = CraftLegacy.fromLegacy(that.getType()); // This may be called from legacy item stacks, try to get the right material + if (!(comparisonType == this.getType() && getDurability() == that.getDurability())) { + return false; + } + return hasItemMeta() + ? (that.hasItemMeta() + && Objects.equals(handle.getTag(), ((CraftItemStackBridge) (Object) that).bridge$getHandle().getTag()) + && Objects.equals(((ItemStackBridge) (Object) handle).bridge$getForgeCaps(), ((ItemStackBridge) (Object) ((CraftItemStackBridge) (Object) that).bridge$getHandle()).bridge$getForgeCaps())) + : !that.hasItemMeta(); + } + + @Inject(method = "hasItemMeta(Lnet/minecraft/item/ItemStack;)Z", cancellable = true, at = @At("HEAD")) + private static void arclight$hasMeta(ItemStack item, CallbackInfoReturnable cir) { + if (item != null) { + CompoundNBT forgeCaps = ((ItemStackBridge) (Object) item).bridge$getForgeCaps(); + if (forgeCaps != null && !forgeCaps.isEmpty()) { + cir.setReturnValue(true); + } + } + } + + @Override + public ItemStack bridge$getHandle() { + return handle; + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMetaItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMetaItemMixin.java index 37963105..46bf9a0c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMetaItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMetaItemMixin.java @@ -116,6 +116,13 @@ public class CraftMetaItemMixin implements ItemMetaBridge { return 61 * hash + (this.forgeCaps != null ? this.forgeCaps.hashCode() : 0); } + @Inject(method = "isEmpty", cancellable = true,at = @At("HEAD")) + private void arclight$forgeCapsEmpty(CallbackInfoReturnable cir) { + if (this.forgeCaps != null && !this.forgeCaps.isEmpty()) { + cir.setReturnValue(false); + } + } + @Inject(method = "equalsCommon", cancellable = true, at = @At("HEAD")) private void arclight$forgeCapsEquals(CraftMetaItem that, CallbackInfoReturnable cir) { CompoundNBT forgeCaps = ((ItemMetaBridge) that).bridge$getForgeCaps();