All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bukkit.craftbukkit.inventory.CraftItemStack Maven / Gradle / Ivy

There is a newer version: 2.4.0
Show newest version
package org.bukkit.craftbukkit.inventory;

import com.google.common.collect.ImmutableMap;
import net.minecraft.server.EnchantmentManager;
import net.minecraft.server.Item;
import net.minecraft.server.NBTTagCompound;
import net.minecraft.server.NBTTagList;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.Map;

import static org.bukkit.craftbukkit.inventory.CraftMetaItem.*;

@DelegateDeserialization(ItemStack.class)
public final class CraftItemStack extends ItemStack {

   net.minecraft.server.ItemStack handle;

   /**
    * Mirror
    */
   private CraftItemStack(net.minecraft.server.ItemStack item) {
      this.handle = item;
   }

   private CraftItemStack(ItemStack item) {
      this(item.getTypeId(), item.getAmount(), item.getDurability(), item.hasItemMeta() ? item.getItemMeta() : null);
   }

   private CraftItemStack(Material type, int amount, short durability, ItemMeta itemMeta) {
      setType(type);
      setAmount(amount);
      setDurability(durability);
      setItemMeta(itemMeta);
   }

   private CraftItemStack(int typeId, int amount, short durability, ItemMeta itemMeta) {
      this(Material.getMaterial(typeId), amount, durability, itemMeta);
   }

   public static net.minecraft.server.ItemStack asNMSMirror(ItemStack original) {
      if (original instanceof CraftItemStack) {
         CraftItemStack stack = (CraftItemStack) original;
         return stack.handle == null ? null : stack.handle;
      }
      return null;
   }

   public static net.minecraft.server.ItemStack asNMSCopy(ItemStack original) {
      if (original instanceof CraftItemStack) {
         CraftItemStack stack = (CraftItemStack) original;
         return stack.handle == null ? null : stack.handle.cloneItemStack();
      }
      if (original == null || original.getTypeId() <= 0) {
         return null;
      }

      Item item = CraftMagicNumbers.getItem(original.getType());

      if (item == null) {
         return null;
      }

      net.minecraft.server.ItemStack stack = new net.minecraft.server.ItemStack(item, original.getAmount(), original.getDurability());
      if (original.hasItemMeta()) {
         setItemMeta(stack, original.getItemMeta());
      }
      return stack;
   }

   public static net.minecraft.server.ItemStack copyNMSStack(net.minecraft.server.ItemStack original, int amount) {
      net.minecraft.server.ItemStack stack = original.cloneItemStack();
      stack.count = amount;
      return stack;
   }

   /**
    * Copies the NMS stack to return as a strictly-Bukkit stack
    */
   public static ItemStack asBukkitCopy(net.minecraft.server.ItemStack original) {
      if (original == null) {
         return new ItemStack(Material.AIR);
      }
      ItemStack stack = new ItemStack(CraftMagicNumbers.getMaterial(original.getItem()), original.count, (short) original.getData());
      if (hasItemMeta(original)) {
         stack.setItemMeta(getItemMeta(original));
      }
      return stack;
   }

   public static CraftItemStack asCraftMirror(net.minecraft.server.ItemStack original) {
      return new CraftItemStack(original);
   }

   public static CraftItemStack asCraftCopy(ItemStack original) {
      if (original instanceof CraftItemStack) {
         CraftItemStack stack = (CraftItemStack) original;
         return new CraftItemStack(stack.handle == null ? null : stack.handle.cloneItemStack());
      }
      return new CraftItemStack(original);
   }

   public static CraftItemStack asNewCraftStack(Item item) {
      return asNewCraftStack(item, 1);
   }

   public static CraftItemStack asNewCraftStack(Item item, int amount) {
      return new CraftItemStack(CraftMagicNumbers.getMaterial(item), amount, (short) 0, null);
   }

   static boolean makeTag(net.minecraft.server.ItemStack item) {
      if (item == null) {
         return false;
      }

      if (item.getTag() == null) {
         item.setTag(new NBTTagCompound());
      }

      return true;
   }

   static Map getEnchantments(net.minecraft.server.ItemStack item) {
      NBTTagList list = (item != null && item.hasEnchantments()) ? item.getEnchantments() : null;

      if (list == null || list.size() == 0) {
         return ImmutableMap.of();
      }

      ImmutableMap.Builder result = ImmutableMap.builder();

      for (int i = 0; i < list.size(); i++) {
         int id = 0xffff & list.get(i).getShort(ENCHANTMENTS_ID.NBT);
         int level = 0xffff & list.get(i).getShort(ENCHANTMENTS_LVL.NBT);

         result.put(Enchantment.getById(id), level);
      }

      return result.build();
   }

