Преглед изворни кода

Optimised craftable filter and changed some api

Signed-off-by: shedaniel <daniel@shedaniel.me>
shedaniel пре 5 година
родитељ
комит
687101e64c
27 измењених фајлова са 151 додато и 68 уклоњено
  1. 1 1
      gradle.properties
  2. 36 14
      src/main/java/me/shedaniel/rei/api/EntryStack.java
  3. 4 3
      src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java
  4. 10 7
      src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java
  5. 3 0
      src/main/java/me/shedaniel/rei/plugin/DefaultAutoCraftingPlugin.java
  6. 14 17
      src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java
  7. 3 0
      src/main/java/me/shedaniel/rei/plugin/DefaultPotionEffectExclusionZones.java
  8. 3 0
      src/main/java/me/shedaniel/rei/plugin/DefaultRecipeBookExclusionZones.java
  9. 3 0
      src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java
  10. 3 0
      src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultRecipeBookHandler.java
  11. 4 2
      src/main/java/me/shedaniel/rei/plugin/beacon/DefaultBeaconBaseDisplay.java
  12. 3 0
      src/main/java/me/shedaniel/rei/plugin/blasting/DefaultBlastingDisplay.java
  13. 6 2
      src/main/java/me/shedaniel/rei/plugin/brewing/DefaultBrewingDisplay.java
  14. 4 1
      src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireDisplay.java
  15. 6 4
      src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingDisplay.java
  16. 4 2
      src/main/java/me/shedaniel/rei/plugin/cooking/DefaultCookingDisplay.java
  17. 3 0
      src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingDisplay.java
  18. 4 1
      src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCustomDisplay.java
  19. 4 1
      src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapedDisplay.java
  20. 4 4
      src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapelessDisplay.java
  21. 3 0
      src/main/java/me/shedaniel/rei/plugin/fuel/DefaultFuelDisplay.java
  22. 3 0
      src/main/java/me/shedaniel/rei/plugin/information/DefaultInformationDisplay.java
  23. 3 0
      src/main/java/me/shedaniel/rei/plugin/smelting/DefaultSmeltingDisplay.java
  24. 10 3
      src/main/java/me/shedaniel/rei/plugin/smithing/DefaultSmithingDisplay.java
  25. 4 3
      src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingDisplay.java
  26. 3 0
      src/main/java/me/shedaniel/rei/plugin/stripping/DefaultStrippingDisplay.java
  27. 3 3
      src/main/java/me/shedaniel/rei/utils/CollectionUtils.java

+ 1 - 1
gradle.properties

@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx3G
-mod_version=4.9.0
+mod_version=4.9.1
 supported_version=1.16.x
 minecraft_version=1.16.1
 yarn_version=1.16.1+build.4+legacy.20w09a+build.8

+ 36 - 14
src/main/java/me/shedaniel/rei/api/EntryStack.java

@@ -50,11 +50,7 @@ import net.minecraft.util.registry.Registry;
 import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 import java.util.function.Function;
 import java.util.function.Supplier;
 
