package joshie.harvest.core.helpers;
import joshie.harvest.tools.ToolHelper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.*;
import net.minecraft.util.EnumHand;
import net.minecraftforge.oredict.OreDictionary;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import static joshie.harvest.core.helpers.InventoryHelper.SearchType.*;
public class InventoryHelper {
public enum SearchType {
FLOWER, HOE, BUCKET, SHEARS, WOOL, PICKAXE
}
public static final Matcher<String> ORE_DICTIONARY = new Matcher<String>() {
@Override
public boolean matches(@Nonnull ItemStack stack, String string) {
return InventoryHelper.isOreName(stack, string);
}
};
public static final Matcher<ItemStack> ITEM_STACK = new Matcher<ItemStack>() {
@Override
public boolean matches(@Nonnull ItemStack stack, ItemStack stack2) {
return stack.isItemEqual(stack2);
}
};
public static final Matcher<Item> ITEM = new Matcher<Item>() {
@Override
public boolean matches(@Nonnull ItemStack stack, Item item) {
return stack.getItem() == item;
}
};
public static final Matcher<SearchType> SPECIAL = new Matcher<SearchType>() {
@Override
public boolean matches(@Nonnull ItemStack stack, SearchType type) {
if (type.equals(FLOWER)) {
if(stack.getItem() == Item.getItemFromBlock(Blocks.RED_FLOWER) || stack.getItem() == Item.getItemFromBlock(Blocks.YELLOW_FLOWER)) return true;
else {
for (String name: getOreNames(stack)) {
if (name.startsWith("flower")) return true;
}
return false;
}
} else if (type.equals(HOE)) {
return stack.getItem() instanceof ItemHoe;
} else if (type.equals(BUCKET)) {
return stack.getItem() instanceof ItemBucket;
} else if (type.equals(SHEARS)) {
return stack.getItem() instanceof ItemShears;
} else if (type.equals(WOOL)) {
return ToolHelper.isWool(stack);
} else if (type.equals(PICKAXE)) {
return stack.getItem() instanceof ItemPickaxe;
}
return false;
}
};
private static <T> void takeItems(EntityPlayer player, T taking, int amount, Matcher<T> matcher) {
int toTake = amount;
ItemStack offhand = player.inventory.offHandInventory[0];
if (offhand != null && matcher.matches(offhand, taking)) {
ItemStack taken = offhand.splitStack(toTake);
toTake -= taken.stackSize;
if (offhand.stackSize <= 0) player.inventory.offHandInventory[0] = null; //Clear
if (toTake <= 0) return; //No further processing neccessary
}
//Main Inventory
for (int i = 0; i < player.inventory.mainInventory.length && toTake > 0; i++) {
ItemStack stack = player.inventory.mainInventory[i];
if (stack != null && matcher.matches(stack, taking)) {
ItemStack taken = stack.splitStack(toTake);
toTake -= taken.stackSize;
if (stack.stackSize <= 0) player.inventory.mainInventory[i] = null; //Clear
if (toTake <= 0) return; //No further processing neccessary
}
}
}
@SuppressWarnings("unchecked")
public static <S> boolean hasInInventory(EntityPlayer player, Matcher matcher, S search, int... amount) {
int count = amount == null || amount.length == 0 ? 1 : amount[0];
return getCount(player, search, matcher) >= count;
}
@SuppressWarnings("unchecked")
public static <S> boolean takeItemsInInventory(EntityPlayer player, Matcher matcher, S search, int... amount) {
int count = amount == null || amount.length == 0 ? 1 : amount[0];
if (hasInInventory(player, matcher, search, count)) {
takeItems(player, search, count, matcher);
return true;
}
return false;
}
@SuppressWarnings("unchecked")
private static <S> int getStackSizeOfHand(EntityPlayer player, Matcher<S> matcher, S search, EnumHand hand) {
ItemStack held = player.getHeldItem(hand);
if (held != null && matcher.matches(held, search)) {
return held.stackSize;
} else return 0;
}
@SuppressWarnings("unchecked")
public static <S> EnumHand getHandItemIsIn(EntityPlayer player, Matcher<S> matcher, S search, int... amount) {
int count = amount == null || amount.length == 0 ? 1 : amount[0];
for (EnumHand hand: EnumHand.values()) {
if (getStackSizeOfHand(player, matcher, search, hand) != 0) {
if (getCount(player, search, matcher) >= count) {
return hand;
}
}
}
return null;
}
@SuppressWarnings("ConstantConditions")
private static int reduceHeld(EntityPlayer player, EnumHand hand, int amount) {
ItemStack held = player.getHeldItem(hand);
if (held.stackSize <= amount) {
int ret = held.stackSize;
player.setHeldItem(hand, null);
return ret;
} else {
held.stackSize -= amount;
return amount;
}
}
@SuppressWarnings("unchecked")
public static <S> EnumHand takeItemsIfHeld(EntityPlayer player, Matcher matcher, S search, int... amount) {
int count = amount == null || amount.length == 0 ? 1 : amount[0];
EnumHand ret = getHandItemIsIn(player, matcher, search, count);
if (ret != null) {
count -= reduceHeld(player, ret, count); //Update the count
if (count > 0) takeItems(player, search, count, matcher);
return ret;
}
return null;
}
public static <T> int getCount(EntityPlayer player, T taking, Matcher<T> matcher) {
int count = 0;
for (ItemStack item: player.inventory.mainInventory) {
if (item == null) continue;
if (matcher.matches(item, taking)) {
count += item.stackSize;
}
}
ItemStack offhand = player.inventory.offHandInventory[0];
if (offhand != null && matcher.matches(offhand, taking)) {
count += offhand.stackSize;
}
return count;
}
public static boolean isOreName(ItemStack stack, String... ore) {
for (String name: ore) {
if (isOreName(stack, name)) return true;
}
return false;
}
public static boolean isOreName(ItemStack stack, String ore) {
int[] ids = OreDictionary.getOreIDs(stack);
for (int i: ids) {
String name = OreDictionary.getOreName(i);
if (name.equals(ore)) {
return true;
}
}
return false;
}
public static List<ItemStack> getStarts(String ore) {
List<ItemStack> list = new ArrayList<>();
for (String name: OreDictionary.getOreNames()) {
if (name.startsWith(ore)) list.addAll(OreDictionary.getOres(name));
}
return list;
}
public static List<ItemStack> getEnds(String ore) {
List<ItemStack> list = new ArrayList<>();
for (String name: OreDictionary.getOreNames()) {
if (name.endsWith(ore)) list.addAll(OreDictionary.getOres(name));
}
return list;
}
public static List<ItemStack> getContains(String ore) {
List<ItemStack> list = new ArrayList<>();
for (String name: OreDictionary.getOreNames()) {
if (name.contains(ore)) list.addAll(OreDictionary.getOres(name));
}
return list;
}
public static boolean startsWith(ItemStack stack, String... ore) {
for (String name: ore) {
if (startsWith(stack, name)) return true;
}
return false;
}
public static boolean endsWith(ItemStack stack, String ore) {
int[] ids = OreDictionary.getOreIDs(stack);
for (int i: ids) {
String name = OreDictionary.getOreName(i);
if (name.endsWith(ore)) {
return true;
}
}
return false;
}
public static boolean contains(ItemStack stack, String ore) {
int[] ids = OreDictionary.getOreIDs(stack);
for (int i: ids) {
String name = OreDictionary.getOreName(i);
if (name.contains(ore)) {
return true;
}
}
return false;
}
public static boolean startsWith(ItemStack stack, String ore) {
int[] ids = OreDictionary.getOreIDs(stack);
for (int i: ids) {
String name = OreDictionary.getOreName(i);
if (name.startsWith(ore)) {
return true;
}
}
return false;
}
public static String[] getOreNames(ItemStack stack) {
int[] ids = OreDictionary.getOreIDs(stack);
String[] names = new String[ids.length];
for (int i = 0; i < ids.length; i++) {
names[i] = OreDictionary.getOreName(ids[i]);
}
return names;
}
public abstract static class Matcher<T> {
public abstract boolean matches(@Nonnull ItemStack stack, T t);
@SafeVarargs
public final boolean matchesAny(@Nullable ItemStack stack, T... t) {
if (stack == null) return false;
for (T value: t) {
if (matches(stack, value)) return true;
}
return false;
}
}
}