   static NBTTagList getEnchantmentList(net.minecraft.server.ItemStack item) {
      return (item != null && item.hasEnchantments()) ? item.getEnchantments() : null;
   }

   public static ItemMeta getItemMeta(net.minecraft.server.ItemStack item) {
      if (!hasItemMeta(item)) {
         return CraftItemFactory.instance().getItemMeta(getType(item));
      }
      switch (getType(item)) {
         case WRITTEN_BOOK:
            return new CraftMetaBookSigned(item.getTag());
         case BOOK_AND_QUILL:
            return new CraftMetaBook(item.getTag());
         case SKULL_ITEM:
            return new CraftMetaSkull(item.getTag());
         case LEATHER_HELMET:
         case LEATHER_CHESTPLATE:
         case LEATHER_LEGGINGS:
         case LEATHER_BOOTS:
            return new CraftMetaLeatherArmor(item.getTag());
         case POTION:
            return new CraftMetaPotion(item.getTag());
         case MAP:
            return new CraftMetaMap(item.getTag());
         case FIREWORK:
            return new CraftMetaFirework(item.getTag());
         case FIREWORK_CHARGE:
            return new CraftMetaCharge(item.getTag());
         case ENCHANTED_BOOK:
            return new CraftMetaEnchantedBook(item.getTag());
         case BANNER:
            return new CraftMetaBanner(item.getTag());
         case FURNACE:
         case CHEST:
         case TRAPPED_CHEST:
         case JUKEBOX:
         case DISPENSER:
         case DROPPER:
         case SIGN:
         case MOB_SPAWNER:
         case NOTE_BLOCK:
         case PISTON_BASE:
         case BREWING_STAND_ITEM:
         case ENCHANTMENT_TABLE:
         case COMMAND:
         case BEACON:
         case DAYLIGHT_DETECTOR:
         case DAYLIGHT_DETECTOR_INVERTED:
         case HOPPER:
         case REDSTONE_COMPARATOR:
         case FLOWER_POT_ITEM:
            return new CraftMetaBlockState(item.getTag(), CraftMagicNumbers.getMaterial(item.getItem()));
         default:
            return new CraftMetaItem(item.getTag());
      }
   }

   static Material getType(net.minecraft.server.ItemStack item) {
      Material material = Material.getMaterial(item == null ? 0 : CraftMagicNumbers.getId(item.getItem()));
      return material == null ? Material.AIR : material;
   }

   public static boolean setItemMeta(net.minecraft.server.ItemStack item, ItemMeta itemMeta) {
      if (item == null) {
         return false;
      }
      if (CraftItemFactory.instance().equals(itemMeta, null)) {
         item.setTag(null);
         return true;
      }
      if (!CraftItemFactory.instance().isApplicable(itemMeta, getType(item))) {
         return false;
      }

      itemMeta = CraftItemFactory.instance().asMetaFor(itemMeta, getType(item));
      if (itemMeta == null) return true;

      NBTTagCompound tag = new NBTTagCompound();
      item.setTag(tag);

      ((CraftMetaItem) itemMeta).applyToItem(tag);

      return true;
   }

   static boolean hasItemMeta(net.minecraft.server.ItemStack item) {
      return !(item == null || item.getTag() == null || item.getTag().isEmpty());
   }

   @Override
   public int getTypeId() {
      return handle != null ? CraftMagicNumbers.getId(handle.getItem()) : 0;
   }

   @Override
   public void setTypeId(int type) {
      if (getTypeId() == type) {
         return;
      } else if (type == 0) {
         handle = null;
      } else if (CraftMagicNumbers.getItem(type) == null) { // :(
         handle = null;
      } else if (handle == null) {
         handle = new net.minecraft.server.ItemStack(CraftMagicNumbers.getItem(type), 1, 0);
      } else {
         handle.setItem(CraftMagicNumbers.getItem(type));
         if (hasItemMeta()) {
            // This will create the appropriate item meta, which will contain all the data we intend to keep
            setItemMeta(handle, getItemMeta(handle));
         }
      }
      setData(null);
   }

   @Override
   public int getAmount() {
      return handle != null ? handle.count : 0;
   }

