Răsfoiți Sursa

REI 5.1.0:
- Improve auto crafting, now able to detect things on the grid
- Introduce getResultingEntries as a replacement for getOutputEntries, it can now handle lists of lists of stacks
- Caching for fluid hashing
- Full fractions support for simple recipe display
- Made searchFavorites defaulted false

Signed-off-by: shedaniel <daniel@shedaniel.me>

shedaniel 4 ani în urmă
părinte
comite
193604a7f9
31 a modificat fișierele cu 164 adăugiri și 105 ștergeri
  1. 1 1
      RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/RecipeCategory.java
  2. 14 1
      RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/RecipeDisplay.java
  3. 51 28
      RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/gui/entries/SimpleRecipeEntry.java
  4. 2 2
      RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/server/RecipeFinder.java
  5. 3 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java
  6. 1 1
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/beacon/DefaultBeaconBaseDisplay.java
  7. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/brewing/DefaultBrewingDisplay.java
  8. 1 1
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireCategory.java
  9. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireDisplay.java
  10. 1 3
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingCategory.java
  11. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingDisplay.java
  12. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/cooking/DefaultCookingCategory.java
  13. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/cooking/DefaultCookingDisplay.java
  14. 1 1
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingCategory.java
  15. 3 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCustomDisplay.java
  16. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapedDisplay.java
  17. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapelessDisplay.java
  18. 1 1
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/fuel/DefaultFuelDisplay.java
  19. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/information/DefaultInformationDisplay.java
  20. 1 1
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/smithing/DefaultSmithingCategory.java
  21. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/smithing/DefaultSmithingDisplay.java
  22. 1 1
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingCategory.java
  23. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingDisplay.java
  24. 2 2
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/stripping/DefaultStrippingDisplay.java
  25. 1 1
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListEntryWidget.java
  26. 15 2
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryWidget.java
  27. 1 1
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java
  28. 17 9
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java
  29. 9 7
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/RecipeHelperImpl.java
  30. 17 17
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java
  31. 1 1
      gradle.properties

+ 1 - 1
RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/RecipeCategory.java

