VillagerTradeLimiter/src/com/pretzel/dev/villagertradelimiter/nms/NBTItem.java

177 lines
4.9 KiB
Java

package com.pretzel.dev.villagertradelimiter.nms;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import com.pretzel.dev.villagertradelimiter.nms.utils.nmsmappings.ReflectionMethod;
/**
* NBT class to access vanilla/custom tags on ItemStacks. This class doesn't
* autosave to the Itemstack, use getItem to get the changed ItemStack
*
* @author tr7zw
*
*/
public class NBTItem extends NBTCompound {
private ItemStack bukkitItem;
private boolean directApply;
private ItemStack originalSrcStack = null;
/**
* Constructor for NBTItems. The ItemStack will be cloned!
*
* @param item
*/
public NBTItem(ItemStack item) {
this(item, false);
}
/**
* Constructor for NBTItems. The ItemStack will be cloned! If directApply is true,
* all changed will be mapped to the original item. Changes to the NBTItem will overwrite changes done
* to the original item in that case.
*
* @param item
* @param directApply
*/
public NBTItem(ItemStack item, boolean directApply) {
super(null, null);
if (item == null || item.getType() == Material.AIR) {
throw new NullPointerException("ItemStack can't be null/Air!");
}
this.directApply = directApply;
bukkitItem = item.clone();
if(directApply) {
this.originalSrcStack = item;
}
}
@Override
public Object getCompound() {
return NBTReflectionUtil.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem));
}
@Override
protected void setCompound(Object compound) {
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, compound);
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
}
/**
* Apply stored NBT tags to the provided ItemStack.
* <p>
* Note: This will completely override current item's {@link ItemMeta}.
* If you still want to keep the original item's NBT tags, see
* {@link #mergeNBT(ItemStack)} and {@link #mergeCustomNBT(ItemStack)}.
*
* @param item ItemStack that should get the new NBT data
*/
public void applyNBT(ItemStack item) {
if (item == null || item.getType() == Material.AIR) {
throw new NullPointerException("ItemStack can't be null/Air!");
}
NBTItem nbti = new NBTItem(new ItemStack(item.getType()));
nbti.mergeCompound(this);
item.setItemMeta(nbti.getItem().getItemMeta());
}
/**
* Merge all NBT tags to the provided ItemStack.
*
* @param item ItemStack that should get the new NBT data
*/
public void mergeNBT(ItemStack item) {
NBTItem nbti = new NBTItem(item);
nbti.mergeCompound(this);
item.setItemMeta(nbti.getItem().getItemMeta());
}
/**
* Merge only custom (non-vanilla) NBT tags to the provided ItemStack.
*
* @param item ItemStack that should get the new NBT data
*/
public void mergeCustomNBT(ItemStack item) {
if (item == null || item.getType() == Material.AIR) {
throw new NullPointerException("ItemStack can't be null/Air!");
}
ItemMeta meta = item.getItemMeta();
NBTReflectionUtil.getUnhandledNBTTags(meta).putAll(NBTReflectionUtil.getUnhandledNBTTags(bukkitItem.getItemMeta()));
item.setItemMeta(meta);
}
/**
* True, if the item has any tags now known for this item type.
*
* @return true when custom tags are present
*/
public boolean hasCustomNbtData() {
ItemMeta meta = bukkitItem.getItemMeta();
return !NBTReflectionUtil.getUnhandledNBTTags(meta).isEmpty();
}
/**
* Remove all custom (non-vanilla) NBT tags from the NBTItem.
*/
public void clearCustomNBT() {
ItemMeta meta = bukkitItem.getItemMeta();
NBTReflectionUtil.getUnhandledNBTTags(meta).clear();
bukkitItem.setItemMeta(meta);
}
/**
* @return The modified ItemStack
*/
public ItemStack getItem() {
return bukkitItem;
}
protected void setItem(ItemStack item) {
bukkitItem = item;
}
/**
* This may return true even when the NBT is empty.
*
* @return Does the ItemStack have a NBTCompound.
*/
public boolean hasNBTData() {
return getCompound() != null;
}
/**
* Helper method that converts {@link ItemStack} to {@link NBTContainer} with
* all it's data like Material, Damage, Amount and Tags.
*
* @param item
* @return Standalone {@link NBTContainer} with the Item's data
*/
public static NBTContainer convertItemtoNBT(ItemStack item) {
return NBTReflectionUtil.convertNMSItemtoNBTCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, item));
}
/**
* Helper method to do the inverse to "convertItemtoNBT". Creates an
* {@link ItemStack} using the {@link NBTCompound}
*
* @param comp
* @return ItemStack using the {@link NBTCompound}'s data
*/
public static ItemStack convertNBTtoItem(NBTCompound comp) {
return (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null,
NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp));
}
@Override
protected void saveCompound() {
if(directApply) {
applyNBT(originalSrcStack);
}
}
}