Ender IO Alloy Smelter Eats Items
geoffreak opened this issue ยท 8 comments
Issue Description:
NOTE: This issue was discovered in the Crackpack 3 modpack (reported issue) but likely extends outside the pack. As I do not have the know-how to get a more basic set up for debugging, I am creating this issue with the hope that someone will be able to reproduce the issue if it's not specific to the mod pack.
In certain circumstances that can occur when trying to automate the Ender IO alloy smelter, items will be destroyed. This only seems to happen on items that use the alloy mode of the alloy smelter and only when a single item type is used (e.g. nether quartz to fused quartz or photovoltaic composite to photovoltaic plate).
It seems that the alloy smelter has a logic issue where if there's not enough items to complete the single item recipe in the first slot (or first two?) it will sometimes discard the items in the slots until it finds enough in later slots. This can happen under normal usage for items that take 3x to make something, like the photovoltaic composite, because if you put multiple stacks in, 3 won't divide into 64 without a single item remaining in a slot, resulting in an item or two getting deleted.
What happens:
Video of unexpected behavior: (from Coestar on Twitch)
7 nether quartz are put in the three slots in the amounts [1][1][5], one fused quartz comes out, but only a single nether quartz remains in the alloy smelter. This is unexpected because the recipe is 4 quartz per fused quartz, meaning that two disappeared.
https://www.twitch.tv/coestar/clip/TameSmellyWatercressMrDestructoid
What you expected to happen:
The alloy smelter should figure out how to do basic math and realize that 1 + 1 + 4 โ 4. It shouldn't matter which slots items are in for a recipe that only needs one type of item in the alloy smelter.
For the example video above, the expected result would have been one fused quartz and 3 nether quartz remaining in the machine. 2 fused quartz are missing.
Steps to reproduce:
Nether quartz (assuming recipe of 4 quartz to 1 fused quartz)
- Get an alloy smelter hooked up to power with a capacitor in.
- Get 7 nether quartz
- Place the items into the slots from left to right [1][1][5]
- Observe that only a single nether quartz remains inside the alloy smelter and only a single fused quartz is made.
- Observe that two nether quartz are missing.
Photovoltaic composite (assuming recipe of 3 composite to 1 plate)
- Get an alloy smelter hooked up to power with a capacitor in.
- Get 7 photovoltaic composite
- Place the items into the slots from left to right [1][1][5]
- Observe that no composite remains inside the alloy smelter and only two plates are produced.
- Observe that one photovoltaic composite is missing.
Affected Versions (Do not use "latest"):
- EnderIO: EnderIO-1.12.2-5.1.52
- EnderCore: EnderCore-1.12.2-0.5.73
- Minecraft: 1.12.2
- Forge: 14.23.5.2847
- SpongeForge? No
- Optifine? No
- Single Player and/or Server? Both
Your most recent log file where the issue was present:
N/A
yeah it acts like the item counter is not being decreased when using items over multiple slots causing it to use them all.
I think the root cause is in this area of the code.
Am I reading it correctly in that it will take a full-set from the last stack and discard the other stacks, rather than breaking the recipe up over the set of stacks?
I think the behavior might be to take a copy of the current machine state and the desired recipe state, and consume items in order from the machine state until the recipe is satisfied. If that completes successfully make the simulated state the actual state, otherwise abort with recipe fail?
I suppose if that is true, this bug could affect any EnderIO machine that has multiple slots for input items and has a recipe that uses only a single type of input item for a recipe. Forgive my ignorance, but I'm not sure if there would be any others.
Also being ignorant and thinking out loud:
It seems like the consume function might need to be changed to not actually consume any items if there aren't enough for the recipe, or return any it does if it fails to get enough. This would create the problem that if enough of an item for a recipe is spread across multiple slots it wouldn't work, so the consume function might also need to know about previous slots to check them and add them all up.
You'll also note that while the machine might have multiple source stacks, the consume function only takes a single stack. The entire structure should be reconsidered, and since there are active developers changes such as that are something they should consider.
For consume(), both available
and required
are copies they it is free to modify.
getQuantitiesConsumed() loops over all required stacks, then over all available inputs. If the input matches the requirement, consume() reduces both the requirement and the input (by the smaller of the two). If the requirement has been used up (is empty), it skips to the next requirement. The return is a list of all consumed items.
Note that this method does not check if the recipe can be preformed, it is only called after a recipe has been selected for the inputs.
I suspect the issue lies in the code that takes the list of consumed items and removes them from the machine, not here.
Update: I think I found it.
We have multiple type of RecipeInput
s. For the traditional (old) one, the code works fine. However, the new one, the one was made to work with input item specifications from the xml recipes, getInput() will return a copy of the stack. That mean that consume() will forget that it already consumed partial amounts from earlier stacks...
Should be an easy fix, there's a method to reduce the stack inside the recipeInput (which was put there for exactly this reason, I'd say)...