@@ -70,7 +70,7 @@ public interface RecipeCategory<T extends RecipeDisplay> {
      */
      */
     @ApiStatus.OverrideOnly
     @ApiStatus.OverrideOnly
     default RecipeEntry getSimpleRenderer(T recipe) {
     default RecipeEntry getSimpleRenderer(T recipe) {
-        return SimpleRecipeEntry.create(recipe::getInputEntries, recipe::getOutputEntries);
+        return SimpleRecipeEntry.from(recipe::getInputEntries, recipe::getResultingEntries);
     }
     }
     
     
     /**
     /**

+ 14 - 1
RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/RecipeDisplay.java

@@ -23,7 +23,9 @@
 
 
 package me.shedaniel.rei.api;
 package me.shedaniel.rei.api;
 
 
+import me.shedaniel.rei.utils.CollectionUtils;
 import net.minecraft.util.Identifier;
 import net.minecraft.util.Identifier;
+import org.jetbrains.annotations.ApiStatus;
 
 
 import java.util.Collections;
 import java.util.Collections;
 import java.util.List;
 import java.util.List;
@@ -39,7 +41,18 @@ public interface RecipeDisplay {
     /**
     /**
      * @return a list of outputs
      * @return a list of outputs
      */
      */
-    List<EntryStack> getOutputEntries();
+    @Deprecated
+    @ApiStatus.ScheduledForRemoval
+    default List<EntryStack> getOutputEntries() {
+        return Collections.emptyList();
+    }
+    
+    /**
+     * @return a list of outputs
+     */
+    default List<List<EntryStack>> getResultingEntries() {
+        return CollectionUtils.map(getOutputEntries(), Collections::singletonList);
+    }
     
     
     /**
     /**
      * Gets the required items used in craftable filters
      * Gets the required items used in craftable filters

+ 51 - 28
RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/gui/entries/SimpleRecipeEntry.java

@@ -23,10 +23,11 @@
 
 
 package me.shedaniel.rei.gui.entries;
 package me.shedaniel.rei.gui.entries;
 
 
-import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import me.shedaniel.math.Point;
 import me.shedaniel.math.Point;
 import me.shedaniel.math.Rectangle;
 import me.shedaniel.math.Rectangle;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.EntryStack;
+import me.shedaniel.rei.api.fractions.Fraction;
 import me.shedaniel.rei.api.widgets.Slot;
 import me.shedaniel.rei.api.widgets.Slot;
 import me.shedaniel.rei.api.widgets.Tooltip;
 import me.shedaniel.rei.api.widgets.Tooltip;
 import me.shedaniel.rei.api.widgets.Widgets;
 import me.shedaniel.rei.api.widgets.Widgets;
@@ -34,14 +35,15 @@ import me.shedaniel.rei.utils.CollectionUtils;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.util.math.MatrixStack;
 import net.minecraft.client.util.math.MatrixStack;
 import net.minecraft.util.Identifier;
 import net.minecraft.util.Identifier;
-import net.minecraft.util.Pair;
 import net.minecraft.util.math.MathHelper;
 import net.minecraft.util.math.MathHelper;
 import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.Nullable;
 
 
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.Comparator;
 import java.util.List;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Supplier;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -50,35 +52,51 @@ public class SimpleRecipeEntry extends RecipeEntry {
     private static final Comparator<EntryStack> ENTRY_COMPARATOR = Comparator.comparingLong(EntryStack::hashCode);
     private static final Comparator<EntryStack> ENTRY_COMPARATOR = Comparator.comparingLong(EntryStack::hashCode);
     private static final Identifier CHEST_GUI_TEXTURE = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
     private static final Identifier CHEST_GUI_TEXTURE = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
     private List<Slot> inputWidgets;
     private List<Slot> inputWidgets;
-    private Slot outputWidget;
+    private List<Slot> outputWidgets;
     
     
     @ApiStatus.Internal
     @ApiStatus.Internal
-    protected SimpleRecipeEntry(List<List<EntryStack>> input, List<EntryStack> output) {
-        List<Pair<List<EntryStack>, AtomicInteger>> newList = Lists.newArrayList();
-        List<Pair<List<EntryStack>, Integer>> a = CollectionUtils.map(input, stacks -> new Pair<>(stacks, stacks.stream().map(EntryStack::getAmount).max(Integer::compareTo).orElse(1)));
-        for (Pair<List<EntryStack>, Integer> pair : a) {
-            Pair<List<EntryStack>, AtomicInteger> any = CollectionUtils.findFirstOrNull(newList, pairr -> equalsList(pair.getLeft(), pairr.getLeft()));
-            if (any != null) {
-                any.getRight().addAndGet(pair.getRight());
-            } else
-                newList.add(new Pair<>(pair.getLeft(), new AtomicInteger(pair.getRight())));
-        }
-        List<List<EntryStack>> b = Lists.newArrayList();
-        for (Pair<List<EntryStack>, AtomicInteger> pair : newList)
-            b.add(pair.getLeft().stream().map(stack -> {
-                EntryStack s = stack.copy();
-                s.setAmount(pair.getRight().get());
-                return s;
-            }).collect(Collectors.toList()));
-        this.inputWidgets = b.stream().filter(stacks -> !stacks.isEmpty()).map(stacks -> Widgets.createSlot(new Point(0, 0)).entries(stacks).disableBackground().disableHighlight().disableTooltips()).collect(Collectors.toList());
-        this.outputWidget = Widgets.createSlot(new Point(0, 0)).entries(CollectionUtils.filter(output, stack -> !stack.isEmpty())).disableBackground().disableHighlight().disableTooltips();
+    protected SimpleRecipeEntry(List<List<EntryStack>> input, List<List<EntryStack>> output) {
+        this.inputWidgets = simplify(input).stream().filter(stacks -> !stacks.isEmpty()).map(stacks -> Widgets.createSlot(new Point(0, 0)).entries(stacks).disableBackground().disableHighlight().disableTooltips()).collect(Collectors.toList());
+        this.outputWidgets = CollectionUtils.map(simplify(output), outputStacks ->
+                Widgets.createSlot(new Point(0, 0)).entries(CollectionUtils.filter(outputStacks, stack -> !stack.isEmpty())).disableBackground().disableHighlight().disableTooltips());
+    }
+    
+    private static List<List<EntryStack>> simplify(List<List<EntryStack>> original) {
+        Map<List<EntryStack>, AtomicReference<Fraction>> inputCounter = Maps.newLinkedHashMap();
+        original.stream().collect(Collectors.groupingBy(stacks -> CollectionUtils.mapAndMax(stacks, EntryStack::getAccurateAmount, Fraction::compareTo).orElse(Fraction.empty())))
+                .forEach((fraction, value) -> {
+                    if (!fraction.equals(Fraction.empty())) {
+                        value.forEach(stackList -> {
+                            List<EntryStack> stacks = inputCounter.keySet().stream().filter(s -> equalsList(stackList, s)).findFirst().orElse(stackList);
+                            AtomicReference<Fraction> reference = inputCounter.computeIfAbsent(stacks, s -> new AtomicReference<>(Fraction.empty()));
+                            reference.set(reference.get().add(fraction));
+                        });
+                    }
+                });
+        return inputCounter.entrySet().stream().map(entry -> CollectionUtils.map(entry.getKey(), stack -> {
+            EntryStack s = stack.copy();
+            s.setAmount(entry.getValue().get());
+            return s;
+        })).collect(Collectors.toList());
     }
     }
     
     
+    @Deprecated
+    @ApiStatus.ScheduledForRemoval
     public static RecipeEntry create(Supplier<List<List<EntryStack>>> input, Supplier<List<EntryStack>> output) {
     public static RecipeEntry create(Supplier<List<List<EntryStack>>> input, Supplier<List<EntryStack>> output) {
         return create(input.get(), output.get());
         return create(input.get(), output.get());
     }
     }
     
     
+    public static RecipeEntry from(Supplier<List<List<EntryStack>>> input, Supplier<List<List<EntryStack>>> output) {
+        return from(input.get(), output.get());
+    }
+    
+    @Deprecated
+    @ApiStatus.ScheduledForRemoval
     public static RecipeEntry create(List<List<EntryStack>> input, List<EntryStack> output) {
     public static RecipeEntry create(List<List<EntryStack>> input, List<EntryStack> output) {
+        return from(input, CollectionUtils.map(output, Collections::singletonList));
+    }
+    
+    public static RecipeEntry from(List<List<EntryStack>> input, List<List<EntryStack>> output) {
         return new SimpleRecipeEntry(input, output);
         return new SimpleRecipeEntry(input, output);
     }
     }
     
     
@@ -117,9 +135,12 @@ public class SimpleRecipeEntry extends RecipeEntry {
         MinecraftClient.getInstance().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
         MinecraftClient.getInstance().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
         drawTexture(matrices, xx, yy, 0, 28, 18, 18);
         drawTexture(matrices, xx, yy, 0, 28, 18, 18);
         xx += 18;
         xx += 18;
-        outputWidget.setZ(getZ() + 50);
-        outputWidget.getBounds().setLocation(xx, yy);
-        outputWidget.render(matrices, mouseX, mouseY, delta);
+        yy += outputWidgets.size() * -9 + 9;
+        for (Slot outputWidget : outputWidgets) {
+            outputWidget.setZ(getZ() + 50);
+            outputWidget.getBounds().setLocation(xx, yy);
+            outputWidget.render(matrices, mouseX, mouseY, delta);
+        }
     }
     }
     
     
     @Nullable
     @Nullable
@@ -129,8 +150,10 @@ public class SimpleRecipeEntry extends RecipeEntry {
             if (widget.containsMouse(point))
             if (widget.containsMouse(point))
                 return widget.getCurrentTooltip(point);
                 return widget.getCurrentTooltip(point);
         }
         }
-        if (outputWidget.containsMouse(point))
-            return outputWidget.getCurrentTooltip(point);
+        for (Slot widget : outputWidgets) {
+            if (widget.containsMouse(point))
+                return widget.getCurrentTooltip(point);
+        }
         return null;
         return null;
     }
     }
     
     

+ 2 - 2
RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/server/RecipeFinder.java

@@ -71,7 +71,7 @@ public class RecipeFinder {
         
         
     }
     }
     
     
-    private boolean contains(int itemId) {
+    public boolean contains(int itemId) {
         return this.idToAmountMap.get(itemId) > 0;
         return this.idToAmountMap.get(itemId) > 0;
     }
     }
     
     
@@ -80,7 +80,7 @@ public class RecipeFinder {
      *
      *
      * @return the amount taken
      * @return the amount taken
      */
      */
-    private int take(int itemId, int amount) {
+    public int take(int itemId, int amount) {
         int mapAmount = this.idToAmountMap.get(itemId);
         int mapAmount = this.idToAmountMap.get(itemId);
         if (mapAmount >= amount) {
         if (mapAmount >= amount) {
             this.idToAmountMap.put(itemId, mapAmount - amount);
             this.idToAmountMap.put(itemId, mapAmount - amount);

+ 3 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java

@@ -252,8 +252,9 @@ public class DefaultPlugin implements REIPluginV0 {
                 for (List<EntryStack> entries : display.getInputEntries())
                 for (List<EntryStack> entries : display.getInputEntries())
                     for (EntryStack stack : entries)
                     for (EntryStack stack : entries)
                         applyPotionTransformer(stack);
                         applyPotionTransformer(stack);
-                for (EntryStack stack : display.getOutputEntries())
-                    applyPotionTransformer(stack);
+                for (List<EntryStack> entries : display.getResultingEntries())
+                    for (EntryStack stack : entries)
+                        applyPotionTransformer(stack);
             }
             }
         }
         }
         time = System.currentTimeMillis() - time;
         time = System.currentTimeMillis() - time;

+ 1 - 1
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/beacon/DefaultBeaconBaseDisplay.java

@@ -53,7 +53,7 @@ public class DefaultBeaconBaseDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
+    public List<List<EntryStack>> getResultingEntries() {
         return Collections.emptyList();
         return Collections.emptyList();
     }
     }
     
     

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/brewing/DefaultBrewingDisplay.java

@@ -65,8 +65,8 @@ public class DefaultBrewingDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return Collections.singletonList(output);
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(Collections.singletonList(output));
     }
     }
     
     
     @Override
     @Override