@@ -81,20 +77,28 @@ public interface EntryStack extends TextRepresentable {
     static EntryStack create(ItemStack stack) {
         return new ItemEntryStack(stack);
     }
-
+    
     static EntryStack create(ItemConvertible item) {
         return create(new ItemStack(item));
     }
-
-    static List<EntryStack> create(Collection<ItemStack> stacks) {
+    
+    static List<EntryStack> ofItems(Collection<ItemConvertible> stacks) {
+        List<EntryStack> result = new ArrayList<>(stacks.size());
+        for (ItemConvertible stack : stacks) {
+            result.add(create(stack));
+        }
+        return result;
+    }
+    
+    static List<EntryStack> ofItemStacks(Collection<ItemStack> stacks) {
         List<EntryStack> result = new ArrayList<>(stacks.size());
         for (ItemStack stack : stacks) {
             result.add(create(stack));
         }
         return result;
     }
-
-    static List<EntryStack> create(Ingredient ingredient) {
+    
+    static List<EntryStack> ofIngredient(Ingredient ingredient) {
         ItemStack[] matchingStacks = ingredient.getMatchingStacksClient();
         List<EntryStack> result = new ArrayList<>(matchingStacks.length);
         for (ItemStack matchingStack : matchingStacks) {
@@ -102,15 +106,33 @@ public interface EntryStack extends TextRepresentable {
         }
         return result;
     }
-
-    static List<List<EntryStack>> create(List<Ingredient> ingredients) {
+    
+    static List<List<EntryStack>> ofIngredients(List<Ingredient> ingredients) {
         List<List<EntryStack>> result = new ArrayList<>(ingredients.size());
         for (Ingredient ingredient : ingredients) {
-            result.add(create(ingredient));
+            result.add(ofIngredient(ingredient));
         }
         return result;
     }
-
+    
+    @Deprecated
+    @ApiStatus.ScheduledForRemoval
+    static List<EntryStack> create(Collection<ItemStack> stacks) {
+        return ofItemStacks(stacks);
+    }
+    
+    @Deprecated
+    @ApiStatus.ScheduledForRemoval
+    static List<EntryStack> create(Ingredient ingredient) {
+        return ofIngredient(ingredient);
+    }
+    
+    @Deprecated
+    @ApiStatus.ScheduledForRemoval
+    static List<List<EntryStack>> create(List<Ingredient> ingredients) {
+        return ofIngredients(ingredients);
+    }
+    
     @ApiStatus.Internal
     static EntryStack readFromJson(JsonElement jsonElement) {
         try {

+ 4 - 3
src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java

@@ -24,6 +24,7 @@
 package me.shedaniel.rei.gui.widget;
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import me.shedaniel.clothconfig2.ClothConfigInitializer;
 import me.shedaniel.clothconfig2.api.ScissorsHandler;
 import me.shedaniel.clothconfig2.api.ScrollingContainer;
@@ -491,9 +492,9 @@ public class EntryListWidget extends WidgetWithBounds {
             this.lastSearchArguments = SearchArgument.processSearchTerm(searchTerm);
             List<EntryStack> list = Lists.newArrayList();
             boolean checkCraftable = ConfigManager.getInstance().isCraftableOnlyEnabled() && !ScreenHelper.inventoryStacks.isEmpty();
-            Set<EntryStack> workingItems = checkCraftable ? new TreeSet<>(Comparator.comparing(EntryStack::hashIgnoreAmount)) : null;
+            Set<Integer> workingItems = checkCraftable ? Sets.newHashSet() : null;
             if (checkCraftable)
-                workingItems.addAll(RecipeHelper.getInstance().findCraftableEntriesByItems(CollectionUtils.map(ScreenHelper.inventoryStacks, EntryStack::create)));
+                workingItems.addAll(CollectionUtils.map(RecipeHelper.getInstance().findCraftableEntriesByItems(CollectionUtils.map(ScreenHelper.inventoryStacks, EntryStack::create)), EntryStack::hashIgnoreAmount));
             List<EntryStack> stacks = EntryRegistry.getInstance().getPreFilteredList();
             if (stacks instanceof CopyOnWriteArrayList && !stacks.isEmpty()) {
                 if (ConfigObject.getInstance().shouldAsyncSearch()) {
@@ -507,7 +508,7 @@ public class EntryListWidget extends WidgetWithBounds {
                             for (; start[0] < end; start[0]++) {
                                 EntryStack stack = stacks.get(start[0]);
                                 if (canLastSearchTermsBeAppliedTo(stack)) {
-                                    if (workingItems != null && workingItems.contains(stack))
+                                    if (workingItems != null && !workingItems.contains(stack.hashIgnoreAmount()))
                                         continue;
                                     filtered.add(stack.copy().setting(EntryStack.Settings.RENDER_COUNTS, EntryStack.Settings.FALSE).setting(EntryStack.Settings.Item.RENDER_ENCHANTMENT_GLINT, RENDER_ENCHANTMENT_GLINT));
                                 }

+ 10 - 7
src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java

@@ -24,6 +24,7 @@
 package me.shedaniel.rei.gui.widget;
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import me.shedaniel.clothconfig2.ClothConfigInitializer;
 import me.shedaniel.clothconfig2.api.ScissorsHandler;
 import me.shedaniel.clothconfig2.api.ScrollingContainer;
@@ -47,7 +48,9 @@ import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.*;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
 
 import static me.shedaniel.rei.gui.widget.EntryListWidget.*;
 
@@ -187,12 +190,12 @@ public class FavoritesListWidget extends WidgetWithBounds {
             if (ConfigObject.getInstance().doSearchFavorites()) {
                 List<EntryStack> list = Lists.newArrayList();
                 boolean checkCraftable = ConfigManager.getInstance().isCraftableOnlyEnabled() && !ScreenHelper.inventoryStacks.isEmpty();
-                Set<EntryStack> workingItems = checkCraftable ? new TreeSet<>(Comparator.comparing(EntryStack::hashIgnoreAmount)) : null;
+                Set<Integer> workingItems = checkCraftable ? Sets.newHashSet() : null;
                 if (checkCraftable)
-                    workingItems.addAll(RecipeHelper.getInstance().findCraftableEntriesByItems(CollectionUtils.map(ScreenHelper.inventoryStacks, EntryStack::create)));
+                    workingItems.addAll(CollectionUtils.map(RecipeHelper.getInstance().findCraftableEntriesByItems(CollectionUtils.map(ScreenHelper.inventoryStacks, EntryStack::create)), EntryStack::hashIgnoreAmount));
                 for (EntryStack stack : ConfigObject.getInstance().getFavorites()) {
                     if (listWidget.canLastSearchTermsBeAppliedTo(stack)) {
-                        if (checkCraftable && workingItems.contains(stack))
+                        if (checkCraftable && !workingItems.contains(stack.hashIgnoreAmount()))
                             continue;
                         list.add(stack.copy().setting(EntryStack.Settings.RENDER_COUNTS, EntryStack.Settings.FALSE).setting(EntryStack.Settings.Item.RENDER_ENCHANTMENT_GLINT, RENDER_ENCHANTMENT_GLINT));
                     }
@@ -208,11 +211,11 @@ public class FavoritesListWidget extends WidgetWithBounds {
             } else {
                 List<EntryStack> list = Lists.newArrayList();
                 boolean checkCraftable = ConfigManager.getInstance().isCraftableOnlyEnabled() && !ScreenHelper.inventoryStacks.isEmpty();
-                Set<EntryStack> workingItems = checkCraftable ? new TreeSet<>(Comparator.comparing(EntryStack::hashIgnoreAmount)) : null;
+                Set<Integer> workingItems = checkCraftable ? Sets.newHashSet() : null;
                 if (checkCraftable)
-                    workingItems.addAll(RecipeHelper.getInstance().findCraftableEntriesByItems(CollectionUtils.map(ScreenHelper.inventoryStacks, EntryStack::create)));
+                    workingItems.addAll(CollectionUtils.map(RecipeHelper.getInstance().findCraftableEntriesByItems(CollectionUtils.map(ScreenHelper.inventoryStacks, EntryStack::create)), EntryStack::hashIgnoreAmount));
                 for (EntryStack stack : ConfigObject.getInstance().getFavorites()) {
-                    if (checkCraftable && workingItems.contains(stack))
+                    if (checkCraftable && !workingItems.contains(stack.hashIgnoreAmount()))
                         continue;
                     list.add(stack.copy().setting(EntryStack.Settings.RENDER_COUNTS, EntryStack.Settings.FALSE).setting(EntryStack.Settings.Item.RENDER_ENCHANTMENT_GLINT, RENDER_ENCHANTMENT_GLINT));
                 }

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/DefaultAutoCraftingPlugin.java

@@ -28,8 +28,11 @@ import me.shedaniel.rei.api.RecipeHelper;
 import me.shedaniel.rei.api.plugins.REIPluginV0;
 import me.shedaniel.rei.plugin.autocrafting.DefaultCategoryHandler;
 import me.shedaniel.rei.plugin.autocrafting.DefaultRecipeBookHandler;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.util.Identifier;
 
+@Environment(EnvType.CLIENT)
 public class DefaultAutoCraftingPlugin implements REIPluginV0 {
     
     public static final Identifier PLUGIN = new Identifier("roughlyenoughitems", "default_auto_crafting_plugin");

+ 14 - 17
src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java

@@ -230,21 +230,19 @@ public class DefaultPlugin implements REIPluginV0 {
             recipeHelper.registerDisplay(new DefaultFuelDisplay(EntryStack.create(entry.getKey()), entry.getValue()));
         }
         List<EntryStack> arrowStack = Collections.singletonList(EntryStack.create(Items.ARROW));
-        for (EntryStack entry : EntryRegistry.getInstance().getStacksList()) {
-            if (entry.getItem() == Items.LINGERING_POTION) {
-                List<List<EntryStack>> input = new ArrayList<>();
-                for (int i = 0; i < 4; i++)
-                    input.add(arrowStack);
-                input.add(Collections.singletonList(EntryStack.create(entry.getItemStack())));
-                for (int i = 0; i < 4; i++)
-                    input.add(arrowStack);
-                ItemStack outputStack = new ItemStack(Items.TIPPED_ARROW, 8);
-                PotionUtil.setPotion(outputStack, PotionUtil.getPotion(entry.getItemStack()));
-                PotionUtil.setCustomPotionEffects(outputStack, PotionUtil.getCustomPotionEffects(entry.getItemStack()));
-                List<EntryStack> output = Collections.singletonList(EntryStack.create(outputStack).addSetting(EntryStack.Settings.CHECK_TAGS, EntryStack.Settings.TRUE));
-                recipeHelper.registerDisplay(new DefaultCustomDisplay(null, input, output));
-            }
-        }
+        EntryRegistry.getInstance().getEntryStacks().filter(entry -> entry.getItem() == Items.LINGERING_POTION).forEach(entry -> {
+            List<List<EntryStack>> input = new ArrayList<>();
+            for (int i = 0; i < 4; i++)
+                input.add(arrowStack);
+            input.add(Collections.singletonList(EntryStack.create(entry.getItemStack())));
+            for (int i = 0; i < 4; i++)
+                input.add(arrowStack);
+            ItemStack outputStack = new ItemStack(Items.TIPPED_ARROW, 8);
+            PotionUtil.setPotion(outputStack, PotionUtil.getPotion(entry.getItemStack()));
+            PotionUtil.setCustomPotionEffects(outputStack, PotionUtil.getCustomPotionEffects(entry.getItemStack()));
+            List<EntryStack> output = Collections.singletonList(EntryStack.create(outputStack).addSetting(EntryStack.Settings.CHECK_TAGS, EntryStack.Settings.TRUE));
+            recipeHelper.registerDisplay(new DefaultCustomDisplay(null, input, output));
+        });
         Map<ItemConvertible, Float> map = Maps.newLinkedHashMap();
         if (ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.isEmpty())
             ComposterBlock.registerDefaultCompostableItems();
@@ -274,8 +272,7 @@ public class DefaultPlugin implements REIPluginV0 {
         // TODO Turn this into an API
         // Sit tight! This will be a fast journey!
         long time = System.currentTimeMillis();
-        for (EntryStack stack : EntryRegistry.getInstance().getStacksList())
-            applyPotionTransformer(stack);
+        EntryRegistry.getInstance().getEntryStacks().forEach(this::applyPotionTransformer);
         for (List<RecipeDisplay> displays : RecipeHelper.getInstance().getAllRecipesNoHandlers().values()) {
             for (RecipeDisplay display : displays) {
                 for (List<EntryStack> entries : display.getInputEntries())

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/DefaultPotionEffectExclusionZones.java

@@ -26,6 +26,8 @@ package me.shedaniel.rei.plugin;
 import com.google.common.collect.Ordering;
 import me.shedaniel.math.Rectangle;
 import me.shedaniel.rei.api.REIHelper;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen;
 import net.minecraft.client.gui.screen.ingame.ContainerScreen;
@@ -37,6 +39,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.function.Supplier;
 
+@Environment(EnvType.CLIENT)
 public class DefaultPotionEffectExclusionZones implements Supplier<List<Rectangle>> {
     @Override
     public List<Rectangle> get() {

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/DefaultRecipeBookExclusionZones.java

@@ -26,6 +26,8 @@ package me.shedaniel.rei.plugin;
 import com.google.common.collect.Lists;
 import me.shedaniel.math.Rectangle;
 import me.shedaniel.rei.api.REIHelper;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.screen.ingame.ContainerScreen;
 import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider;
@@ -36,6 +38,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.function.Supplier;
 
+@Environment(EnvType.CLIENT)
 public class DefaultRecipeBookExclusionZones implements Supplier<List<Rectangle>> {
     
     @Override

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java

@@ -32,6 +32,8 @@ import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.TransferRecipeDisplay;
 import me.shedaniel.rei.server.ContainerInfo;
 import me.shedaniel.rei.server.ContainerInfoHandler;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.screen.Screen;
@@ -45,6 +47,7 @@ import net.minecraft.util.collection.DefaultedList;
 
 import java.util.List;
 
+@Environment(EnvType.CLIENT)
 public class DefaultCategoryHandler implements AutoTransferHandler {
     
     public static boolean canUseMovePackets() {

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultRecipeBookHandler.java

@@ -29,6 +29,8 @@ import me.shedaniel.rei.api.TransferRecipeDisplay;
 import me.shedaniel.rei.impl.ScreenHelper;
 import me.shedaniel.rei.plugin.cooking.DefaultCookingDisplay;
 import me.shedaniel.rei.plugin.crafting.DefaultCraftingDisplay;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.client.gui.screen.Screen;
 import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider;
 import net.minecraft.client.resource.language.I18n;
@@ -37,6 +39,7 @@ import net.minecraft.container.CraftingTableContainer;
 import net.minecraft.container.PlayerContainer;
 import net.minecraft.recipe.Recipe;
 
+@Environment(EnvType.CLIENT)
 public class DefaultRecipeBookHandler implements AutoTransferHandler {
     @Override
     public Result handle(Context context) {

+ 4 - 2
src/main/java/me/shedaniel/rei/plugin/beacon/DefaultBeaconBaseDisplay.java

@@ -26,19 +26,21 @@ package me.shedaniel.rei.plugin.beacon;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
-import me.shedaniel.rei.utils.CollectionUtils;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.item.ItemStack;
 import net.minecraft.util.Identifier;
 
 import java.util.Collections;
 import java.util.List;
 
+@Environment(EnvType.CLIENT)
 public class DefaultBeaconBaseDisplay implements RecipeDisplay {
     
     private List<EntryStack> entries;
     
     public DefaultBeaconBaseDisplay(List<ItemStack> entries) {
-        this.entries = CollectionUtils.map(entries, EntryStack::create);
+        this.entries = EntryStack.ofItemStacks(entries);
     }
     
     @Override

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/blasting/DefaultBlastingDisplay.java

@@ -25,9 +25,12 @@ package me.shedaniel.rei.plugin.blasting;
 
 import me.shedaniel.rei.plugin.DefaultPlugin;
 import me.shedaniel.rei.plugin.cooking.DefaultCookingDisplay;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.recipe.BlastingRecipe;
 import net.minecraft.util.Identifier;
 
+@Environment(EnvType.CLIENT)
 public class DefaultBlastingDisplay extends DefaultCookingDisplay {
     
     public DefaultBlastingDisplay(BlastingRecipe recipe) {

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

@@ -27,6 +27,8 @@ import com.google.common.collect.Lists;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.Ingredient;
 import net.minecraft.text.TranslatableText;
@@ -37,6 +39,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+@Environment(EnvType.CLIENT)
 public class DefaultBrewingDisplay implements RecipeDisplay {
     
     private EntryStack input, output;
@@ -44,8 +47,9 @@ public class DefaultBrewingDisplay implements RecipeDisplay {
     
     public DefaultBrewingDisplay(ItemStack input, Ingredient reactant, ItemStack output) {
         this.input = EntryStack.create(input).setting(EntryStack.Settings.TOOLTIP_APPEND_EXTRA, stack -> Collections.singletonList(new TranslatableText("category.rei.brewing.input").formatted(Formatting.YELLOW)));
-        this.reactant = new ArrayList<>();
-        for (ItemStack stack : reactant.getMatchingStacksClient()) {
+        ItemStack[] reactantStacks = reactant.getMatchingStacksClient();
+        this.reactant = new ArrayList<>(reactantStacks.length);
+        for (ItemStack stack : reactantStacks) {
             EntryStack entryStack = EntryStack.create(stack);
             entryStack.setting(EntryStack.Settings.TOOLTIP_APPEND_EXTRA, s -> Collections.singletonList(new TranslatableText("category.rei.brewing.reactant").formatted(Formatting.YELLOW)));
             this.reactant.add(entryStack);

+ 4 - 1
src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireDisplay.java

@@ -26,6 +26,8 @@ package me.shedaniel.rei.plugin.campfire;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.AbstractCookingRecipe;
 import net.minecraft.recipe.CampfireCookingRecipe;
@@ -39,6 +41,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
+@Environment(EnvType.CLIENT)
 public class DefaultCampfireDisplay implements RecipeDisplay {
     
     private List<List<EntryStack>> inputs;
@@ -52,7 +55,7 @@ public class DefaultCampfireDisplay implements RecipeDisplay {
     }
     
     public DefaultCampfireDisplay(DefaultedList<Ingredient> ingredients, ItemStack output, int cookTime) {
-        this.inputs = EntryStack.create(ingredients);
+        this.inputs = EntryStack.ofIngredients(ingredients);
         this.output = Collections.singletonList(EntryStack.create(output));
         this.cookTime = cookTime;
     }

+ 6 - 4
src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingDisplay.java

@@ -26,13 +26,15 @@ package me.shedaniel.rei.plugin.composting;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.item.ItemConvertible;
 import net.minecraft.item.ItemStack;
 import net.minecraft.util.Identifier;
 
 import java.util.*;
-import java.util.stream.Collectors;
 
+@Environment(EnvType.CLIENT)
 public class DefaultCompostingDisplay implements RecipeDisplay {
     
     private List<EntryStack> order, allItems;
@@ -42,10 +44,10 @@ public class DefaultCompostingDisplay implements RecipeDisplay {
     
     public DefaultCompostingDisplay(int page, List<ItemConvertible> order, Map<ItemConvertible, Float> inputMap, List<ItemConvertible> allItems, ItemStack[] output) {
         this.page = page;
-        this.order = order.stream().map(EntryStack::create).collect(Collectors.toList());
+        this.order = EntryStack.ofItems(order);
         this.inputMap = inputMap;
-        this.output = Arrays.stream(output).map(EntryStack::create).collect(Collectors.toList());
-        this.allItems = allItems.stream().map(EntryStack::create).collect(Collectors.toList());
+        this.output = EntryStack.ofItemStacks(Arrays.asList(output));
+        this.allItems = EntryStack.ofItems(allItems);
     }
     
     public int getPage() {

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

@@ -26,7 +26,8 @@ package me.shedaniel.rei.plugin.cooking;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.TransferRecipeDisplay;
 import me.shedaniel.rei.server.ContainerInfo;
-import me.shedaniel.rei.utils.CollectionUtils;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.block.entity.FurnaceBlockEntity;
 import net.minecraft.container.Container;
 import net.minecraft.item.Item;
@@ -41,6 +42,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
+@Environment(EnvType.CLIENT)
 public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
     private static List<EntryStack> fuel;
     
@@ -56,7 +58,7 @@ public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
     
     public DefaultCookingDisplay(AbstractCookingRecipe recipe) {
         this.recipe = recipe;
-        this.input = EntryStack.create(recipe.getPreviewInputs());
+        this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
         this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
         this.xp = recipe.getExperience();
         this.cookTime = recipe.getCookTime();

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingDisplay.java

@@ -28,6 +28,8 @@ import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.TransferRecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
 import me.shedaniel.rei.server.ContainerInfo;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.container.Container;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.util.Identifier;
@@ -36,6 +38,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
+@Environment(EnvType.CLIENT)
 public interface DefaultCraftingDisplay extends TransferRecipeDisplay {
     
     @Override

+ 4 - 1
src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCustomDisplay.java

@@ -26,6 +26,8 @@ package me.shedaniel.rei.plugin.crafting;
 import com.google.common.collect.Lists;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.utils.CollectionUtils;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.util.Identifier;
@@ -33,6 +35,7 @@ import net.minecraft.util.Identifier;
 import java.util.List;
 import java.util.Optional;
 
+@Environment(EnvType.CLIENT)
 public class DefaultCustomDisplay implements DefaultCraftingDisplay {
     
     private List<List<EntryStack>> input;
@@ -41,7 +44,7 @@ public class DefaultCustomDisplay implements DefaultCraftingDisplay {
     private int width, height;
     
     public DefaultCustomDisplay(List<List<ItemStack>> input, List<ItemStack> output, Recipe<?> possibleRecipe) {
-        this(possibleRecipe, CollectionUtils.map(input, i -> CollectionUtils.map(i, EntryStack::create)), CollectionUtils.map(output, EntryStack::create));
+        this(possibleRecipe, CollectionUtils.map(input, EntryStack::ofItemStacks), EntryStack.ofItemStacks(output));
     }
     
     public DefaultCustomDisplay(Recipe<?> possibleRecipe, List<List<EntryStack>> input, List<EntryStack> output) {

+ 4 - 1
src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapedDisplay.java

@@ -24,6 +24,8 @@
 package me.shedaniel.rei.plugin.crafting;
 
 import me.shedaniel.rei.api.EntryStack;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.recipe.ShapedRecipe;
@@ -35,6 +37,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
+@Environment(EnvType.CLIENT)
 public class DefaultShapedDisplay implements DefaultCraftingDisplay {
     
     private ShapedRecipe display;
@@ -43,7 +46,7 @@ public class DefaultShapedDisplay implements DefaultCraftingDisplay {
     
     public DefaultShapedDisplay(ShapedRecipe recipe) {
         this.display = recipe;
-        this.input = EntryStack.create(recipe.getPreviewInputs());
+        this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
         this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
     }
     

+ 4 - 4
src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapelessDisplay.java

@@ -24,17 +24,17 @@
 package me.shedaniel.rei.plugin.crafting;
 
 import me.shedaniel.rei.api.EntryStack;
-import net.minecraft.item.ItemStack;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.recipe.ShapelessRecipe;
 import net.minecraft.util.Identifier;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
-import java.util.stream.Collectors;
 
+@Environment(EnvType.CLIENT)
 public class DefaultShapelessDisplay implements DefaultCraftingDisplay {
     
     private ShapelessRecipe display;
@@ -43,7 +43,7 @@ public class DefaultShapelessDisplay implements DefaultCraftingDisplay {
     
     public DefaultShapelessDisplay(ShapelessRecipe recipe) {
         this.display = recipe;
-        this.input = EntryStack.create(recipe.getPreviewInputs());
+        this.input = EntryStack.ofIngredients(recipe.getPreviewInputs());
         this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
     }
     

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/fuel/DefaultFuelDisplay.java

@@ -26,11 +26,14 @@ package me.shedaniel.rei.plugin.fuel;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.util.Identifier;
 
 import java.util.Collections;
 import java.util.List;
 
+@Environment(EnvType.CLIENT)
 public class DefaultFuelDisplay implements RecipeDisplay {
     private EntryStack fuel;
     private int fuelTime;

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/information/DefaultInformationDisplay.java

@@ -27,6 +27,8 @@ import com.google.common.collect.Lists;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.text.Text;
 import net.minecraft.util.Identifier;
 
@@ -35,6 +37,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
+@Environment(EnvType.CLIENT)
 public class DefaultInformationDisplay implements RecipeDisplay {
     private List<EntryStack> entryStacks;
     private List<Text> texts;

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/smelting/DefaultSmeltingDisplay.java

@@ -25,9 +25,12 @@ package me.shedaniel.rei.plugin.smelting;
 
 import me.shedaniel.rei.plugin.DefaultPlugin;
 import me.shedaniel.rei.plugin.cooking.DefaultCookingDisplay;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.recipe.SmeltingRecipe;
 import net.minecraft.util.Identifier;
 
+@Environment(EnvType.CLIENT)
 public class DefaultSmeltingDisplay extends DefaultCookingDisplay {
     
     public DefaultSmeltingDisplay(SmeltingRecipe recipe) {

+ 10 - 3
src/main/java/me/shedaniel/rei/plugin/smithing/DefaultSmithingDisplay.java

@@ -27,7 +27,8 @@ import com.google.common.collect.Lists;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
-import me.shedaniel.rei.utils.CollectionUtils;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.recipe.SmithingRecipe;
 import net.minecraft.util.Identifier;
 import org.jetbrains.annotations.NotNull;
@@ -37,6 +38,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
+@Environment(EnvType.CLIENT)
 public class DefaultSmithingDisplay implements RecipeDisplay {
     @NotNull
     private List<List<EntryStack>> input;
@@ -48,8 +50,8 @@ public class DefaultSmithingDisplay implements RecipeDisplay {
     public DefaultSmithingDisplay(@NotNull SmithingRecipe recipe) {
         this(
                 Lists.newArrayList(
-                        EntryStack.create(recipe.base),
-                        EntryStack.create(recipe.addition)
+                        EntryStack.ofIngredient(recipe.base),
+                        EntryStack.ofIngredient(recipe.addition)
                 ),
                 Collections.singletonList(EntryStack.create(recipe.getOutput())),
                 recipe.getId()
@@ -73,6 +75,11 @@ public class DefaultSmithingDisplay implements RecipeDisplay {
         return output;
     }
     
+    @Override
+    public List<List<EntryStack>> getRequiredEntries() {
+        return getInputEntries();
+    }
+    
     @Override
     public Identifier getRecipeCategory() {
         return DefaultPlugin.SMITHING;

+ 4 - 3
src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingDisplay.java

@@ -26,6 +26,8 @@ package me.shedaniel.rei.plugin.stonecutting;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.CuttingRecipe;
 import net.minecraft.recipe.Ingredient;
@@ -33,12 +35,11 @@ import net.minecraft.recipe.StonecuttingRecipe;
 import net.minecraft.util.Identifier;
 import net.minecraft.util.collection.DefaultedList;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
-import java.util.stream.Collectors;
 
+@Environment(EnvType.CLIENT)
 public class DefaultStoneCuttingDisplay implements RecipeDisplay {
     
     private List<List<EntryStack>> inputs;
@@ -51,7 +52,7 @@ public class DefaultStoneCuttingDisplay implements RecipeDisplay {
     }
     
     public DefaultStoneCuttingDisplay(DefaultedList<Ingredient> ingredients, ItemStack output) {
-        this.inputs = EntryStack.create(ingredients);
+        this.inputs = EntryStack.ofIngredients(ingredients);
         this.output = Collections.singletonList(EntryStack.create(output));
     }
     

+ 3 - 0
src/main/java/me/shedaniel/rei/plugin/stripping/DefaultStrippingDisplay.java

@@ -26,12 +26,15 @@ package me.shedaniel.rei.plugin.stripping;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.minecraft.item.ItemStack;
 import net.minecraft.util.Identifier;
 
 import java.util.Collections;
 import java.util.List;
 
+@Environment(EnvType.CLIENT)
 public class DefaultStrippingDisplay implements RecipeDisplay {
     private EntryStack in, out;
     

+ 3 - 3
src/main/java/me/shedaniel/rei/utils/CollectionUtils.java

@@ -142,7 +142,7 @@ public class CollectionUtils {
     }
     
     public static <T, R> List<R> map(List<T> list, Function<T, R> function) {
-        List<R> l = Lists.newArrayList();
+        List<R> l = new ArrayList<>(list.size());
         for (T t : list) {
             l.add(function.apply(t));
         }
@@ -150,7 +150,7 @@ public class CollectionUtils {
     }
     
     public static <T, R> List<R> map(Collection<T> list, Function<T, R> function) {
-        List<R> l = Lists.newArrayList();
+        List<R> l = new ArrayList<>(list.size());
         for (T t : list) {
             l.add(function.apply(t));
         }
@@ -158,7 +158,7 @@ public class CollectionUtils {
     }
     
     public static <T, R> List<R> map(T[] list, Function<T, R> function) {
-        List<R> l = Lists.newArrayList();
+        List<R> l = new ArrayList<>(list.length);
         for (T t : list) {
             l.add(function.apply(t));
         }