Skip to content

Commit

Permalink
Factory recipe check (#5399)
Browse files Browse the repository at this point in the history
* Fixes null pointer on no recipe found #5392
Compare the recipe against the cache

* Add a few missing secondary input checks

* Don't set the cached recipe when only checking if an item can be inserted
  • Loading branch information
pupnewfster committed Apr 15, 2019
1 parent bc8c4f6 commit f3fdf00
Showing 1 changed file with 75 additions and 15 deletions.
90 changes: 75 additions & 15 deletions src/main/java/mekanism/common/tile/TileEntityFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
import mekanism.common.integration.computer.IComputerIntegration;
import mekanism.common.network.PacketTileEntity.TileEntityMessage;
import mekanism.common.recipe.RecipeHandler;
import mekanism.common.recipe.inputs.AdvancedMachineInput;
import mekanism.common.recipe.inputs.DoubleMachineInput;
import mekanism.common.recipe.inputs.InfusionInput;
import mekanism.common.recipe.inputs.ItemStackInput;
import mekanism.common.recipe.machines.AdvancedMachineRecipe;
import mekanism.common.recipe.machines.BasicMachineRecipe;
import mekanism.common.recipe.machines.ChanceMachineRecipe;
Expand Down Expand Up @@ -411,9 +414,9 @@ public void sortInventory() {
}
//Output/Input will not match
// Only check if the input spot is empty otherwise assume it works
if (stack.isEmpty() && !inputProducesOutput(checkStack, output) ||
checkStack.isEmpty() && !inputProducesOutput(stack,
inventory.get(tier.processes + checkSlotID))) {
if (stack.isEmpty() && !inputProducesOutput(checkSlotID, checkStack, output, true) ||
checkStack.isEmpty() && !inputProducesOutput(slotID, stack,
inventory.get(tier.processes + checkSlotID), true)) {
continue;
}

Expand All @@ -430,20 +433,77 @@ public void sortInventory() {
}
}

private boolean inputProducesOutput(ItemStack input, ItemStack output) {
/**
* Checks if the cached recipe (or recipe for current factory if the cache is out of date) can produce a specific
* output.
*
* @param slotID Slot ID to grab the cached recipe of.
* @param fallbackInput Used if the cached recipe is null or to validate the cached recipe is not out of date.
* @param output The output we want.
* @param updateCache True to make the cached recipe get updated if it is out of date.
* @return True if the recipe produces the given output.
*/
private boolean inputProducesOutput(int slotID, ItemStack fallbackInput, ItemStack output, boolean updateCache) {
if (output.isEmpty()) {
return true;
}
//TODO: At some point it might be worth caching the machine recipe it found,
// but as it only checks when slots are empty it is unlikely to make that large a performance boost
// for the added logic complexity of keeping track of it.
// The case it would help the most is if you have something in the first slot and every other slot is empty
// and nothing is valid for it so it keeps on trying each slot, then caching the recipe and just comparing
// the output to the output would yield even better performance.
MachineRecipe matchingRecipe = getRecipeType()
.getAnyRecipe(input, inventory.get(4), gasTank.getGasType(), infuseStored);
if (matchingRecipe.recipeOutput instanceof ItemStackOutput) {
return ItemStack.areItemsEqual(((ItemStackOutput) matchingRecipe.recipeOutput).output, output);
int process = getOperation(slotID);
//cached recipe may be invalid
MachineRecipe cached = cachedRecipe[process];
ItemStack extra = inventory.get(4);
if (cached == null) {
cached = recipeType
.getAnyRecipe(fallbackInput, extra, gasTank.getGasType(), infuseStored);
if (updateCache) {
cachedRecipe[process] = cached;
}
} else {
ItemStack recipeInput = ItemStack.EMPTY;
boolean secondaryMatch = true;
if (cached.recipeInput instanceof ItemStackInput) {
recipeInput = ((ItemStackInput) cached.recipeInput).ingredient;
} else if (cached.recipeInput instanceof AdvancedMachineInput) {
AdvancedMachineInput advancedInput = (AdvancedMachineInput) cached.recipeInput;
recipeInput = advancedInput.itemStack;
secondaryMatch = gasTank.getGasType() == null || advancedInput.gasType == gasTank.getGasType();
} else if (cached.recipeInput instanceof DoubleMachineInput) {
DoubleMachineInput doubleMachineInput = (DoubleMachineInput) cached.recipeInput;
recipeInput = doubleMachineInput.itemStack;
secondaryMatch = extra.isEmpty() || ItemStack.areItemsEqual(doubleMachineInput.extraStack, extra);
}/*else if (cached.recipeInput instanceof PressurizedInput) {
PressurizedInput pressurizedInput = (PressurizedInput) cached.recipeInput;
recipeInput = pressurizedInput.getSolid();
secondaryMatch = gasTank.getGas() == null || gasTank.getGas().isGasEqual(pressurizedInput.getGas());
//TODO: Handle fluid for secondary matching if we ever have a PRC factory
pressurizedInput.getFluid();
}*/ else if (cached.recipeInput instanceof InfusionInput) {
InfusionInput infusionInput = (InfusionInput) cached.recipeInput;
recipeInput = infusionInput.inputStack;
secondaryMatch = infuseStored.amount == 0 || infuseStored.type == infusionInput.infuse.type;
}
//If there is no cached item input or it doesn't match our fallback
// then it is an out of date cache so we compare against the new one
// and update the cache while we are at it
if (recipeInput.isEmpty() || !secondaryMatch || !ItemStack.areItemsEqual(recipeInput, fallbackInput)) {
cached = cachedRecipe[process] = recipeType
.getAnyRecipe(fallbackInput, extra, gasTank.getGasType(), infuseStored);
if (updateCache) {
cachedRecipe[process] = cached;
}
}
}
//If there is no recipe found
if (cached != null) {
ItemStack recipeOutput = ItemStack.EMPTY;
if (cached.recipeOutput instanceof ItemStackOutput) {
recipeOutput = ((ItemStackOutput) cached.recipeOutput).output;
}/* else if (cached.recipeOutput instanceof PressurizedOutput) {
//TODO: uncomment if we add a PRC factory
recipeOutput = ((PressurizedOutput) cached.recipeOutput).getItemOutput();
}*/
if (!recipeOutput.isEmpty()) {
return ItemStack.areItemsEqual(recipeOutput, output);
}
}
return true;
}
Expand Down Expand Up @@ -516,7 +576,7 @@ public boolean canInsertItem(int slotID, @Nonnull ItemStack itemstack, @Nonnull
if (slotID == 1) {
return ChargeUtils.canBeDischarged(itemstack);
} else if (isInputSlot(slotID)) {
return inputProducesOutput(itemstack, inventory.get(tier.processes + slotID));
return inputProducesOutput(slotID, itemstack, inventory.get(tier.processes + slotID), false);
}
//TODO: Only allow inserting into extra slot if it can go in
return super.canInsertItem(slotID, itemstack, side);
Expand Down

0 comments on commit f3fdf00

Please sign in to comment.