+ 1 - 1
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireCategory.java

@@ -69,7 +69,7 @@ public class DefaultCampfireCategory implements RecipeCategory<DefaultCampfireDi
                 new TranslatableText("category.rei.campfire.time", df.format(cookingTime / 20d))).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB));
                 new TranslatableText("category.rei.campfire.time", df.format(cookingTime / 20d))).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB));
         widgets.add(Widgets.createArrow(new Point(startPoint.x + 24, startPoint.y + 8)).animationDurationTicks(cookingTime));
         widgets.add(Widgets.createArrow(new Point(startPoint.x + 24, startPoint.y + 8)).animationDurationTicks(cookingTime));
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 1, startPoint.y + 1)).entries(display.getInputEntries().get(0)).markInput());
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 1, startPoint.y + 1)).entries(display.getInputEntries().get(0)).markInput());
-        widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 9)).entries(display.getOutputEntries()).disableBackground().markOutput());
+        widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 9)).entries(display.getResultingEntries().get(0)).disableBackground().markOutput());
         return widgets;
         return widgets;
     }
     }
     
     

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireDisplay.java

@@ -73,8 +73,8 @@ public class DefaultCampfireDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return output;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(output);
     }
     }
     
     
     @Override
     @Override

+ 1 - 3
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingCategory.java

