package codechicken.nei.recipe;
import codechicken.nei.ItemStackSet;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.api.API;
import codechicken.nei.api.ItemFilter;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import net.minecraft.client.gui.inventory.GuiBrewingStand;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.init.Items;
import net.minecraft.item.ItemPotion;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.potion.PotionHelper;
import net.minecraftforge.common.brewing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.TreeSet;
public class BrewingRecipeHandler extends TemplateRecipeHandler {
public static class NEIBrewingRecipe {
final PositionedStack input;
final PositionedStack output;
final PositionedStack ingredient;
public NEIBrewingRecipe(AbstractBrewingRecipe<?> recipe) {
input = new PositionedStack(recipe.input, 51, 35);
output = new PositionedStack(recipe.output, 97, 35);
ingredient = new PositionedStack(recipe.ingredient, 74, 6);
}
public NEIBrewingRecipe(ItemStack ingred, int basePotionID, int resultDamage) {
input = new PositionedStack(new ItemStack(Items.potionitem, 1, basePotionID), 51, 35);
output = new PositionedStack(new ItemStack(Items.potionitem, 1, resultDamage), 97, 35);
ingredient = new PositionedStack(ingred, 74, 6);
}
}
public class CachedBrewingRecipe extends CachedRecipe {
final NEIBrewingRecipe recipe;
public CachedBrewingRecipe(NEIBrewingRecipe recipe) {
this.recipe = recipe;
}
public CachedBrewingRecipe(AbstractBrewingRecipe<?> recipe) {
this(new NEIBrewingRecipe(recipe));
}
@Override
public PositionedStack getResult() {
return recipe.output;
}
@Override
public ArrayList<PositionedStack> getIngredients() {
ArrayList<PositionedStack> recipestacks = new ArrayList<PositionedStack>();
recipestacks.add(recipe.ingredient);
recipestacks.add(recipe.input);
return recipestacks;
}
}
public static final ItemStackSet ingredients = new ItemStackSet();
public static final HashSet<NEIBrewingRecipe> apotions = new HashSet<NEIBrewingRecipe>();
@Override
public void loadTransferRects() {
transferRects.add(new RecipeTransferRect(new Rectangle(58, 3, 14, 30), "brewing"));
transferRects.add(new RecipeTransferRect(new Rectangle(92, 3, 14, 30), "brewing"));
transferRects.add(new RecipeTransferRect(new Rectangle(68, 23, 28, 18), "brewing"));
}
@Override
public Class<? extends GuiContainer> getGuiClass() {
return GuiBrewingStand.class;
}
@Override
public String getRecipeName() {
return NEIClientUtils.translate("recipe.brewing");
}
@Override
public void loadCraftingRecipes(String outputId, Object... results) {
if (outputId.equals("brewing") && getClass() == BrewingRecipeHandler.class) {// don't want subclasses getting a hold of this
for (NEIBrewingRecipe recipe : apotions) {
arecipes.add(new CachedBrewingRecipe(recipe));
}
for (IBrewingRecipe recipe : BrewingRecipeRegistry.getRecipes()) {
if (recipe instanceof BrewingRecipe || recipe instanceof BrewingOreRecipe) {
arecipes.add(new CachedBrewingRecipe((AbstractBrewingRecipe<?>) recipe));
}
}
} else {
super.loadCraftingRecipes(outputId, results);
}
}
@Override
public void loadCraftingRecipes(ItemStack result) {
if (result.getItem() == Items.potionitem) {
int damage = result.getItemDamage();
for (NEIBrewingRecipe recipe : apotions) {
if (recipe.output.item.getItemDamage() == damage) {
arecipes.add(new CachedBrewingRecipe(recipe));
}
}
}
for (IBrewingRecipe recipe : BrewingRecipeRegistry.getRecipes()) {
if (recipe instanceof BrewingRecipe || recipe instanceof BrewingOreRecipe) {
if (NEIServerUtils.areStacksSameType(((AbstractBrewingRecipe<?>) recipe).output, result)) {
arecipes.add(new CachedBrewingRecipe((AbstractBrewingRecipe<?>) recipe));
}
}
}
}
@Override
public void loadUsageRecipes(ItemStack ingredient) {
if (ingredient.getItem() == Items.potionitem || ingredients.contains(ingredient)) {
for (NEIBrewingRecipe recipe : apotions) {
if (NEIServerUtils.areStacksSameType(recipe.ingredient.item, ingredient) || NEIServerUtils.areStacksSameType(recipe.input.item, ingredient)) {
arecipes.add(new CachedBrewingRecipe(recipe));
}
}
}
nextRecipe:
for (IBrewingRecipe recipe : BrewingRecipeRegistry.getRecipes()) {
if (recipe instanceof BrewingRecipe || recipe instanceof BrewingOreRecipe) {
AbstractBrewingRecipe<?> arecipe = (AbstractBrewingRecipe<?>) recipe;
if (NEIServerUtils.areStacksSameType(arecipe.input, ingredient)) {
arecipes.add(new CachedBrewingRecipe(arecipe));
} else {
ItemStack[] recipeIngredients = NEIServerUtils.extractRecipeItems(arecipe.ingredient);
for (ItemStack recipeIngredient : recipeIngredients) {
if (NEIServerUtils.areStacksSameType(recipeIngredient, ingredient)) {
arecipes.add(new CachedBrewingRecipe(arecipe));
continue nextRecipe;
}
}
}
}
}
}
@Override
public String getGuiTexture() {
return "textures/gui/container/brewing_stand.png";
}
@Override
public void drawExtras(int recipe) {
drawProgressBar(92, 5, 176, 0, 8, 30, 120, 1);
drawProgressBar(60, 1, 185, -2, 12, 30, 35, 3);
}
public static void searchPotions() {
TreeSet<Integer> allPotions = new TreeSet<Integer>();
HashSet<Integer> searchPotions = new HashSet<Integer>();
searchPotions.add(0);
allPotions.add(0);
do {
HashSet<Integer> newPotions = new HashSet<Integer>();
for (Integer basePotion : searchPotions) {
if (ItemPotion.isSplash(basePotion)) {
continue;
}
for (ItemStack ingred : ingredients.values()) {
int result = PotionHelper.applyIngredient(basePotion, ingred.getItem().getPotionEffect(ingred));
if (ItemPotion.isSplash(result)) {//splash potions qualify
addPotion(ingred, basePotion, result, allPotions, newPotions);
continue;
}
List<?> baseMods = Items.potionitem.getEffects(basePotion);
List<?> newMods = Items.potionitem.getEffects(result);//compare ID's
if (basePotion > 0 && baseMods == newMods || //same modifers and not water->empty
baseMods != null && (baseMods.equals(newMods) || newMods == null) || //modifiers different and doesn't lose modifiers
basePotion == result || //same potion
levelModifierChanged(basePotion, result))//redstone/glowstone cycle
{
continue;
}
addPotion(ingred, basePotion, result, allPotions, newPotions);
}
}
searchPotions = newPotions;
} while (!searchPotions.isEmpty());
API.setItemListEntries(Items.potionitem, Iterables.transform(allPotions, new Function<Integer, ItemStack>()//override with only potions that can be crafted
{
@Override
public ItemStack apply(Integer potionID) {
return new ItemStack(Items.potionitem, 1, potionID);
}
}));
API.addSubset("Items.Potions", new ItemStackSet().with(Items.potionitem));
API.addSubset("Items.Potions.Splash", new ItemFilter() {
@Override
public boolean matches(ItemStack item) {
return item.getItem() == Items.potionitem && (item.getItemDamage() & 0x4000) != 0;
}
});
ItemStackSet positivepots = new ItemStackSet();
ItemStackSet negativepots = new ItemStackSet();
ItemStackSet neutralpots = new ItemStackSet();
for (int potionID : allPotions) {
List<PotionEffect> effectlist = Items.potionitem.getEffects(potionID);
int type = 0;
if (effectlist != null && !effectlist.isEmpty()) {
for (PotionEffect potioneffect : effectlist) {
if (Potion.potionTypes[potioneffect.getPotionID()].isBadEffect()) {
type--;
} else {
type++;
}
}
}
(type == 0 ? neutralpots : type > 0 ? positivepots : negativepots).add(new ItemStack(Items.potionitem, 1, potionID));
}
API.addSubset("Items.Potions.Positive", positivepots);
API.addSubset("Items.Potions.Negative", negativepots);
API.addSubset("Items.Potions.Neutral", neutralpots);
}
private static boolean levelModifierChanged(int basePotionID, int result) {
int basemod = basePotionID & 0xE0;
int resultmod = result & 0xE0;
return basemod != 0 && basemod != resultmod;
}
private static void addPotion(ItemStack ingred, int basePotion, int result, TreeSet<Integer> allPotions, HashSet<Integer> newPotions) {
apotions.add(new NEIBrewingRecipe(ingred, basePotion, result));
if (allPotions.add(result))//it's new
{
newPotions.add(result);
}
}
@Override
public String getOverlayIdentifier() {
return "brewing";
}
}