diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingStep.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingStep.java index 7b7bbc5f3..bdf1b9165 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingStep.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingStep.java @@ -66,11 +66,17 @@ public interface ICraftingStep { boolean hasReceivedOutputs(); /** - * @param stack the output to check, + * @param stack the output to check * @return true if we received the given output (based upon item and stacksize), false otherwise */ boolean hasReceivedOutput(ItemStack stack); + /** + * @param stack the output to check + * @return amount of times this {@link ItemStack} has been received + */ + int getReceivedOutput(ItemStack stack); + /** * The {@link ItemStack} given to it will be changed and contain the remainder * The return value will only be true if the stack size is zero diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingTask.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingTask.java index ad2a115e1..22f44d40b 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingTask.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingTask.java @@ -40,6 +40,16 @@ public interface ICraftingTask { */ boolean update(Map usedContainers); + /** + * Reschedule the task. This does a recalculation and restart of the task. + */ + void reschedule(); + + /** + * Clear out missing items. Tasks will run all possible tasks, before reporting missing items again. + */ + void clearMissing(); + /** * @return the amount of items that have to be crafted */ diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetworkMaster.java b/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetworkMaster.java index 7739d34bc..ad064df1e 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetworkMaster.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetworkMaster.java @@ -184,10 +184,8 @@ public interface INetworkMaster { ICraftingTask task = createCraftingTask(stack, pattern, 1); task.calculate(); - - if (!task.hasMissing()) { - addCraftingTask(task); - } + task.clearMissing(); + addCraftingTask(task); } } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingStep.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingStep.java index 684dd683e..cbf363c2a 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingStep.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingStep.java @@ -112,6 +112,12 @@ public abstract class CraftingStep implements ICraftingStep { return received != null && received >= stack.stackSize; } + @Override + public int getReceivedOutput(ItemStack stack) { + Integer received = satisfied.get(API.instance().getItemStackHashCode(stack)); + return received == null ? 0 : received; + } + @Override public boolean onReceiveOutput(ItemStack stack) { for (ItemStack output : pattern.getOutputs()) { 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 429285de1..348016913 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 @@ -240,6 +240,21 @@ public class CraftingTask implements ICraftingTask { @Override public boolean update(Map usedContainers) { + IItemStackList oreDictPrepped = network.getItemStorageCache().getList().prepOreDict(); + + if (hasMissing()) { + for (ItemStack missing : this.missing.getStacks()) { + if (!oreDictPrepped.trackedRemove(missing, true)) { + oreDictPrepped.undo(); + return false; + } + } + oreDictPrepped.undo(); + reschedule(); + return false; + } + + for (FluidStack stack : toTakeFluids.getStacks()) { FluidStack stackExtracted = network.extractFluid(stack, stack.amount); if (stackExtracted != null) { @@ -251,8 +266,6 @@ public class CraftingTask implements ICraftingTask { toTakeFluids.clean(); - IItemStackList oreDictPrepped = network.getItemStorageCache().getList().prepOreDict(); - for (ICraftingStep step : steps) { ICraftingPatternContainer container = step.getPattern().getContainer(); Integer timesUsed = usedContainers.get(container); @@ -284,11 +297,39 @@ public class CraftingTask implements ICraftingTask { } } + if (steps.stream().filter(ICraftingStep::hasStartedProcessing).count() == 0) { + // When there is no started processes, restart the task. + reschedule(); + } + + // Remove finished tasks steps.removeIf(ICraftingStep::hasReceivedOutputs); return isFinished(); } + @Override + public void reschedule() { + List mainSteps = steps.stream().filter(s -> s.getPattern() == pattern).collect(Collectors.toList()); + missing.clear(); + steps.clear(); + // if the list of main steps is empty there is no point in rescheduling + if (!mainSteps.isEmpty()) { + quantity = 0; + int quantityPerRequest = pattern.getQuantityPerRequest(requested); + for (ICraftingStep step : mainSteps) { + quantity += quantityPerRequest - step.getReceivedOutput(requested); + } + calculate(); + network.sendCraftingMonitorUpdate(); + } + } + + @Override + public void clearMissing() { + missing.clear(); + } + @Override public int getQuantity() { return quantity; @@ -346,6 +387,21 @@ public class CraftingTask implements ICraftingTask { 0 )); + if (!missing.isEmpty()) { + elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_missing", 16)); + + missing.getStacks().stream() + .map(stack -> new CraftingMonitorElementError(new CraftingMonitorElementItemRender( + -1, + stack, + stack.stackSize, + 32 + ), "")) + .forEach(elements::add); + + elements.commit(); + } + if (!toInsertItems.isEmpty()) { elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_inserting", 16)); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/ItemGridHandler.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/ItemGridHandler.java index 5713d3aba..9f9397328 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/ItemGridHandler.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/ItemGridHandler.java @@ -145,12 +145,9 @@ public class ItemGridHandler implements IItemGridHandler { if (stack != null) { ICraftingTask task = new CraftingTask(network, stack, network.getPattern(stack), quantity); - task.calculate(); - - if (!task.hasMissing()) { - network.addCraftingTask(task); - } + task.clearMissing(); + network.addCraftingTask(task); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingMonitor.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingMonitor.java index 263312aa8..a0d71c4c5 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingMonitor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingMonitor.java @@ -132,7 +132,7 @@ public class GuiCraftingMonitor extends GuiBase { item++; } - if (itemSelectedTooltip != null) { + if (itemSelectedTooltip != null && !itemSelectedTooltip.isEmpty()) { drawTooltip(mouseX, mouseY, I18n.format(itemSelectedTooltip)); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingPreview.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingPreview.java index f60fef309..addb6de34 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingPreview.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingPreview.java @@ -78,6 +78,10 @@ public class GuiCraftingPreview extends GuiBase { public void update(int x, int y) { scrollbar.setEnabled(getRows() > VISIBLE_ROWS); scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS); + + if (!startButton.enabled && isCtrlKeyDown() && isShiftKeyDown()) { + startButton.enabled = true; + } } @Override @@ -146,6 +150,10 @@ public class GuiCraftingPreview extends GuiBase { } else if (hoveringFluid != null) { drawTooltip(mouseX, mouseY, hoveringFluid.getLocalizedName()); } + + if (!startButton.enabled && inBounds(85, 144, 50, 20, mouseX, mouseY)) { + drawTooltip(mouseX, mouseY, t("gui.refinedstorage:crafting_preview.force_start")); + } } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/integration/jei/RecipeTransferHandlerPattern.java b/src/main/java/com/raoulvdberge/refinedstorage/integration/jei/RecipeTransferHandlerPattern.java index 29faf6daf..a0884db84 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/integration/jei/RecipeTransferHandlerPattern.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/integration/jei/RecipeTransferHandlerPattern.java @@ -13,6 +13,7 @@ import net.minecraft.item.ItemStack; import javax.annotation.Nullable; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; public class RecipeTransferHandlerPattern implements IRecipeTransferHandler { @@ -30,8 +31,8 @@ public class RecipeTransferHandlerPattern implements IRecipeTransferHandler inputs = new HashMap<>(); - Map outputs = new HashMap<>(); + Map inputs = new LinkedHashMap<>(); + Map outputs = new LinkedHashMap<>(); for (IGuiIngredient guiIngredient : recipeLayout.getItemStacks().getGuiIngredients().values()) { if (guiIngredient != null && guiIngredient.getDisplayedIngredient() != null) { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/TileController.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/TileController.java index 200cb8f3b..d309d5050 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/TileController.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/TileController.java @@ -275,6 +275,8 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR craftingTaskIterator.remove(); craftingTasksChanged = true; + } else if(task.hasMissing() && ticks % 100 == 0 && Math.random() > 0.5) { + task.clearMissing(); } } diff --git a/src/main/resources/assets/refinedstorage/lang/en_US.lang b/src/main/resources/assets/refinedstorage/lang/en_US.lang index 72dbcdc27..793ad0fc5 100755 --- a/src/main/resources/assets/refinedstorage/lang/en_US.lang +++ b/src/main/resources/assets/refinedstorage/lang/en_US.lang @@ -24,9 +24,9 @@ gui.refinedstorage:crafting_monitor.fluids_taking=Fluids taking gui.refinedstorage:crafting_monitor.items_crafting=Items crafting gui.refinedstorage:crafting_monitor.items_processing=Items processing gui.refinedstorage:crafting_monitor.items_inserting=Items inserting +gui.refinedstorage:crafting_monitor.items_missing=Items missing gui.refinedstorage:crafting_monitor.machine_in_use=Machine is in use gui.refinedstorage:crafting_monitor.machine_none=No machine found -gui.refinedstorage:crafting_monitor.waiting_for_items=Waiting for items gui.refinedstorage:wireless_transmitter=Wireless Transmitter gui.refinedstorage:wireless_transmitter.distance=%d blocks gui.refinedstorage:crafter=Crafter @@ -50,6 +50,7 @@ gui.refinedstorage:crafting_preview.available=Available: %d gui.refinedstorage:crafting_preview.missing=Missing: %d gui.refinedstorage:crafting_preview.circular=Circular dependency! gui.refinedstorage:crafting_preview.loop=Loop in processing... +gui.refinedstorage:crafting_preview.force_start=Press ctrl + shift to start anyway. misc.refinedstorage:energy_stored=%d / %d RS misc.refinedstorage:energy_usage=Usage: %d RS/t