@@ -27,7 +27,6 @@ import com.google.common.collect.Lists;
 import me.shedaniel.math.Point;
 import me.shedaniel.math.Point;
 import me.shedaniel.math.Rectangle;
 import me.shedaniel.math.Rectangle;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.EntryStack;
-import me.shedaniel.rei.api.REIHelper;
 import me.shedaniel.rei.api.RecipeCategory;
 import me.shedaniel.rei.api.RecipeCategory;
 import me.shedaniel.rei.api.widgets.Widgets;
 import me.shedaniel.rei.api.widgets.Widgets;
 import me.shedaniel.rei.gui.entries.RecipeEntry;
 import me.shedaniel.rei.gui.entries.RecipeEntry;
@@ -86,7 +85,6 @@ public class DefaultCompostingCategory implements RecipeCategory<DefaultComposti
     public List<Widget> setupDisplay(DefaultCompostingDisplay display, Rectangle bounds) {
     public List<Widget> setupDisplay(DefaultCompostingDisplay display, Rectangle bounds) {
         List<Widget> widgets = Lists.newArrayList();
         List<Widget> widgets = Lists.newArrayList();
         Point startingPoint = new Point(bounds.x + bounds.width - 55, bounds.y + 110);
         Point startingPoint = new Point(bounds.x + bounds.width - 55, bounds.y + 110);
-        widgets.add(Widgets.createFilledRectangle(bounds, REIHelper.getInstance().isDarkThemeEnabled() ? -13750738 : -3750202));
         List<EntryStack> stacks = new ArrayList<>(display.getRequiredEntries().get(0));
         List<EntryStack> stacks = new ArrayList<>(display.getRequiredEntries().get(0));
         int i = 0;
         int i = 0;
         for (int y = 0; y < 6; y++)
         for (int y = 0; y < 6; y++)
@@ -102,7 +100,7 @@ public class DefaultCompostingCategory implements RecipeCategory<DefaultComposti
             }
             }
         widgets.add(Widgets.createArrow(new Point(startingPoint.x - 1, startingPoint.y + 7)));
         widgets.add(Widgets.createArrow(new Point(startingPoint.x - 1, startingPoint.y + 7)));
         widgets.add(Widgets.createResultSlotBackground(new Point(startingPoint.x + 33, startingPoint.y + 8)));
         widgets.add(Widgets.createResultSlotBackground(new Point(startingPoint.x + 33, startingPoint.y + 8)));
-        widgets.add(Widgets.createSlot(new Point(startingPoint.x + 33, startingPoint.y + 8)).entries(display.getOutputEntries()).disableBackground().markOutput());
+        widgets.add(Widgets.createSlot(new Point(startingPoint.x + 33, startingPoint.y + 8)).entries(display.getResultingEntries().get(0)).disableBackground().markOutput());
         return widgets;
         return widgets;
     }
     }
     
     

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingDisplay.java

@@ -65,8 +65,8 @@ public class DefaultCompostingDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return output;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(output);
     }
     }
     
     
     @Override
     @Override

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/cooking/DefaultCookingCategory.java

@@ -78,13 +78,13 @@ public class DefaultCookingCategory implements TransferRecipeCategory<DefaultCoo
                 new TranslatableText("category.rei.cooking.time&xp", df.format(display.getXp()), df.format(cookingTime / 20d))).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB));
                 new TranslatableText("category.rei.cooking.time&xp", df.format(display.getXp()), df.format(cookingTime / 20d))).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB));
         widgets.add(Widgets.createArrow(new Point(startPoint.x + 24, startPoint.y + 8)).animationDurationTicks(cookingTime));
         widgets.add(Widgets.createArrow(new Point(startPoint.x + 24, startPoint.y + 8)).animationDurationTicks(cookingTime));
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 1, startPoint.y + 1)).entries(display.getInputEntries().get(0)).markInput());
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 1, startPoint.y + 1)).entries(display.getInputEntries().get(0)).markInput());
-        widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 9)).entries(display.getOutputEntries()).disableBackground().markOutput());
+        widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 9)).entries(display.getResultingEntries().get(0)).disableBackground().markOutput());
         return widgets;
         return widgets;
     }
     }
     
     
     @Override
     @Override
     public RecipeEntry getSimpleRenderer(DefaultCookingDisplay recipe) {
     public RecipeEntry getSimpleRenderer(DefaultCookingDisplay recipe) {
-        return SimpleRecipeEntry.create(Collections.singletonList(recipe.getInputEntries().get(0)), recipe.getOutputEntries());
+        return SimpleRecipeEntry.from(Collections.singletonList(recipe.getInputEntries().get(0)), recipe.getResultingEntries());
     }
     }
     
     
     @Override
     @Override

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/cooking/DefaultCookingDisplay.java

@@ -79,8 +79,8 @@ public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return output;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(output);
     }
     }
     
     
     @Override
     @Override

