carpet-autoCraftingTable
carpet-autoCraftingTable copied to clipboard
Recipes don't update with an item filter beneath the crafting table 1.4.56
When making an item filter beneath the autocrafting table, it will only accept the first recipe put into the table. From what it appear, it seems as if the first recipe is actually crafted and stored in the output slot, not allowing any other recipes to be crafted.
This is not the case for a locked hopper under the crafting table. It works perfectly fine with that.
It is the same issue mumbo jumbo has right here: https://youtu.be/n1WCEBdAfQ4?t=132
The issue stems from the fact that the exact process by which hoppers extract items from inventories is a little confusing. These are the steps as I understand them:
- Get the output inventory of the thing above the hopper. (For the crafting table block entity, this is the whole inventory with the output slot first)
- For each slot in the output inventory do the following:
- Get the stack in the slot
- Make a copy of the stack verbatim
- Extract 1 item from slot (as its own, new, stack)
- Try to transfer (i.e. move, not copy) the entire new stack into the hopper's inventory
- If the new stack is now empty, we moved successfully: end the loop by returning
true
- If the new stack still has items left, we couldn't move it: put the copy of the original stack in the inventory slot (this "undoes" the item being removed)
- Continue the loop with the next slot...
- If we're here, nothing could be moved. Return
false
I think the best solution would be to "undo" a crafting operation if a copy of the last crafting outputs are put back in the output slot. AFAIK only hoppers can re-insert an item like this, so you wouldn't be able to exploit this to un-craft items somehow.
Here's something scuffed to get started. It doesn't sync the inventory to the client properly though.
Index: src/main/java/carpet_autocraftingtable/CraftingTableBlockEntity.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/carpet_autocraftingtable/CraftingTableBlockEntity.java b/src/main/java/carpet_autocraftingtable/CraftingTableBlockEntity.java
--- a/src/main/java/carpet_autocraftingtable/CraftingTableBlockEntity.java (revision 7f2188f67a179c0f47c15326e8a5942bcccb7fef)
+++ b/src/main/java/carpet_autocraftingtable/CraftingTableBlockEntity.java (date 1642736048671)
@@ -21,8 +21,8 @@
import net.minecraft.screen.ScreenHandler;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
-import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.ItemScatterer;
+import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry;
@@ -42,6 +42,7 @@
public DefaultedList<ItemStack> inventory;
public ItemStack output = ItemStack.EMPTY;
private Recipe<?> lastRecipe;
+ public DefaultedList<ItemStack> lastInventory;
private final List<AutoCraftingTableContainer> openContainers = new ArrayList<>();
public CraftingTableBlockEntity(BlockPos pos, BlockState state) { //this(BlockEntityType.BARREL);
@@ -54,6 +55,10 @@
public static void init() { } // registers BE type
+ private static DefaultedList<ItemStack> copyInv(DefaultedList<ItemStack> original) {
+ return DefaultedList.copyOf(ItemStack.EMPTY, original.toArray(ItemStack[]::new));
+ }
+
@Override
public void writeNbt(NbtCompound tag) {
super.writeNbt(tag);
@@ -120,7 +125,11 @@
if (slot > 0) return this.inventory.get(slot - 1);
if (!output.isEmpty()) return output;
Optional<CraftingRecipe> recipe = getCurrentRecipe();
- return recipe.map(craftingRecipe -> craftingRecipe.craft(craftingInventory)).orElse(ItemStack.EMPTY);
+ if (recipe.isPresent()) {
+ return recipe.get().craft(craftingInventory);
+ } else {
+ return ItemStack.EMPTY;
+ }
}
@Override
@@ -147,10 +156,17 @@
@Override
public void setStack(int slot, ItemStack stack) {
if (slot == 0) {
- output = stack;
- return;
- }
- inventory.set(slot - 1, stack);
+ // "Undo" the last crafting operation; the right items were put back in the output slot by a hopper or something
+ if (stack.equals(lastRecipe.getOutput())) {
+ inventory = lastInventory;
+ output = ItemStack.EMPTY;
+ markDirty();
+ } else {
+ output = stack;
+ }
+ } else {
+ inventory.set(slot - 1, stack);
+ }
}
@Override
@@ -190,13 +206,14 @@
if (this.world == null) return Optional.empty();
Optional<CraftingRecipe> optionalRecipe = this.world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, craftingInventory, world);
optionalRecipe.ifPresent(this::setLastRecipe);
+ lastInventory = copyInv(inventory); // Track the pre-crafted inventory to restore it later
return optionalRecipe;
}
private ItemStack craft() {
if (this.world == null) return ItemStack.EMPTY;
Optional<CraftingRecipe> optionalRecipe = getCurrentRecipe();
- if (!optionalRecipe.isPresent()) return ItemStack.EMPTY;
+ if (optionalRecipe.isEmpty()) return ItemStack.EMPTY;
CraftingRecipe recipe = optionalRecipe.get();
ItemStack result = recipe.craft(craftingInventory);
DefaultedList<ItemStack> remaining = world.getRecipeManager().getRemainingStacks(RecipeType.CRAFTING, craftingInventory, world);
Having this issue with my gold farm crafting system as well, joining so ik when it is fixed