diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPattern.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPattern.java index 395b58783..4aedd17e8 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPattern.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPattern.java @@ -39,6 +39,11 @@ public interface ICraftingPattern { */ List getInputs(); + /** + * @return the possible inputs per slot, empty list means null slot + */ + List> getOreInputs(); + /** * @param took the items took * @return the outputs based on the items took diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingPattern.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingPattern.java index 5eb0b3456..e7043c1af 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingPattern.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingPattern.java @@ -12,21 +12,21 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; import net.minecraft.world.World; +import net.minecraftforge.oredict.ShapedOreRecipe; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.lang.reflect.InvocationTargetException; +import java.util.*; public class CraftingPattern implements ICraftingPattern { - private World world; private ICraftingPatternContainer container; private ItemStack stack; + private IRecipe recipe; private List inputs = new ArrayList<>(); + private List> oreInputs = new ArrayList<>(); private List outputs = new ArrayList<>(); private List byproducts = new ArrayList<>(); public CraftingPattern(World world, ICraftingPatternContainer container, ItemStack stack) { - this.world = world; this.container = container; this.stack = stack; @@ -44,14 +44,52 @@ public class CraftingPattern implements ICraftingPattern { } if (!ItemPattern.isProcessing(stack)) { - ItemStack output = CraftingManager.getInstance().findMatchingRecipe(inv, world); + recipe = CraftingManager.getInstance().getRecipeList().stream().filter(r -> r.matches(inv, world)).findFirst().orElse(null); + if (recipe != null) { + ItemStack output = recipe.getCraftingResult(inv); + if (output != null) { + outputs.add(output.copy()); - if (output != null) { - outputs.add(output.copy()); + boolean shapedOre = recipe instanceof ShapedOreRecipe; + // It is a dirty fix, but hey someone has to do it. ~ way2muchnoise 2016 "bite me" + if (shapedOre || recipe.getClass().getName().equals("mekanism.common.recipe.ShapedMekanismRecipe")) { + Object[] inputs = new Object[0]; + if (shapedOre) { + inputs = ((ShapedOreRecipe) recipe).getInput(); + } + else { + try { + inputs = (Object[]) recipe.getClass().getMethod("getInput").invoke(recipe); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + e.printStackTrace(); + } + } + for (Object input : inputs) { + if (input == null) { + oreInputs.add(Collections.emptyList()); + } + if (input instanceof ItemStack) { + oreInputs.add(Collections.singletonList((ItemStack) input)); + } else { + oreInputs.add((List)input); + } + } + } - for (ItemStack remaining : CraftingManager.getInstance().getRemainingItems(inv, world)) { - if (remaining != null) { - byproducts.add(remaining.copy()); + if (oreInputs.isEmpty()) { + for (ItemStack input : inputs) { + if (input == null) { + oreInputs.add(Collections.emptyList()); + } else { + oreInputs.add(Collections.singletonList(input)); + } + } + } + + for (ItemStack remaining : recipe.getRemainingItems(inv)) { + if (remaining != null) { + byproducts.add(remaining.copy()); + } } } } @@ -90,6 +128,11 @@ public class CraftingPattern implements ICraftingPattern { return inputs; } + @Override + public List> getOreInputs() { + return oreInputs; + } + @Override public List getOutputs(ItemStack[] took) { List outputs = new ArrayList<>(); @@ -105,7 +148,7 @@ public class CraftingPattern implements ICraftingPattern { inv.setInventorySlotContents(i, took[i]); } - outputs.add(CraftingManager.getInstance().findMatchingRecipe(inv, world)); + outputs.add(recipe.getCraftingResult(inv)); return outputs; } @@ -130,7 +173,7 @@ public class CraftingPattern implements ICraftingPattern { inv.setInventorySlotContents(i, took[i]); } - for (ItemStack remaining : CraftingManager.getInstance().getRemainingItems(inv, world)) { + for (ItemStack remaining : recipe.getRemainingItems(inv)) { if (remaining != null) { byproducts.add(remaining.copy()); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingStepCraft.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingStepCraft.java index 2617ab706..ff6d557c2 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingStepCraft.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingStepCraft.java @@ -9,26 +9,46 @@ import com.raoulvdberge.refinedstorage.api.util.IItemStackList; import com.raoulvdberge.refinedstorage.apiimpl.API; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.ItemHandlerHelper; -import java.util.Deque; +import java.util.*; +import java.util.stream.Collectors; public class CraftingStepCraft extends CraftingStep { public static final String ID = "craft"; + private static final String NBT_TO_INSERT = "ToInsert"; - public CraftingStepCraft(INetworkMaster network, ICraftingPattern pattern) { + private List toInsert; + + public CraftingStepCraft(INetworkMaster network, ICraftingPattern pattern, List toInsert) { super(network, pattern); + this.toInsert = new LinkedList<>(); + toInsert.stream().filter(insert -> insert != null).forEach(stack -> this.toInsert.add(stack.copy())); } public CraftingStepCraft(INetworkMaster network) { super(network); } + @Override + public List getToInsert() { + return toInsert == null ? super.getToInsert() : toInsert; + } + @Override public boolean canStartProcessing(IItemStackList items, IFluidStackList fluids) { - int compare = IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0); + int compare = CraftingTask.DEFAULT_COMPARE | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0); for (ItemStack stack : getToInsert()) { + // This will be a tool, like a hammer + if (stack.isItemStackDamageable()) { + compare &= ~IComparer.COMPARE_DAMAGE; + } else { + compare |= IComparer.COMPARE_DAMAGE; + } + ItemStack actualStack = items.get(stack, compare); if (actualStack == null || actualStack.stackSize == 0 || !items.trackedRemove(actualStack, stack.stackSize, true)) { @@ -101,6 +121,36 @@ public class CraftingStepCraft extends CraftingStep { @Override public NBTTagCompound writeToNBT(NBTTagCompound tag) { tag.setString(NBT_CRAFTING_STEP_TYPE, ID); - return super.writeToNBT(tag); + super.writeToNBT(tag); + + NBTTagList toInsertList = new NBTTagList(); + + for (ItemStack insert : toInsert) { + toInsertList.appendTag(insert.serializeNBT()); + } + + tag.setTag(NBT_TO_INSERT, toInsertList); + + return tag; + } + + @Override + public boolean readFromNBT(NBTTagCompound tag) { + if (super.readFromNBT(tag)) { + if (tag.hasKey(NBT_TO_INSERT)) { + NBTTagList toInsertList = tag.getTagList(CraftingTask.NBT_TO_INSERT_ITEMS, Constants.NBT.TAG_COMPOUND); + toInsert = new ArrayList<>(toInsertList.tagCount()); + for (int i = 0; i < toInsertList.tagCount(); ++i) { + ItemStack insertStack = ItemStack.loadItemStackFromNBT(toInsertList.getCompoundTagAt(i)); + if (insertStack != null) { + toInsert.add(insertStack); + } + } + } + + return true; + } + + return false; } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java index 665cc6f78..f8b5c8ea3 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java @@ -99,14 +99,37 @@ public class CraftingTask implements ICraftingTask { IItemStackList inputs = API.instance().createItemStackList(); IItemStackList actualInputs = API.instance().createItemStackList(); + List usedStacks = new LinkedList<>(); - for (ItemStack input : pattern.getInputs()) { - if (input != null) { - inputs.add(input.copy()); + for (List oreInputs : pattern.getOreInputs()) { + boolean added = false; + for (ItemStack input : oreInputs) { + int oreCompare = IComparer.COMPARE_NBT | (input.isItemStackDamageable() ? 0 : IComparer.COMPARE_DAMAGE); + if (network.getItemStorageCache().getList().get(input, oreCompare) != null) { + usedStacks.add(input.copy()); + inputs.add(input.copy()); + added = true; + break; + } + } + if (!added) { + ItemStack choice = null; + if (!oreInputs.isEmpty()) { + choice = oreInputs.get(0); + inputs.add(choice); + } + usedStacks.add(choice); } } for (ItemStack input : inputs.getStacks()) { + // This will be a tool, like a hammer + if (input.isItemStackDamageable()) { + compare &= ~IComparer.COMPARE_DAMAGE; + } else { + compare |= IComparer.COMPARE_DAMAGE; + } + ItemStack extraStack = toInsert.get(input, compare); ItemStack networkStack = networkList.get(input, compare); @@ -163,14 +186,14 @@ public class CraftingTask implements ICraftingTask { if (pattern.isProcessing()) { steps.add(new CraftingStepProcess(network, pattern)); } else { - steps.add(new CraftingStepCraft(network, pattern)); + steps.add(new CraftingStepCraft(network, pattern, usedStacks)); } if (missing.isEmpty()) { ItemStack[] took = new ItemStack[9]; if (!pattern.isProcessing()) { - for (int i = 0; i < pattern.getInputs().size(); i++) { - ItemStack input = pattern.getInputs().get(i); + for (int i = 0; i < usedStacks.size(); i++) { + ItemStack input = usedStacks.get(i); if (input != null) { ItemStack actualInput = actualInputs.get(input, compare); ItemStack taken = ItemHandlerHelper.copyStackWithSize(actualInput, input.stackSize);