+ 1 - 1
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingCategory.java

@@ -89,7 +89,7 @@ public class DefaultCraftingCategory implements TransferRecipeCategory<DefaultCr
                 slots.get(i).entries(input.get(i));
                 slots.get(i).entries(input.get(i));
         }
         }
         widgets.addAll(slots);
         widgets.addAll(slots);
-        widgets.add(Widgets.createSlot(new Point(startPoint.x + 95, startPoint.y + 19)).entries(display.getOutputEntries()).disableBackground().markOutput());
+        widgets.add(Widgets.createSlot(new Point(startPoint.x + 95, startPoint.y + 19)).entries(display.getResultingEntries().get(0)).disableBackground().markOutput());
         return widgets;
         return widgets;
     }
     }
     
     

+ 3 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCustomDisplay.java

@@ -32,6 +32,7 @@ import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.util.Identifier;
 import net.minecraft.util.Identifier;
 
 
+import java.util.Collections;
 import java.util.List;
 import java.util.List;
 import java.util.Optional;
 import java.util.Optional;
 
 
@@ -84,8 +85,8 @@ public class DefaultCustomDisplay implements DefaultCraftingDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return output;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(output);
     }
     }
     
     
     @Override
     @Override

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapedDisplay.java

@@ -58,8 +58,8 @@ public class DefaultShapedDisplay implements DefaultCraftingDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return output;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(output);
     }
     }
     
     
     @Override
     @Override

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapelessDisplay.java

@@ -63,8 +63,8 @@ public class DefaultShapelessDisplay implements DefaultCraftingDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return output;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(output);
     }
     }
     
     
     @Override
     @Override

+ 1 - 1
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/fuel/DefaultFuelDisplay.java

@@ -49,7 +49,7 @@ public class DefaultFuelDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
+    public List<List<EntryStack>> getResultingEntries() {
         return Collections.emptyList();
         return Collections.emptyList();
     }
     }
     
     

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/information/DefaultInformationDisplay.java

@@ -63,8 +63,8 @@ public class DefaultInformationDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return entryStacks;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(entryStacks);
     }
     }
     
     
     public DefaultInformationDisplay line(Text line) {
     public DefaultInformationDisplay line(Text line) {

+ 1 - 1
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/smithing/DefaultSmithingCategory.java

@@ -62,7 +62,7 @@ public class DefaultSmithingCategory implements RecipeCategory<DefaultSmithingDi
         widgets.add(Widgets.createResultSlotBackground(new Point(startPoint.x + 61, startPoint.y + 5)));
         widgets.add(Widgets.createResultSlotBackground(new Point(startPoint.x + 61, startPoint.y + 5)));
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 4 - 22, startPoint.y + 5)).entries(display.getInputEntries().get(0)).markInput());
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 4 - 22, startPoint.y + 5)).entries(display.getInputEntries().get(0)).markInput());
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 4, startPoint.y + 5)).entries(display.getInputEntries().get(1)).markInput());
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 4, startPoint.y + 5)).entries(display.getInputEntries().get(1)).markInput());
-        widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 5)).entries(display.getOutputEntries()).disableBackground().markOutput());
+        widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 5)).entries(display.getResultingEntries().get(0)).disableBackground().markOutput());
         return widgets;
         return widgets;
     }
     }
     
     

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/smithing/DefaultSmithingDisplay.java

@@ -71,8 +71,8 @@ public class DefaultSmithingDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return output;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(output);
     }
     }
     
     
     @Override
     @Override

+ 1 - 1
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingCategory.java

@@ -62,7 +62,7 @@ public class DefaultStoneCuttingCategory implements RecipeCategory<DefaultStoneC
         widgets.add(Widgets.createArrow(new Point(startPoint.x + 27, startPoint.y + 4)));
         widgets.add(Widgets.createArrow(new Point(startPoint.x + 27, startPoint.y + 4)));
         widgets.add(Widgets.createResultSlotBackground(new Point(startPoint.x + 61, startPoint.y + 5)));
         widgets.add(Widgets.createResultSlotBackground(new Point(startPoint.x + 61, startPoint.y + 5)));
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 4, startPoint.y + 5)).entries(display.getInputEntries().get(0)).markInput());
         widgets.add(Widgets.createSlot(new Point(startPoint.x + 4, startPoint.y + 5)).entries(display.getInputEntries().get(0)).markInput());
-        widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 5)).entries(display.getOutputEntries()).disableBackground().markOutput());
+        widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 5)).entries(display.getResultingEntries().get(0)).disableBackground().markOutput());
         return widgets;
         return widgets;
     }
     }
     
     

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingDisplay.java

@@ -67,8 +67,8 @@ public class DefaultStoneCuttingDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return output;
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(output);
     }
     }
     
     
     @Override
     @Override

+ 2 - 2
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/stripping/DefaultStrippingDisplay.java

@@ -62,8 +62,8 @@ public class DefaultStrippingDisplay implements RecipeDisplay {
     }
     }
     
     
     @Override
     @Override
-    public List<EntryStack> getOutputEntries() {
-        return Collections.singletonList(out);
+    public List<List<EntryStack>> getResultingEntries() {
+        return Collections.singletonList(Collections.singletonList(out));
     }
     }
     
     
     @Override
     @Override

