Refined Storage

Refined Storage

77M Downloads

[Request] Allow multiple patterns for the same output to co-exist

leviathan13 opened this issue ยท 5 comments

commented

Unless I missed something, it seems that it's not possible to have more then one pattern for producing the same item. Only one pattern will be considered by the internal crafting system and if that pattern doesn't have the required items, crafting won't be possible, even if the alternative patterns do have the requirements. This is somewhat a big obstacle to automation.

E.g.: a vanilla iron ingot can be made from iron nuggets, an iron block or by smelting raw iron. If you make a patter for each way, only one can be crafted by the system, regardless of the available ingredients, and you have no choice on which one to use.

Suggested solution:

When crafting an item with multiple patterns available, the crafting preview window should prompt you to choose the preferred one. For the internal automated crafting system, the patterns could have any kind of priority (even a basic one, like order of the patterns is enough) and the system will use the first craftable pattern.

I saw that this issue was already reported here, but since that thread is two years old and it was talking about another mod, I decided to re-post it since it is a general issue, not a mod-specific one.

commented

I support this idea, as I demonstrated here: #948 (comment)

commented

Starting some brainstorming here as I am looking at this issue. Considering a priority is added to the patterns.

First question I am having: do we want this priority directly into the mod or further in the progression? Should RS have a Pattern without priority and an "Advanced Pattern" which is more expensive to craft but has the priority?

Then regarding the handling of such crafting requests, there are several cases that should be explored:

  1. same output, same input (=> same craft), same priority: distributing the craft to several crafters,
  2. same output, different inputs, different priorities: having "backup" recipes for a given item (if recipe 1 is not enough, then use recipe 2...),
  3. same output, different inputs, same priorities: I couldn't find a use case.

Maybe there are also other cases I didn't think about?

In my opinion, 3. could be either an error or the current behaviour (one pattern is picked arbitrarily). I also believe that while 1. is not implemented in RS, it is always possible to direct a crafter at a chest and use another pipe system with round robin to distribute the crafting (even though it might be complicated sometimes if the input contains different items). So I think 2. (which is also the original example in the issue) would be the most valuable at the moment.

Regarding the implementation, there are also some questions that can be raised, for example:

Let's say we have these recipes:
9 iron nuggets => 1 iron ingot (priority: 0)
1 iron block => 9 iron ingots (priority: 1)

9 iron ingots => 1 iron block (priority: 0)

4 iron ingots, 3 iron blocks => 1 anvil (priority: 0)

Let's say we have 18 iron nuggets, 3 iron blocks and 2 iron ingots.

We request one anvil.

I'll preface this by saying in the current system, depending on which iron ingot recipe is selected, if I understand correctly I believe we either have a successful craft (if the iron nugget recipe is selected), or a recursive error (if the iron block recipe is selected).

So in the new system, let's say we want 1 anvil.
The algorithm (arbitrarily) starts by wanting the 4 iron ingots for the anvil.
The algorithm finds 2 iron ingots in the system and wants to craft 2 iron ingots.
The algorithm crafts the 2 iron ingots from a block, with 7 ingots remaining.
The algorithm now wants the 3 iron blocks for the anvil.
The algorithm finds 2 iron blocks in the system and wants to craft 1 iron block.
The algorithm finds 7 iron ingots and wants to craft 2 iron ingots.
The algorithm does not find any iron block to craft the 2 iron ingots, so it looks at the second recipe;
The algorithm finds 18 iron nuggets in the system.
The algorithm crafts the 2 iron ingots.
The algorithm crafts the iron block.
The algorithm crafts the anvil.

Would this be the behaviour expected here? Or should the algorithm directly optimise the request?

If we want to optimise directly, then maybe an algorithm would look like this:

Reserve all the input items from storage for the patterns with the highest priority for every item in the chain.
Reserve all the input items from storage for the patterns with the second highest priority for every item in the chain.
Reserve all the input items from storage for the patterns with the third highest priority for every item in the chain.
...
Until we have gone through all of the patterns; and only then compute what needs to be crafted.

So this would require a lot of changes to the crafting system (add lists of patterns in the "byOutputs" maps in the crafting manager, add the priority to the patterns, add an ordering to the patterns, update the calculator...), so if this were to be implemented should it be a v7 implementation of the crafting?

All in all, there is also the question of whether this should be added to RS1 or to RS2, given there will be breaking interface and implementation changes?
Being unfamiliar with minecraft modding, I am also wondering which consequence such changes would have when upgrading from a version of RS without them to a version of RS with them. I believe all the existing patterns could be considered with priority 0, but how would this work if there is a crafting task running when the update is being done?

commented

To give a different perspective on how the algorithm could work, without complicating it much, here it is:

Imagining we want to build an anvil and we have the following items:
10 iron nuggets, 4 iron blocks and 2 iron ingots, and 5 magic petals.

Let's consider that we also have the following priorities for the craftings, the lowest the number, the higher the priority, as it tends to follow that rule across multiple mods and real-world applications:

Iron Nuggets:
1 iron ingot => 9 iron nuggets (priority 0)

Iron Ingot:
9 iron nuggets => 1 Iron Ingot (priority 0) (higher priority)
9 magic petals => 1 iron ingot (priority 1) (lower priority)
1 iron Block => 9 iron ingots (priority 2) (lower priority)

Iron Block:
9 iron Ingots => 1 Iron Block (priority 0) (higher priority)

So the logic process would be the following:
1 - reserve the items that are already available (Reserving 2 iron ingots + Reserving 3 iron blocks) (2 iron ingots still missing)
2 - Craft the missing items (2 iron ingots)
3 - check all the recipes for iron ingots
4 - Analyze the recipes, and try the highest priority one (9 nuggets => 1 ingot) (only able to craft 1 out of 2 ingots needed)
5 - Craft using that recipe (+1 ingot)
6 - Reserve 1x Iron Ingot (3 out of 4 iron ingots available) (1 iron ingot missing)

7 - Try the highest priority recipe (9 nuggets => 1 ingot) = Not enough items.
8 - exclude the recipe from the list.

9 - Try the highest priority recipe (9 petals => 1 ingot) = Not enough items.
10 - exclude the recipe from the list.

11 - Try the highest priority recipe (1 block => 9 ingots)
12 - Craft using that recipe (+9 ingots)
13 - Reserve 1x iron ingot (4 out of 4 iron ingots available, 3 out of 3 iron blocks available)
14 - Craft the Anvil!
15 - Anvil is available.

It would end everything with
1 iron nugget, 5 petals, 8 iron ingots, and 1 anvil in the system.

I think this way of crafting while not the most optimized version of it, follows the priority system the user created, and respects it, Using it to craft the item he wanted with what he had available.

I imagine that if someone just didn't add priorities to their multiple ways to craft the same item, the system could simply use the recipes that had the larger amount of leftover items, or that could produce the largest amount of items, etc. Some level of optimization and algorithm would need to be created for this. But that could be something further down the line. Just having the priorities like I mentioned I think would be way easier to implement, as it (I believe) follows some of the logic that RF2 already uses.

commented

Thanks for the reply @skygamer125, I see yeah maybe reserving the items as we hit the pattern is just the best way to go

I also want to mention here that Raoul said on discord that this will not be implemented in RS1. I will still investigate to implement it in RS1 to make it easier to implement in RS2 when autocrafting is tackled but this will not be merged.

One other question that I found is that currently in the implementation a crafting a task has a root pattern, which means that at the highest level, only one pattern can be used (i.e. if I have two patterns to craft iron ingots and I want to craft iron ingots directly, then I can only use one of the two patterns). I am at this moment unsure if this is also the case for the nested patterns, but this already raises the question of whether we want to also use the priority system at the top level, or if we want to let the user choose which pattern they use, or a mix of both (in the UI they could select).

commented

can this be implemented on RS2 then? hmmm I just thought this was the github for RS2 haha, I got it wrong. but yeah I think this would work wonders in RS2