AztechMC / Modern-Industrialization

Modern industrial mod for Minecraft.
https://www.curseforge.com/minecraft/mc-mods/modern-industrialization
MIT License
150 stars 86 forks source link

I/O Pipe inserting into the same inventory it pulled from causes unexpected behavior for inventories with multiple item types #685

Open trunksbomb opened 5 months ago

trunksbomb commented 5 months ago

Minecraft 1.20.1 Fabric 0.14.25 MI: 1.8.3

Long story short, I realized the exact issue as I was writing this. The problem is that an I/O pipe will pull up to 16 items out of the inventory it's attached to and then reinsert those 16 items back into the source inventory if they don't have another destination. In the case where you have two different types of item stack in your source inventory and 16 or more of the first item stack then it will never pull the second type of item in the source inventory. It gets into a loop of pulling 16 of the first, only having the source inventory as a destination, putting them back into the source inventory, and repeating.

This is a problem when:

  1. Your source inventory has 2+ item types in it (like copper and tin dust to mix into bronze dust)
  2. You have 16+ of whatever item type (copper or tin) is first in the source inventory
  3. Your destination accepts those 2+ types (a Mixer) but cannot accept any more of whatever item type happens to be first in the source inventory

In this very specific situation, the I/O pipe constantly pulls 16 of the first item type and reinserts it into the source inventory and never reaches the second item type. This is unexpected because according to the tooltip for Extraction Priority (Lower priorities first, only into higher priorities), an I/O pipe shouldn't even be able to insert back into itself. The problem would be fixed either by preventing I/O pipes from inserting into themselves or by adding special behavior to the I/O pipe that will skip all operations that would extract X items from an inventory and reinsert X items back into the same inventory.

Feel free to read the rest of this, it's the original issue I was going to post that led me to the realization above.


Possibly related to #268

Ran into a quirk in behavior in pipes configured I/O vs OUT. I created a simplified setup to explain the situation. Pictures below text for clarifcation.

Left barrel is my source Right barrel is the destination

I/O pipe connected to left chest IN pipe connected to right chest

Expected behavior: Pipe network fills up both the single stack for bronze plates and the single stack for bricks in the right chest. Actual Behavior: Pipe network only fills up the corresponding slot in the right chest with whatever item happens to be first in the left barrel. As pictured, it filled up the bronze plates because those were first in the left barrel. If I instead swapped those so that the bricks were first in the left barrel, it would have filled up the bricks on the right barrel and not the plates.

image image image image image

Two more interesting quirks I observed while writing this issue:

  1. An inventory with a single I/O pipe connected to it will pull a set of items from the inventory and then reinsert them, but it will only do it if the first occupied slot of the inventory has a full stack of items. image image

  2. The 2 images below are stable - nothing is transferring from the first (left) barrel to the second (right) barrel. (You can also observe the behavior described in the previous two pictures - I inserted a stack of 64 bronze plates and the I/O pipe pulled out 16 and reinserted them into the barrel in the second slot). But specifically the other quirk is that reducing the quantity of bronze plates to below 16 lets the I/O pipe take some of the bricks. If I reduce the quantity of bronze plates to 15, for example, then the I/O pipe will take 15 plates out and 1 brick out in a single operation - inserting the 15 plates back into the barrel from which they came, and inserting the 1 brick into the second barrel. image image

Technici4n commented 5 months ago

This is actually "working as intended" - in some cases it is useful to move items within the same block, e.g. a machine output that gets moved back into an input slot for a different recipe. It is annoying in some cases and useful in other cases.

trunksbomb commented 5 months ago

What's funny is that before I thought of this as unintended behavior, I had already used it as you described - to pull output from a Macerator and insert it right back into the same Macerator with just a single pipe in I/O mode.

The main thing to me is that intuitively it seems like inconsistent behavior, especially based on the tooltip for Extraction Priority. If the tooltip was accurate (only into higher priorities) then an I/O pipe could never insert into itself. I haven't looked at the code, but is it the case that it's actually "same or higher priorities"? In which case, a change in wording of the tooltip would probably be sufficient in clearing that up.

Technici4n commented 5 months ago

What I tried to say with Lower priorities first, only into higher priorities. is that the insert priority of the target must be larger than the extract priority of the source. In other words, there will be no self-loop if the insert priority of the pipe is larger than its extract priority.

trunksbomb commented 5 months ago

Understood. I think there's a typo on your sentence though - there will be no self-loop if the insert priority of the pipe is less than its extract priority.

So my previous comment of "If the tooltip was accurate (only into higher priorities) then an I/O pipe could never insert into itself" is wrong - I was thinking it compared the extract priority to the destination extract priority, not the destination insert priority (which is obvious in hindsight lol). But with that information, the tooltip is still incorrect because it's "lower priorities first, only into equal or higher priorities" currently. I imagine it's just a simple >= vs > (or <= vs < depending on order) in the code.

Tested in-game:

Self inserts with Insert Priority > Extract Priority (as expected) image

Self inserts with Insert Priority == Extract Priority (unexpected?) image

Does not self insert with Insert Priority < Extract Priority (as expected) image

I guess my point now is just that the tooltip isn't fully accurate which could lead to confusion, but maybe I'm the only one that was tripped up by it.