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

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

package org.bukkit.craftbukkit.inventory;

import com.google.common.collect.ImmutableMap;
import net.minecraft.server.*;
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 walkmc.item.IItem;

import java.util.ArrayList;
import java.util.List;
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;
	}
	
	/*
	 TODO: When adding extra data for item stacks, remember to add compatibility in this method.
	 */
	private CraftItemStack(ItemStack item) {
		this(item.getTypeId(), item.getAmount(),item.getDurability(), item.hasItemMeta() ? item.getItemMeta() : null);
	
		// walkmc start
		if (handle != null) {
			if (item.hasCustomItem())
				handle.setCustomItem(item.getCustomItem());
			
			if (item.hasTag())
				handle.addAll(item.getTag());
		}
		// walkmc end
	}
	
	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 asNMSCopy(original); // fallback
	}
	
	
	/*
	 TODO: When adding extra data for item stacks, remember to add compatibility in this method.
	 */
	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());
		
		// walkmc start
		if (original.hasCustomItem())
			stack.setCustomItem(original.getCustomItem());
		
		if (original.hasTag())
			stack.addAll(original.getTag());
		// walkmc end
		
		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
	 */
	/*
	 TODO: When adding extra data for item stacks, remember to add compatibility in this method.
	 */
	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));
		
		// walkmc start
		if (original.getCustomItem() != null)
			stack.setCustomItem(original.getCustomItem());
		
		if (original.hasTag())
			stack.setTag(original.getTag());
		// walkmc end
		
		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.getCompound(i).getShort(ENCHANTMENTS_ID.NBT);
			//int level = 0xffff & list.get(i).getShort(ENCHANTMENTS_LVL.NBT);
			int level = list.getCompound(i).getInt(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.setItemDamage(durability);
		}
	}
	
	@Override
	public int getMaxStackSize() {
		return (handle == null) ? Material.AIR.getMaxStackSize() : handle.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.getCompound(i);
			short id = tag.getShort(ENCHANTMENTS_ID.NBT);
			if (id == ench.getId()) {
				//tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level);
				tag.setInt(ENCHANTMENTS_LVL.NBT, level);
				return;
			}
		}
		NBTTagCompound tag = new NBTTagCompound();
		tag.setShort(ENCHANTMENTS_ID.NBT, (short) ench.getId());
		//tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level);
		tag.setInt(ENCHANTMENTS_LVL.NBT, 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.getCompound(i);
			int id = 0xffff & enchantment.getShort(ENCHANTMENTS_ID.NBT);
			if (id == ench.getId()) {
				index = i;
				// level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT);
				level = enchantment.getInt(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.getCompound(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);
	}
	
	@Override
	public NBTTagCompound getTag() {
		if (handle == null)
			return new NBTTagCompound();
		
		if (handle.tag == null)
			handle.tag = new NBTTagCompound();
		
		return handle.tag;
	}
	
	@Override
	public void setTag(NBTTagCompound tag) {
		if (handle != null)
			handle.tag = tag;
	}
	
	@Override
	public boolean hasTag() {
		return handle != null && handle.tag != null;
	}
	
	@Override
	public IItem getCustomItem() {
		return handle == null ? null : handle.getCustomItem();
	}
	
	@Override
	public void setCustomItem(IItem customItem) {
		if (handle != null)
			handle.setCustomItem(customItem);
	}
	
	@Override
	public boolean hasCustomItem() {
		return getCustomItem() != null;
	}
	
	@Override
	public CraftItemStack getCraftItem() {
		return this;
	}
	
	@Override
	public net.minecraft.server.ItemStack getHandler() {
		return handle;
	}
	
	@Override
	public String getName() {
		if (handle == null || handle.tag == null)
			return null;
		
		return handle.getName();
	}
	
	@Override
	public List getLore() {
		if (handle == null || handle.tag == null)
			return null;
		
		if (!handle.tag.hasKey("display"))
			return null;
		
		NBTTagCompound display = handle.tag.getCompound("display");
		if (!display.hasKey("Lore"))
			return null;
		
		ArrayList result = new ArrayList<>();
		NBTTagList lore = display.getList("Lore", NBTBase.LIST);
		for (NBTBase line : lore) {
			result.add(((NBTTagString) line).data);
		}
		
		return result;
	}
	
	@Override
	public void setName(String name) {
		if (handle != null) {
			handle.setName(name);
		}
	}
	
	@Override
	public void setLore(List lore) {
		if (handle != null) {
			NBTTagList list = new NBTTagList();
			for (String line : lore) {
				list.add(new NBTTagString(line));
			}
			
			CraftMetaItem.setDisplayTag(handle.tag, "Lore", list);
		}
	}
	
	@Override
	public boolean hasName() {
		return handle != null && handle.hasName();
	}
	
	@Override
	public boolean hasLore() {
		if (handle == null || handle.tag == null)
			return false;
		
		return handle.tag.hasKeyOfType("display", 10) && handle.tag.getCompound("display").hasKey("Lore");
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy