package crazypants.enderio.machine.recipe;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.item.ItemStack;
import crazypants.enderio.machine.IMachineRecipe;
import crazypants.enderio.machine.MachineRecipeInput;
public abstract class AbstractMachineRecipe implements IMachineRecipe {
@Override
public int getEnergyRequired(MachineRecipeInput... inputs) {
if(inputs == null || inputs.length <= 0) {
return 0;
}
IRecipe recipe = getRecipeForInputs(inputs);
return recipe == null ? 0 : recipe.getEnergyRequired();
}
public RecipeBonusType getBonusType(MachineRecipeInput... inputs) {
if(inputs == null || inputs.length <= 0) {
return RecipeBonusType.NONE;
}
IRecipe recipe = getRecipeForInputs(inputs);
return recipe == null ? RecipeBonusType.NONE : recipe.getBonusType();
}
public abstract IRecipe getRecipeForInputs(MachineRecipeInput[] inputs);
@Override
public List<MachineRecipeInput> getQuantitiesConsumed(MachineRecipeInput[] inputs) {
IRecipe recipe = getRecipeForInputs(inputs);
List<MachineRecipeInput> result = new ArrayList<MachineRecipeInput>();
//Need to make copies so we can reduce their values as we go
MachineRecipeInput[] availableInputs = new MachineRecipeInput[inputs.length];
int i = 0;
for (MachineRecipeInput available : inputs) {
availableInputs[i] = available.copy();
++i;
}
RecipeInput[] requiredIngredients = new RecipeInput[recipe.getInputs().length];
i = 0;
for (RecipeInput ri : recipe.getInputs()) {
requiredIngredients[i] = ri.copy();
++i;
}
//For each input required by the recipe got through the available machine inputs and consume them
for (RecipeInput required : requiredIngredients) {
for (MachineRecipeInput available : availableInputs) {
if(isValid(available)) {
if(consume(required, available, result)) {
break;
}
}
}
}
return result;
}
protected boolean consume(RecipeInput required, MachineRecipeInput available, List<MachineRecipeInput> consumedInputs) {
if(required.isInput(available.fluid)) {
consumedInputs.add(new MachineRecipeInput(available.slotNumber, required.getFluidInput().copy()));
return true;
}
if(required.isInput(available.item) && (required.getSlotNumber() == -1 || required.getSlotNumber() == available.slotNumber)) {
ItemStack availableStack = available.item;
ItemStack requiredStack = required.getInput();
ItemStack consumedStack = requiredStack.copy();
consumedStack.stackSize = Math.min(requiredStack.stackSize, availableStack.stackSize);
requiredStack.stackSize -= consumedStack.stackSize;
availableStack.stackSize -= consumedStack.stackSize;
consumedInputs.add(new MachineRecipeInput(available.slotNumber, consumedStack));
if(requiredStack.stackSize <= 0) {
//Fully met the requirement
return true;
}
}
return false;
}
protected boolean isValid(MachineRecipeInput input) {
if(input == null) {
return false;
}
if(input.item != null && input.item.stackSize > 0) {
return true;
}
return input.fluid != null && input.fluid.amount > 0;
}
@Override
public float getExperienceForOutput(ItemStack output) {
return 0;
}
@Override
public boolean isRecipe(MachineRecipeInput... inputs) {
if(inputs == null || inputs.length <= 0) {
return false;
}
IRecipe recipe = getRecipeForInputs(inputs);
return recipe != null;
}
@Override
public ResultStack[] getCompletedResult(float chance, MachineRecipeInput... inputs) {
if(inputs == null || inputs.length <= 0) {
return new ResultStack[0];
}
IRecipe recipe = getRecipeForInputs(inputs);
if(recipe == null) {
return new ResultStack[0];
}
RecipeOutput[] outputs = recipe.getOutputs();
if(outputs == null) {
return new ResultStack[0];
}
List<ResultStack> result = new ArrayList<ResultStack>();
for (RecipeOutput output : outputs) {
if(output.getChance() >= chance) {
if(output.isFluid()) {
result.add(new ResultStack(output.getFluidOutput().copy()));
} else {
result.add(new ResultStack(output.getOutput().copy()));
}
}
}
return result.toArray(new ResultStack[result.size()]);
}
}