   @Override
   public void setAmount(int amount) {
      if (handle == null) {
         return;
      }
      if (amount == 0) {
         handle = null;
      } else {
         handle.count = amount;
      }
   }

   @Override
   public short getDurability() {
      if (handle != null) {
         return (short) handle.getData();
      } else {
         return -1;
      }
   }

   @Override
   public void setDurability(final short durability) {
      // Ignore damage if item is null
      if (handle != null) {
         handle.setData(durability);
      }
   }

   @Override
   public int getMaxStackSize() {
      return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize();
   }

   @Override
   public void addUnsafeEnchantment(Enchantment ench, int level) {
      Validate.notNull(ench, "Cannot add null enchantment");

      if (!makeTag(handle)) {
         return;
      }
      NBTTagList list = getEnchantmentList(handle);
      if (list == null) {
         list = new NBTTagList();
         handle.getTag().set(ENCHANTMENTS.NBT, list);
      }
      int size = list.size();

      for (int i = 0; i < size; i++) {
         NBTTagCompound tag = list.get(i);
         short id = tag.getShort(ENCHANTMENTS_ID.NBT);
         if (id == ench.getId()) {
            tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level);
            return;
         }
      }
      NBTTagCompound tag = new NBTTagCompound();
      tag.setShort(ENCHANTMENTS_ID.NBT, (short) ench.getId());
      tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level);
      list.add(tag);
   }

   @Override
   public boolean containsEnchantment(Enchantment ench) {
      return getEnchantmentLevel(ench) > 0;
   }

   @Override
   public int getEnchantmentLevel(Enchantment ench) {
      Validate.notNull(ench, "Cannot find null enchantment");
      if (handle == null) {
         return 0;
      }
      return EnchantmentManager.getEnchantmentLevel(ench.getId(), handle);
   }

   @Override
   public int removeEnchantment(Enchantment ench) {
      Validate.notNull(ench, "Cannot remove null enchantment");

      NBTTagList list = getEnchantmentList(handle), listCopy;
      if (list == null) {
         return 0;
      }
      int index = Integer.MIN_VALUE;
      int level = Integer.MIN_VALUE;
      int size = list.size();

      for (int i = 0; i < size; i++) {
         NBTTagCompound enchantment = list.get(i);
         int id = 0xffff & enchantment.getShort(ENCHANTMENTS_ID.NBT);
         if (id == ench.getId()) {
            index = i;
            level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT);
            break;
         }
      }

      if (index == Integer.MIN_VALUE) {
         return 0;
      }
      if (size == 1) {
         handle.getTag().remove(ENCHANTMENTS.NBT);
         if (handle.getTag().isEmpty()) {
            handle.setTag(null);
         }
         return level;
      }

      // This is workaround for not having an index removal
      listCopy = new NBTTagList();
      for (int i = 0; i < size; i++) {
         if (i != index) {
            listCopy.add(list.get(i));
         }
      }
      handle.getTag().set(ENCHANTMENTS.NBT, listCopy);

      return level;
   }

   @Override
   public Map getEnchantments() {
      return getEnchantments(handle);
   }

   @Override
   public CraftItemStack clone() {
      CraftItemStack itemStack = (CraftItemStack) super.clone();
      if (this.handle != null) {
         itemStack.handle = this.handle.cloneItemStack();
      }
      return itemStack;
   }

   @Override
   public ItemMeta getItemMeta() {
      return getItemMeta(handle);
   }

   @Override
   public boolean setItemMeta(ItemMeta itemMeta) {
      return setItemMeta(handle, itemMeta);
   }

   @Override
   public boolean isSimilar(ItemStack stack) {
      if (stack == null) {
         return false;
      }
      if (stack == this) {
         return true;
      }
      if (!(stack instanceof CraftItemStack)) {
         return stack.getClass() == ItemStack.class && stack.isSimilar(this);
      }

      CraftItemStack that = (CraftItemStack) stack;
      if (handle == that.handle) {
         return true;
      }
      if (handle == null || that.handle == null) {
         return false;
      }
      if (!(that.getTypeId() == getTypeId() && getDurability() == that.getDurability())) {
         return false;
      }
      return hasItemMeta() ? that.hasItemMeta() && handle.getTag().equals(that.handle.getTag()) : !that.hasItemMeta();
   }

   @Override
   public boolean hasItemMeta() {
      return hasItemMeta(handle);
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy