package blusunrize.immersiveengineering.common.crafting;
import blusunrize.immersiveengineering.api.ApiUtils;
import blusunrize.immersiveengineering.api.crafting.IngredientStack;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.oredict.ShapedOreRecipe;
public class RecipeShapedIngredient extends ShapedOreRecipe
{
static IngredientStack[] tempIngredients;
IngredientStack[] ingredients;
IngredientStack[] ingredientsQuarterTurn;
IngredientStack[] ingredientsEighthTurn;
int nbtCopyTargetSlot = -1;
int lastMatch = 0;
public RecipeShapedIngredient(ItemStack result, Object... recipe)
{
super(result, saveIngredients(recipe));
setIngredients(tempIngredients);
tempIngredients = null;
}
public RecipeShapedIngredient setIngredients(IngredientStack[] ingr)
{
ingredients = ingr;
for(int i=0; i<input.length; i++)
if(ingredients[i]!=null)
input[i] = ingredients[i].getShapedRecipeInput();
return this;
}
public IngredientStack[] getIngredients()
{
return ingredients;
}
public RecipeShapedIngredient allowQuarterTurn()
{
ingredientsQuarterTurn = new IngredientStack[ingredients.length];
int maxH = (height - 1);
for(int h = 0; h < height; h++)
for(int w = 0; w < width; w++)
ingredientsQuarterTurn[w * height + (maxH - h)] = ingredients[h * width + w];
return this;
}
static int[] eighthTurnMap = {3, -1, -1, 3, 0, -3, 1, 1, -3};
public RecipeShapedIngredient allowEighthTurn()
{
if(width != 3 || height != 3)//Recipe won't allow 8th turn when not a 3x3 square
return this;
ingredientsEighthTurn = new IngredientStack[ingredients.length];
int maxH = (height - 1);
for(int h = 0; h < height; h++)
for(int w = 0; w < width; w++)
{
int i = h * width + w;
ingredientsEighthTurn[i + eighthTurnMap[i]] = ingredients[i];
}
return this;
}
public RecipeShapedIngredient setNBTCopyTargetRecipe(int slot)
{
this.nbtCopyTargetSlot = slot;
return this;
}
public static Object[] saveIngredients(Object... recipe)
{
Object[] converted = new Object[recipe.length];
String shape = "";
boolean shapeDone = false;
for(int i=0; i<converted.length; i++)
{
converted[i] = recipe[i];
if(!shapeDone)
if(recipe[i] instanceof String[])
{
String[] parts = ((String[])recipe[i]);
for(String s : parts)
shape += s;
}
else if(recipe[i] instanceof String)
shape += (String)recipe[i];
if(recipe[i] instanceof Character)
{
if(!shapeDone)
{
shapeDone = true;
tempIngredients = new IngredientStack[shape.length()];
}
Character chr = (Character)recipe[i];
Object in = recipe[i+1];
IngredientStack ingredient = ApiUtils.createIngredientStack(in);
if(ingredient!=null)
{
recipe[i+1] = Blocks.FIRE;//Temp Replacement, fixed in constructor
for(int j=0; j<shape.length(); j++)
if(chr.charValue()==shape.charAt(j))
tempIngredients[j] = ingredient;
}
}
}
return converted;
}
@Override
public ItemStack getCraftingResult(InventoryCrafting matrix)
{
if(nbtCopyTargetSlot >= 0)
{
ItemStack out = output.copy();
if(matrix.getStackInSlot(nbtCopyTargetSlot) != null && matrix.getStackInSlot(nbtCopyTargetSlot).hasTagCompound())
out.setTagCompound(matrix.getStackInSlot(nbtCopyTargetSlot).getTagCompound().copy());
return out;
}
else
return super.getCraftingResult(matrix);
}
@Override
public ItemStack[] getRemainingItems(InventoryCrafting inv) //getRecipeLeftovers
{
ItemStack[] remains = ForgeHooks.defaultRecipeGetRemainingItems(inv);
// Commented out, apparently fluids handle this reasonably well themselves .-.
// for(int i = 0; i < height*width; i++)
// {
// ItemStack s = inv.getStackInSlot(i);
// IngredientStack[] matchedIngr = lastMatch==1?ingredientsQuarterTurn: lastMatch==2?ingredientsEighthTurn: ingredients;
// if((remains[i]!=null || s!=null) && matchedIngr[i]!=null && matchedIngr[i].fluid!=null)
// {
// if(remains[i]==null && s!=null)
// remains[i] = s.copy();
// IFluidHandler handler = FluidUtil.getFluidHandler(remains[i]);
// if(handler!=null)
// handler.drain(matchedIngr[i].fluid.amount, true);
// if(remains[i].stackSize<=0)
// remains[i] = null;
// }
// }
return remains;
}
@Override
protected boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirror)
{
if(checkMatchDo(inv, ingredients, startX, startY, mirror, false))
{
lastMatch = 0;
return true;
}
else if(ingredientsQuarterTurn != null && checkMatchDo(inv, ingredientsQuarterTurn, startX, startY, mirror, true))
{
lastMatch = 1;
return true;
}
else if(ingredientsEighthTurn != null && checkMatchDo(inv, ingredientsEighthTurn, startX, startY, mirror, false))
{
lastMatch = 2;
return true;
}
return false;
}
protected boolean checkMatchDo(InventoryCrafting inv, IngredientStack[] ingredients, int startX, int startY, boolean mirror, boolean rotate)
{
for(int x = 0; x < MAX_CRAFT_GRID_WIDTH; x++)
for(int y = 0; y < MAX_CRAFT_GRID_HEIGHT; y++)
{
int subX = x - startX;
int subY = y - startY;
IngredientStack target = null;
if(!rotate)
{
if(subX >= 0 && subY >= 0 && subX < width && subY < height)
if(mirror)
target = ingredients[width - subX - 1 + subY * width];
else
target = ingredients[subX + subY * width];
} else
{
if(subX >= 0 && subY >= 0 && subX < height && subY < width)
if(mirror)
target = ingredients[height - subX - 1 + subY * width];
else
target = ingredients[subY + subX * height];
}
ItemStack slot = inv.getStackInRowAndColumn(x, y);
if((target == null) != (slot == null))
return false;
else if(target != null && !target.matchesItemStack(slot))
return false;
}
return true;
}
}