+ 1 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListEntryWidget.java

@@ -62,7 +62,7 @@ public class EntryListEntryWidget extends EntryWidget {
             return super.mouseReleased(mouseX, mouseY, button);
             return super.mouseReleased(mouseX, mouseY, button);
         if (containsMouse(mouseX, mouseY) && ClientHelper.getInstance().isCheating()) {
         if (containsMouse(mouseX, mouseY) && ClientHelper.getInstance().isCheating()) {
             EntryStack entry = getCurrentEntry().copy();
             EntryStack entry = getCurrentEntry().copy();
-            if (!entry.isEmpty()) {
+            if (!entry.isEmpty() && wasClicked()) {
                 if (entry.getType() == EntryStack.Type.FLUID) {
                 if (entry.getType() == EntryStack.Type.FLUID) {
                     Item bucketItem = entry.getFluid().getBucketItem();
                     Item bucketItem = entry.getFluid().getBucketItem();
                     if (bucketItem != null) {
                     if (bucketItem != null) {

+ 15 - 2
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryWidget.java

@@ -29,7 +29,6 @@ import me.shedaniel.math.Point;
 import me.shedaniel.math.Rectangle;
 import me.shedaniel.math.Rectangle;
 import me.shedaniel.math.impl.PointHelper;
 import me.shedaniel.math.impl.PointHelper;
 import me.shedaniel.rei.api.*;
 import me.shedaniel.rei.api.*;
-import me.shedaniel.rei.api.fractions.Fraction;
 import me.shedaniel.rei.api.widgets.Slot;
 import me.shedaniel.rei.api.widgets.Slot;
 import me.shedaniel.rei.api.widgets.Tooltip;
 import me.shedaniel.rei.api.widgets.Tooltip;
 import me.shedaniel.rei.gui.ContainerScreenOverlay;
 import me.shedaniel.rei.gui.ContainerScreenOverlay;
@@ -65,6 +64,7 @@ public class EntryWidget extends Slot {
     protected boolean background = true;
     protected boolean background = true;
     protected boolean interactable = true;
     protected boolean interactable = true;
     protected boolean interactableFavorites = true;
     protected boolean interactableFavorites = true;
+    protected boolean wasClicked = false;
     private Rectangle bounds;
     private Rectangle bounds;
     private List<EntryStack> entryStacks;
     private List<EntryStack> entryStacks;
     
     
@@ -350,11 +350,24 @@ public class EntryWidget extends Slot {
         return Collections.emptyList();
         return Collections.emptyList();
     }
     }
     
     
+    protected boolean wasClicked() {
+        boolean b = this.wasClicked;
+        this.wasClicked = false;
+        return b;
+    }
+    
+    @Override
+    public boolean mouseClicked(double mouseX, double mouseY, int button) {
+        if (containsMouse(mouseX, mouseY))
+            this.wasClicked = true;
+        return super.mouseClicked(mouseX, mouseY, button);
+    }
+    
     @Override
     @Override
     public boolean mouseReleased(double mouseX, double mouseY, int button) {
     public boolean mouseReleased(double mouseX, double mouseY, int button) {
         if (!interactable)
         if (!interactable)
             return false;
             return false;
-        if (containsMouse(mouseX, mouseY)) {
+        if (wasClicked() && containsMouse(mouseX, mouseY)) {
             if (interactableFavorites && ConfigObject.getInstance().isFavoritesEnabled() && containsMouse(PointHelper.ofMouse()) && !getCurrentEntry().isEmpty()) {
             if (interactableFavorites && ConfigObject.getInstance().isFavoritesEnabled() && containsMouse(PointHelper.ofMouse()) && !getCurrentEntry().isEmpty()) {
                 ModifierKeyCode keyCode = ConfigObject.getInstance().getFavoriteKeyCode();
                 ModifierKeyCode keyCode = ConfigObject.getInstance().getFavoriteKeyCode();
                 EntryStack entry = getCurrentEntry().copy();
                 EntryStack entry = getCurrentEntry().copy();

+ 1 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java

@@ -448,7 +448,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
         }
         }
         
         
         public static class Search {
         public static class Search {
-            @Comment("Declares whether favorites will be searched.") private boolean searchFavorites = true;
+            @Comment("Declares whether favorites will be searched.") private boolean searchFavorites = false;
             @Comment("Declares whether search time should be debugged.") private boolean debugSearchTimeRequired = false;
             @Comment("Declares whether search time should be debugged.") private boolean debugSearchTimeRequired = false;
             @Comment("Declares whether REI should search async.") private boolean asyncSearch = true;
             @Comment("Declares whether REI should search async.") private boolean asyncSearch = true;
             @Comment("Declares how many entries should be grouped one async search.") @ConfigEntry.BoundedDiscrete(min = 25, max = 400)
             @Comment("Declares how many entries should be grouped one async search.") @ConfigEntry.BoundedDiscrete(min = 25, max = 400)

+ 17 - 9
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java

@@ -65,6 +65,8 @@ public class FluidEntryStack extends AbstractEntryStack {
     private static final Fraction IGNORE_AMOUNT = Fraction.of(ThreadLocalRandom.current().nextLong(), ThreadLocalRandom.current().nextLong(Long.MAX_VALUE)).simplify();
     private static final Fraction IGNORE_AMOUNT = Fraction.of(ThreadLocalRandom.current().nextLong(), ThreadLocalRandom.current().nextLong(Long.MAX_VALUE)).simplify();
     private Fluid fluid;
     private Fluid fluid;
     private Fraction amount;
     private Fraction amount;
+    private int hashIgnoreAmount;
+    private int hash;
     
     
     public FluidEntryStack(Fluid fluid) {
     public FluidEntryStack(Fluid fluid) {
         this(fluid, IGNORE_AMOUNT);
         this(fluid, IGNORE_AMOUNT);
@@ -73,6 +75,15 @@ public class FluidEntryStack extends AbstractEntryStack {
     public FluidEntryStack(Fluid fluid, Fraction amount) {
     public FluidEntryStack(Fluid fluid, Fraction amount) {
         this.fluid = fluid;
         this.fluid = fluid;
         this.amount = amount;
         this.amount = amount;
+        
+        rehash();
+    }
+    
+    private void rehash() {
+        hashIgnoreAmount = 31 + getType().ordinal();
+        hashIgnoreAmount = 31 * hashIgnoreAmount + fluid.hashCode();
+        
+        hash = 31 * hashIgnoreAmount + amount.hashCode();
     }
     }
     
     
     @Override
     @Override
@@ -96,6 +107,8 @@ public class FluidEntryStack extends AbstractEntryStack {
         if (isEmpty()) {
         if (isEmpty()) {
             fluid = Fluids.EMPTY;
             fluid = Fluids.EMPTY;
         }
         }
+        
+        rehash();
     }
     }
     
     
     private <T extends Comparable<T>> T max(T o1, T o2) {
     private <T extends Comparable<T>> T max(T o1, T o2) {
@@ -157,27 +170,22 @@ public class FluidEntryStack extends AbstractEntryStack {
     
     
     @Override
     @Override
     public int hashOfAll() {
     public int hashOfAll() {
-        int result = hashIgnoreAmountAndTags();
-        result = 31 * result + amount.hashCode();
-        return result;
+        return hash;
     }
     }
     
     
     @Override
     @Override
     public int hashIgnoreAmountAndTags() {
     public int hashIgnoreAmountAndTags() {
-        int result = 1;
-        result = 31 * result + getType().ordinal();
-        result = 31 * result + fluid.hashCode();
-        return result;
+        return hashIgnoreAmount;
     }
     }
     
     
     @Override
     @Override
     public int hashIgnoreTags() {
     public int hashIgnoreTags() {
-        return hashOfAll();
+        return hash;
     }
     }
     
     
     @Override
     @Override
     public int hashIgnoreAmount() {
     public int hashIgnoreAmount() {
-        return hashIgnoreAmountAndTags();
+        return hashIgnoreAmount;
     }
     }
     
     
     @Nullable
     @Nullable

+ 9 - 7
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/RecipeHelperImpl.java

@@ -98,7 +98,7 @@ public class RecipeHelperImpl implements RecipeHelper {
                     }
                     }
                 }
                 }
                 if (slotsCraftable == recipeDisplay.getRequiredEntries().size())
                 if (slotsCraftable == recipeDisplay.getRequiredEntries().size())
-                    craftables.addAll(recipeDisplay.getOutputEntries());
+                    recipeDisplay.getResultingEntries().stream().flatMap(Collection::stream).collect(Collectors.toCollection(() -> craftables));
             }
             }
         return craftables.stream().distinct().collect(Collectors.toList());
         return craftables.stream().distinct().collect(Collectors.toList());
     }
     }
@@ -175,12 +175,14 @@ public class RecipeHelperImpl implements RecipeHelper {
             for (RecipeDisplay display : allRecipesFromCategory) {
             for (RecipeDisplay display : allRecipesFromCategory) {
                 if (!isDisplayVisible(display)) continue;
                 if (!isDisplayVisible(display)) continue;
                 if (!recipesFor.isEmpty()) {
                 if (!recipesFor.isEmpty()) {
-                    label:
-                    for (EntryStack outputStack : display.getOutputEntries()) {
-                        for (EntryStack stack : recipesFor) {
-                            if (stack.equals(outputStack)) {
-                                set.add(display);
-                                break label;
+                    back:
+                    for (List<EntryStack> results : display.getResultingEntries()) {
+                        for (EntryStack otherEntry : results) {
+                            for (EntryStack stack : recipesFor) {
+                                if (otherEntry.equals(stack)) {
+                                    set.add(display);
+                                    break back;
+                                }
                             }
                             }
                         }
                         }
                     }
                     }

+ 17 - 17
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java

@@ -33,6 +33,7 @@ import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.TransferRecipeDisplay;
 import me.shedaniel.rei.api.TransferRecipeDisplay;
 import me.shedaniel.rei.server.ContainerInfo;
 import me.shedaniel.rei.server.ContainerInfo;
 import me.shedaniel.rei.server.ContainerInfoHandler;
 import me.shedaniel.rei.server.ContainerInfoHandler;
+import me.shedaniel.rei.server.RecipeFinder;
 import net.fabricmc.api.EnvType;
 import net.fabricmc.api.EnvType;
 import net.fabricmc.api.Environment;
 import net.fabricmc.api.Environment;
 import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
 import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
@@ -44,7 +45,7 @@ import net.minecraft.client.resource.language.I18n;
 import net.minecraft.container.Container;
 import net.minecraft.container.Container;
 import net.minecraft.item.ItemStack;
 import net.minecraft.item.ItemStack;
 import net.minecraft.network.PacketByteBuf;
 import net.minecraft.network.PacketByteBuf;
-import net.minecraft.util.collection.DefaultedList;
+import net.minecraft.util.registry.Registry;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.NotNull;
 
 
 import java.util.List;
 import java.util.List;
@@ -66,7 +67,7 @@ public class DefaultCategoryHandler implements AutoTransferHandler {
         if (recipe.getHeight() > containerInfo.getCraftingHeight(container) || recipe.getWidth() > containerInfo.getCraftingWidth(container))
         if (recipe.getHeight() > containerInfo.getCraftingHeight(container) || recipe.getWidth() > containerInfo.getCraftingWidth(container))
             return Result.createFailed(I18n.translate("error.rei.transfer.too_small", containerInfo.getCraftingWidth(container), containerInfo.getCraftingHeight(container)));
             return Result.createFailed(I18n.translate("error.rei.transfer.too_small", containerInfo.getCraftingWidth(container), containerInfo.getCraftingHeight(container)));
         List<List<EntryStack>> input = recipe.getOrganisedInputEntries(containerInfo, container);
         List<List<EntryStack>> input = recipe.getOrganisedInputEntries(containerInfo, container);
-        IntList intList = hasItems(input);
+        IntList intList = hasItems(container, containerInfo, input);
         if (!intList.isEmpty())
         if (!intList.isEmpty())
             return Result.createFailed("error.rei.not.enough.materials", intList);
             return Result.createFailed("error.rei.not.enough.materials", intList);
         if (!ClientHelper.getInstance().canUseMovePackets())
         if (!ClientHelper.getInstance().canUseMovePackets())
@@ -100,11 +101,12 @@ public class DefaultCategoryHandler implements AutoTransferHandler {
         return -10;
         return -10;
     }
     }
     
     
-    public IntList hasItems(List<List<EntryStack>> inputs) {
+    public IntList hasItems(Container container, ContainerInfo<Container> containerInfo, List<List<EntryStack>> inputs) {
         // Create a clone of player's inventory, and count
         // Create a clone of player's inventory, and count
-        DefaultedList<ItemStack> copyMain = DefaultedList.of();
+        RecipeFinder recipeFinder = new RecipeFinder();
+        containerInfo.populateRecipeFinder(container, recipeFinder);
         for (ItemStack stack : MinecraftClient.getInstance().player.inventory.main) {
         for (ItemStack stack : MinecraftClient.getInstance().player.inventory.main) {
-            copyMain.add(stack.copy());
+            recipeFinder.addNormalItem(stack.copy());
         }
         }
         IntList intList = new IntArrayList();
         IntList intList = new IntArrayList();
         for (int i = 0; i < inputs.size(); i++) {
         for (int i = 0; i < inputs.size(); i++) {
@@ -112,19 +114,17 @@ public class DefaultCategoryHandler implements AutoTransferHandler {
             boolean done = possibleStacks.isEmpty();
             boolean done = possibleStacks.isEmpty();
             for (EntryStack possibleStack : possibleStacks) {
             for (EntryStack possibleStack : possibleStacks) {
                 if (!done) {
                 if (!done) {
-                    int invRequiredCount = possibleStack.getAmount();
-                    for (ItemStack stack : copyMain) {
-                        EntryStack entryStack = EntryStack.create(stack);
-                        if (entryStack.equals(possibleStack)) {
-                            while (invRequiredCount > 0 && !stack.isEmpty()) {
-                                invRequiredCount--;
-                                stack.decrement(1);
-                            }
+                    if (possibleStack.getType() == EntryStack.Type.ITEM) {
+                        int invRequiredCount = possibleStack.getAmount();
+                        int key = Registry.ITEM.getRawId(possibleStack.getItem());
+                        while (invRequiredCount > 0 && recipeFinder.contains(key)) {
+                            invRequiredCount--;
+                            recipeFinder.take(key, 1);
+                        }
+                        if (invRequiredCount <= 0) {
+                            done = true;
+                            break;
                         }
                         }
-                    }
-                    if (invRequiredCount <= 0) {
-                        done = true;
-                        break;
                     }
                     }
                 }
                 }
             }
             }

+ 1 - 1
gradle.properties

@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx3G
 org.gradle.jvmargs=-Xmx3G
-mod_version=5.0.3-unstable
+mod_version=5.1.0-unstable
 supported_version=1.16.2+
 supported_version=1.16.2+
 minecraft_version=1.16.2-pre1
 minecraft_version=1.16.2-pre1
 yarn_version=1.16.2-pre1+build.1+legacy.20w09a+build.8
 yarn_version=1.16.2-pre1+build.1+legacy.20w09a+build.8