package de.take_weiland.mods.commons.util; import com.google.common.base.Objects; import cpw.mods.fml.common.registry.GameRegistry; import de.take_weiland.mods.commons.meta.HasSubtypes; import de.take_weiland.mods.commons.meta.MetadataProperty; import de.take_weiland.mods.commons.meta.Subtype; import de.take_weiland.mods.commons.nbt.NBT; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import org.jetbrains.annotations.Contract; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; /** * <p>Utilities for ItemStacks.</p> * * @see net.minecraft.item.ItemStack */ @ParametersAreNonnullByDefault public final class ItemStacks { public static ItemStack clone(@Nullable ItemStack stack) { return stack == null ? null : stack.copy(); } /** * <p>Tests if the first ItemStack can be fully merged into the second one.</p> * * @param from the ItemStack to merge, may be null * @param into the ItemStack to merge into, may be null * @return true if the first ItemStack can be fully merged into the second one */ public static boolean fitsInto(@Nullable ItemStack from, @Nullable ItemStack into) { return from == null || into == null || fitsIntoImpl(from, into); } private static boolean fitsIntoImpl(ItemStack from, ItemStack into) { return equalsImpl(from, into) && from.stackSize + into.stackSize <= into.getMaxStackSize(); } /** * <p>Determine if the given ItemStacks are equal.</p> * <p>This method checks the ItemID, damage value and NBT data of the stack, it does not check stack sizes.</p> * * @param a an ItemStack * @param b an ItemStack * @return true if the ItemStack are equal */ @Contract("null, null -> true; null, !null -> false; !null, null -> false") public static boolean equal(@Nullable ItemStack a, @Nullable ItemStack b) { return a == b || (a != null && b != null && equalsImpl(a, b)); } private static boolean equalsImpl(ItemStack a, ItemStack b) { return a.itemID == b.itemID && a.getItemDamage() == b.getItemDamage() && Objects.equal(a.stackTagCompound, b.stackTagCompound); } @Contract("null, null -> true; null, !null -> false; !null, null -> false") public static boolean identical(@Nullable ItemStack a, @Nullable ItemStack b) { return a == b || (a != null && b != null && equalsImpl(a, b) && a.stackSize == b.stackSize); } public static int hash(@Nullable ItemStack stack) { if (stack == null) { return 0; } else { int result = stack.itemID | (stack.getItemDamage() << 16); result = 31 * result + stack.stackSize; result = 31 * result + (stack.stackTagCompound != null ? stack.stackTagCompound.hashCode() : 0); return result; } } public static ItemStack merge(@Nullable ItemStack from, @Nullable ItemStack into) { return merge(from, into, false); } public static ItemStack merge(@Nullable ItemStack from, @Nullable ItemStack into, boolean force) { if (from == null) { return into; } if (into == null) { ItemStack result = from.copy(); from.stackSize = 0; return result; } if (force || equalsImpl(from, into)) { int transferCount = Math.min(into.getMaxStackSize() - into.stackSize, from.stackSize); from.stackSize -= transferCount; into.stackSize += transferCount; } return into; } public static Block getBlock(ItemStack stack) { return Block.blocksList[stack.itemID]; } @Contract("null -> null") public static ItemStack emptyToNull(@Nullable ItemStack stack) { return stack == null || stack.stackSize <= 0 ? null : stack; } public static NBTTagCompound getNbt(ItemStack stack) { if (stack.stackTagCompound == null) { stack.stackTagCompound = new NBTTagCompound(); } return stack.stackTagCompound; } public static NBTTagCompound getNbt(ItemStack stack, String key) { return NBT.getOrCreateCompound(getNbt(stack), key); } public static boolean is(@Nullable ItemStack stack, Item item) { return stack != null && stack.itemID == item.itemID; } public static boolean is(@Nullable ItemStack stack, Item item, int meta) { return stack != null && stack.itemID == item.itemID && stack.getItemDamage() == meta; } public static boolean is(@Nullable ItemStack stack, Block block) { return stack != null && stack.itemID == block.blockID; } public static boolean is(@Nullable ItemStack stack, Block block, int meta) { return stack != null && stack.itemID == block.blockID && stack.getItemDamage() == meta; } @SuppressWarnings("unchecked") static <T extends Enum<T> & Subtype> void registerSubstacks(String baseName, Item item) { MetadataProperty<T> prop = ((HasSubtypes<T>) item).subtypeProperty(); for (T type : prop.values()) { ItemStack stack = new ItemStack(item); stack.setItemDamage(prop.toMeta(type, 0)); String name = baseName + "." + type.subtypeName(); GameRegistry.registerCustomItemStack(name, stack); } } private ItemStacks() { } }