Danielshe 5 лет назад
Родитель
Сommit
e751eb9aa5
57 измененных файлов с 405 добавлено и 1491 удалено
  1. 2 2
      gradle.properties
  2. 0 52
      src/main/java/me/shedaniel/rei/api/Entry.java
  3. 6 62
      src/main/java/me/shedaniel/rei/api/EntryRegistry.java
  4. 1 6
      src/main/java/me/shedaniel/rei/api/EntryStack.java
  5. 5 12
      src/main/java/me/shedaniel/rei/api/RecipeCategory.java
  6. 2 63
      src/main/java/me/shedaniel/rei/api/RecipeDisplay.java
  7. 6 36
      src/main/java/me/shedaniel/rei/api/RecipeHelper.java
  8. 0 211
      src/main/java/me/shedaniel/rei/api/Renderer.java
  9. 1 22
      src/main/java/me/shedaniel/rei/api/TransferRecipeDisplay.java
  10. 4 4
      src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java
  11. 4 5
      src/main/java/me/shedaniel/rei/gui/RecipeViewingScreen.java
  12. 78 47
      src/main/java/me/shedaniel/rei/gui/VillagerRecipeViewingScreen.java
  13. 117 0
      src/main/java/me/shedaniel/rei/gui/entries/RecipeEntry.java
  14. 0 23
      src/main/java/me/shedaniel/rei/gui/renderers/EmptyRenderer.java
  15. 0 122
      src/main/java/me/shedaniel/rei/gui/renderers/FluidRenderer.java
  16. 0 106
      src/main/java/me/shedaniel/rei/gui/renderers/ItemStackRenderer.java
  17. 0 18
      src/main/java/me/shedaniel/rei/gui/renderers/RecipeRenderer.java
  18. 40 58
      src/main/java/me/shedaniel/rei/gui/renderers/SimpleRecipeEntry.java
  19. 0 1
      src/main/java/me/shedaniel/rei/gui/toast/CopyRecipeIdentifierToast.java
  20. 0 1
      src/main/java/me/shedaniel/rei/gui/widget/ButtonWidget.java
  21. 10 4
      src/main/java/me/shedaniel/rei/gui/widget/ClickableLabelWidget.java
  22. 1 1
      src/main/java/me/shedaniel/rei/gui/widget/CraftableToggleButtonWidget.java
  23. 0 48
      src/main/java/me/shedaniel/rei/gui/widget/DetailedButtonWidget.java
  24. 7 15
      src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java
  25. 15 14
      src/main/java/me/shedaniel/rei/gui/widget/EntryWidget.java
  26. 5 0
      src/main/java/me/shedaniel/rei/gui/widget/LabelWidget.java
  27. 2 9
      src/main/java/me/shedaniel/rei/gui/widget/PanelWidget.java
  28. 1 1
      src/main/java/me/shedaniel/rei/gui/widget/RecipeArrowWidget.java
  29. 0 8
      src/main/java/me/shedaniel/rei/gui/widget/RecipeBaseWidget.java
  30. 0 318
      src/main/java/me/shedaniel/rei/gui/widget/SlotWidget.java
  31. 1 1
      src/main/java/me/shedaniel/rei/gui/widget/TabWidget.java
  32. 2 2
      src/main/java/me/shedaniel/rei/gui/widget/Widget.java
  33. 2 2
      src/main/java/me/shedaniel/rei/impl/AbstractEntryStack.java
  34. 1 0
      src/main/java/me/shedaniel/rei/impl/BaseBoundsHandlerImpl.java
  35. 0 6
      src/main/java/me/shedaniel/rei/impl/EmptyEntryStack.java
  36. 0 53
      src/main/java/me/shedaniel/rei/impl/FluidEntry.java
  37. 0 6
      src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java
  38. 6 13
      src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java
  39. 0 53
      src/main/java/me/shedaniel/rei/impl/ItemStackEntry.java
  40. 9 11
      src/main/java/me/shedaniel/rei/impl/RecipeHelperImpl.java
  41. 1 1
      src/main/java/me/shedaniel/rei/mixin/MixinBrewingRecipeRegistry.java
  42. 8 8
      src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java
  43. 3 30
      src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultRecipeBookHandler.java
  44. 1 1
      src/main/java/me/shedaniel/rei/plugin/brewing/DefaultBrewingCategory.java
  45. 1 1
      src/main/java/me/shedaniel/rei/plugin/brewing/DefaultBrewingDisplay.java
  46. 1 1
      src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireCategory.java
  47. 1 1
      src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireDisplay.java
  48. 14 6
      src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingCategory.java
  49. 9 8
      src/main/java/me/shedaniel/rei/plugin/cooking/DefaultCookingCategory.java
  50. 9 4
      src/main/java/me/shedaniel/rei/plugin/cooking/DefaultCookingDisplay.java
  51. 3 7
      src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingCategory.java
  52. 1 1
      src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapedDisplay.java
  53. 1 1
      src/main/java/me/shedaniel/rei/plugin/crafting/DefaultShapelessDisplay.java
  54. 1 3
      src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingCategory.java
  55. 1 1
      src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingDisplay.java
  56. 1 1
      src/main/java/me/shedaniel/rei/plugin/stripping/DefaultStrippingCategory.java
  57. 21 0
      src/main/java/me/shedaniel/rei/utils/CollectionUtils.java

+ 2 - 2
gradle.properties

@@ -1,10 +1,10 @@
-mod_version=3.2.1-unstable
+mod_version=3.2.2-unstable
 minecraft_version=19w44a
 yarn_version=19w44a+build.3
 fabricloader_version=0.6.3+build.168
 jankson_version=1.1.0
 cloth_events_version=1.0.1-unstable.201911010702
-cloth_config_version=2.3.1-unstable.201911010710
+cloth_config_version=2.3.3-unstable.201911020734
 modmenu_version=1.7.13-unstable.19w38b+build.5
 fabric_api=0.4.9+build.258-1.15
 

+ 0 - 52
src/main/java/me/shedaniel/rei/api/Entry.java

@@ -1,52 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.api;
-
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
-import me.shedaniel.rei.impl.FluidEntry;
-import me.shedaniel.rei.impl.ItemStackEntry;
-import net.minecraft.fluid.Fluid;
-import net.minecraft.item.ItemStack;
-
-import javax.annotation.Nullable;
-
-@Deprecated
-@ToBeRemoved
-public interface Entry extends Cloneable {
-    @SuppressWarnings("deprecation")
-    static Entry create(ItemStack itemStack) {
-        return new ItemStackEntry(itemStack);
-    }
-    
-    @SuppressWarnings("deprecation")
-    static Entry create(Fluid fluid) {
-        return new FluidEntry(fluid);
-    }
-    
-    Type getEntryType();
-    
-    @Nullable
-    ItemStack getItemStack();
-    
-    @Nullable
-    Fluid getFluid();
-    
-    Entry clone();
-    
-    default EntryStack toEntryStack() {
-        if (getEntryType() == Type.ITEM)
-            return EntryStack.create(getItemStack());
-        if (getEntryType() == Type.FLUID)
-            return EntryStack.create(getFluid());
-        return EntryStack.empty();
-    }
-    
-    boolean equalsEntry(Entry other, boolean checkTags);
-    
-    public static enum Type {
-        ITEM, FLUID
-    }
-}

+ 6 - 62
src/main/java/me/shedaniel/rei/api/EntryRegistry.java

@@ -5,27 +5,14 @@
 
 package me.shedaniel.rei.api;
 
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
 import me.shedaniel.rei.utils.CollectionUtils;
-import net.minecraft.fluid.Fluid;
 import net.minecraft.item.Item;
 import net.minecraft.item.ItemStack;
 
-import java.util.Collections;
 import java.util.List;
 
 public interface EntryRegistry {
     
-    /**
-     * Gets the current unmodifiable item list
-     *
-     * @return an unmodifiable item list
-     */
-    @Deprecated
-    default List<Entry> getEntryList() {
-        return Collections.unmodifiableList(getModifiableEntryList());
-    }
-    
     /**
      * Gets the current modifiable stacks list
      *
@@ -33,16 +20,6 @@ public interface EntryRegistry {
      */
     List<EntryStack> getStacksList();
     
-    /**
-     * Gets the current modifiable item list
-     *
-     * @return an modifiable item list
-     */
-    @Deprecated
-    default List<Entry> getModifiableEntryList() {
-        return CollectionUtils.map(getStacksList(), EntryStack::toEntry);
-    }
-    
     /**
      * Gets all possible stacks from an item
      *
@@ -51,39 +28,18 @@ public interface EntryRegistry {
      */
     ItemStack[] getAllStacksFromItem(Item item);
     
-    /**
-     * Registers an new stack to the item list
-     *
-     * @param afterItem the stack to put after
-     * @param stack     the stack to register
-     */
-    @Deprecated
-    default void registerItemStack(Item afterItem, ItemStack stack) {
-        registerEntryAfter(EntryStack.create(afterItem), EntryStack.create(stack));
-    }
-    
-    @Deprecated
-    default void registerFluid(Fluid fluid) {
-        registerEntry(EntryStack.create(fluid));
-    }
-    
     default void registerEntry(EntryStack stack) {
         registerEntryAfter(null, stack);
     }
     
+    /**
+     * Registers an new stack to the entry list
+     *
+     * @param afterEntry the stack to put after
+     * @param stack      the stack to register
+     */
     void registerEntryAfter(EntryStack afterEntry, EntryStack stack);
     
-    @ToBeRemoved
-    @Deprecated
-    default void registerItemStack(Item afterItem, ItemStack... stacks) {
-        EntryStack afterStack = EntryStack.create(afterItem);
-        for (int i = stacks.length - 1; i >= 0; i--) {
-            ItemStack stack = stacks[i];
-            if (stack != null && !stack.isEmpty())
-                registerEntryAfter(afterStack, EntryStack.create(stack));
-        }
-    }
-    
     /**
      * Registers multiple stacks to the item list
      *
@@ -98,12 +54,6 @@ public interface EntryRegistry {
         }
     }
     
-    @ToBeRemoved
-    @Deprecated
-    default void registerItemStack(ItemStack... stacks) {
-        registerItemStack(null, stacks);
-    }
-    
     /**
      * Registers multiple stacks to the item list
      *
@@ -113,12 +63,6 @@ public interface EntryRegistry {
         registerEntriesAfter(null, stacks);
     }
     
-    @ToBeRemoved
-    @Deprecated
-    default boolean alreadyContain(ItemStack stack) {
-        return alreadyContain(EntryStack.create(stack));
-    }
-    
     /**
      * Checks if a stack is already registered
      *

+ 1 - 6
src/main/java/me/shedaniel/rei/api/EntryStack.java

@@ -6,7 +6,6 @@
 package me.shedaniel.rei.api;
 
 import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
 import me.shedaniel.rei.gui.widget.QueuedTooltip;
 import me.shedaniel.rei.impl.EmptyEntryStack;
 import me.shedaniel.rei.impl.FluidEntryStack;
@@ -61,10 +60,6 @@ public interface EntryStack {
     
     boolean isEmpty();
     
-    @ToBeRemoved
-    @Deprecated
-    Entry toEntry();
-    
     EntryStack copy();
     
     Object getObject();
@@ -119,7 +114,7 @@ public interface EntryStack {
     void render(Rectangle bounds, int mouseX, int mouseY, float delta);
     
     public static enum Type {
-        ITEM, FLUID, EMPTY
+        ITEM, FLUID, EMPTY, RENDER
     }
     
     public static class Settings<T> {

+ 5 - 12
src/main/java/me/shedaniel/rei/api/RecipeCategory.java

@@ -6,9 +6,9 @@
 package me.shedaniel.rei.api;
 
 import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
 import me.shedaniel.rei.gui.RecipeViewingScreen;
-import me.shedaniel.rei.gui.renderers.RecipeRenderer;
+import me.shedaniel.rei.gui.entries.RecipeEntry;
+import me.shedaniel.rei.gui.renderers.SimpleRecipeEntry;
 import me.shedaniel.rei.gui.widget.CategoryBaseWidget;
 import me.shedaniel.rei.gui.widget.RecipeBaseWidget;
 import me.shedaniel.rei.gui.widget.Widget;
@@ -33,17 +33,10 @@ public interface RecipeCategory<T extends RecipeDisplay> {
     /**
      * Gets the renderer of the icon, allowing developers to render things other than items
      *
-     * @see RecipeCategory#getLogo()
      * @return the renderer of the icon
      */
-    @ToBeRemoved
-    @Deprecated
-    default Renderer getIcon() {
-        return Renderer.empty();
-    }
-    
     default EntryStack getLogo() {
-        return getIcon().getEntry();
+        return EntryStack.empty();
     }
     
     /**
@@ -60,8 +53,8 @@ public interface RecipeCategory<T extends RecipeDisplay> {
      * @return the recipe renderer
      */
     @SuppressWarnings("unchecked")
-    default RecipeRenderer getSimpleRenderer(T recipe) {
-        return Renderer.fromRecipeEntries(recipe::getInputEntries, recipe::getOutputEntries);
+    default RecipeEntry getSimpleRenderer(T recipe) {
+        return SimpleRecipeEntry.create(recipe::getInputEntries, recipe::getOutputEntries);
     }
     
     /**

+ 2 - 63
src/main/java/me/shedaniel/rei/api/RecipeDisplay.java

@@ -5,67 +5,23 @@
 
 package me.shedaniel.rei.api;
 
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
-import net.minecraft.item.ItemStack;
 import net.minecraft.util.Identifier;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
 public interface RecipeDisplay {
     
-    /**
-     * @return a list of items
-     * @see RecipeDisplay#getInputStacks()
-     */
-    @ToBeRemoved
-    @Deprecated
-    default List<List<ItemStack>> getInput() {
-        return Collections.emptyList();
-    }
-    
     /**
      * @return a list of inputs
      */
-    default List<List<EntryStack>> getInputEntries() {
-        List<List<ItemStack>> input = getInput();
-        if (input.isEmpty())
-            return Collections.emptyList();
-        List<List<EntryStack>> list = new ArrayList<>();
-        for (List<ItemStack> stacks : input) {
-            List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : stacks) {
-                entries.add(EntryStack.create(stack));
-            }
-            list.add(entries);
-        }
-        return list;
-    }
+    List<List<EntryStack>> getInputEntries();
     
     /**
      * @return a list of outputs
      */
-    @ToBeRemoved
-    @Deprecated
-    default List<ItemStack> getOutput() {
-        return Collections.emptyList();
-    }
-    
-    /**
-     * @return a list of outputs
-     */
-    default List<EntryStack> getOutputEntries() {
-        List<ItemStack> input = getOutput();
-        if (input.isEmpty())
-            return Collections.emptyList();
-        List<EntryStack> entries = new ArrayList<>();
-        for (ItemStack stack : input) {
-            entries.add(EntryStack.create(stack));
-        }
-        return entries;
-    }
+    List<EntryStack> getOutputEntries();
     
     /**
      * Gets the required items used in craftable filters
@@ -73,23 +29,6 @@ public interface RecipeDisplay {
      * @return the list of required items
      */
     default List<List<EntryStack>> getRequiredEntries() {
-        List<List<ItemStack>> input = getRequiredItems();
-        if (input.isEmpty())
-            return Collections.emptyList();
-        List<List<EntryStack>> list = new ArrayList<>();
-        for (List<ItemStack> stacks : input) {
-            List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : stacks) {
-                entries.add(EntryStack.create(stack));
-            }
-            list.add(entries);
-        }
-        return list;
-    }
-    
-    @ToBeRemoved
-    @Deprecated
-    default List<List<ItemStack>> getRequiredItems() {
         return Collections.emptyList();
     }
     

+ 6 - 36
src/main/java/me/shedaniel/rei/api/RecipeHelper.java

@@ -7,14 +7,11 @@ package me.shedaniel.rei.api;
 
 import me.shedaniel.math.api.Rectangle;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
 import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
-import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.recipe.RecipeManager;
 import net.minecraft.util.Identifier;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -46,28 +43,13 @@ public interface RecipeHelper {
      */
     List<Recipe> getAllSortedRecipes();
     
-    /**
-     * Gets all craftable items from materials.
-     *
-     * @param inventoryItems the materials
-     * @return the list of craftable items
-     */
-    default List<ItemStack> findCraftableByItems(List<ItemStack> inventoryItems) {
-        List<ItemStack> itemStacks = new ArrayList<>();
-        for (EntryStack item : findCraftableEntriesByItems(inventoryItems)) {
-            if (item.getItemStack() != null)
-                itemStacks.add(item.getItemStack());
-        }
-        return itemStacks;
-    }
-    
     /**
      * Gets all craftable items from materials.
      *
      * @param inventoryItems the materials
      * @return the list of craftable entries
      */
-    List<EntryStack> findCraftableEntriesByItems(List<ItemStack> inventoryItems);
+    List<EntryStack> findCraftableEntriesByItems(List<EntryStack> inventoryItems);
     
     /**
      * Registers a category
@@ -82,7 +64,7 @@ public interface RecipeHelper {
      * @param category        the category
      * @param workingStations the working stations
      */
-    void registerWorkingStations(Identifier category, List<ItemStack>... workingStations);
+    void registerWorkingStations(Identifier category, List<EntryStack>... workingStations);
     
     /**
      * Registers the working stations of a category
@@ -90,9 +72,9 @@ public interface RecipeHelper {
      * @param category        the category
      * @param workingStations the working stations
      */
-    void registerWorkingStations(Identifier category, ItemStack... workingStations);
+    void registerWorkingStations(Identifier category, EntryStack... workingStations);
     
-    List<List<ItemStack>> getWorkingStations(Identifier category);
+    List<List<EntryStack>> getWorkingStations(Identifier category);
     
     /**
      * Registers a recipe display
@@ -103,19 +85,13 @@ public interface RecipeHelper {
     void registerDisplay(Identifier categoryIdentifier, RecipeDisplay display);
     
     /**
-     * Gets a map of recipes for an itemstack
+     * Gets a map of recipes for an entry
      *
      * @param stack the stack to be crafted
      * @return the map of recipes
      */
     Map<RecipeCategory<?>, List<RecipeDisplay>> getRecipesFor(EntryStack stack);
     
-    @ToBeRemoved
-    @Deprecated
-    default Map<RecipeCategory<?>, List<RecipeDisplay>> getRecipesFor(ItemStack stack) {
-        return getRecipesFor(EntryStack.create(stack));
-    }
-    
     RecipeCategory getCategory(Identifier identifier);
     
     /**
@@ -133,19 +109,13 @@ public interface RecipeHelper {
     List<RecipeCategory> getAllCategories();
     
     /**
-     * Gets a map of usages for an itemstack
+     * Gets a map of usages for an entry
      *
      * @param stack the stack to be used
      * @return the map of recipes
      */
     Map<RecipeCategory<?>, List<RecipeDisplay>> getUsagesFor(EntryStack stack);
     
-    @ToBeRemoved
-    @Deprecated
-    default Map<RecipeCategory<?>, List<RecipeDisplay>> getUsagesFor(ItemStack stack) {
-        return getUsagesFor(EntryStack.create(stack));
-    }
-    
     /**
      * Gets the optional of the speed crafting button area from a category
      *

+ 0 - 211
src/main/java/me/shedaniel/rei/api/Renderer.java

@@ -1,211 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.api;
-
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
-import me.shedaniel.rei.gui.renderers.EmptyRenderer;
-import me.shedaniel.rei.gui.renderers.FluidRenderer;
-import me.shedaniel.rei.gui.renderers.ItemStackRenderer;
-import me.shedaniel.rei.gui.renderers.SimpleRecipeRenderer;
-import me.shedaniel.rei.gui.widget.QueuedTooltip;
-import net.minecraft.client.gui.DrawableHelper;
-import net.minecraft.fluid.Fluid;
-import net.minecraft.item.ItemStack;
-import net.minecraft.util.math.MathHelper;
-import org.jetbrains.annotations.NotNull;
-
-import javax.annotation.Nullable;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-
-@Deprecated
-public abstract class Renderer extends DrawableHelper {
-    /**
-     * Gets an item stack renderer by an item stack supplier
-     *
-     * @param supplier the supplier for getting the item stack
-     * @return the item stack renderer
-     */
-    public static ItemStackRenderer fromItemStackSupplier(Supplier<ItemStack> supplier) {
-        return fromItemStacks(() -> Collections.singletonList(supplier.get()), true, null);
-    }
-    
-    /**
-     * Gets an item stack renderer by an item stack supplier
-     *
-     * @param supplier the supplier for getting the item stack
-     * @return the item stack renderer
-     */
-    public static ItemStackRenderer fromItemStackSupplierNoCounts(Supplier<ItemStack> supplier) {
-        return fromItemStacks(() -> Collections.singletonList(supplier.get()), false, null);
-    }
-    
-    /**
-     * Gets an item stack renderer by an item stack
-     *
-     * @param stack the item stack to be displayed
-     * @return the item stack renderer
-     */
-    public static ItemStackRenderer fromItemStack(ItemStack stack) {
-        return fromItemStacks(() -> Collections.singletonList(stack), true, null);
-    }
-    
-    public static FluidRenderer fromFluid(Fluid fluid) {
-        return fromFluid(() -> fluid, null);
-    }
-    
-    public static FluidRenderer fromFluid(Supplier<Fluid> fluidSupplier, @Nullable Function<Fluid, List<String>> extraTooltipSupplier) {
-        return new FluidRenderer() {
-            @Override
-            public Fluid getFluid() {
-                return fluidSupplier.get();
-            }
-            
-            @Override
-            protected List<String> getExtraToolTips(Fluid fluid) {
-                if (extraTooltipSupplier == null)
-                    return super.getExtraToolTips(fluid);
-                List<String> apply = extraTooltipSupplier.apply(fluid);
-                if (apply == null)
-                    return super.getExtraToolTips(fluid);
-                return apply;
-            }
-        };
-    }
-    
-    /**
-     * Gets an item stack renderer by an item stack
-     *
-     * @param stack the item stack to be displayed
-     * @return the item stack renderer
-     */
-    public static ItemStackRenderer fromItemStackNoCounts(ItemStack stack) {
-        return fromItemStacks(() -> Collections.singletonList(stack), false, null);
-    }
-    
-    /**
-     * Gets an empty renderer
-     *
-     * @return an empty renderer
-     */
-    public static EmptyRenderer empty() {
-        return EmptyRenderer.INSTANCE;
-    }
-    
-    /**
-     * Gets a simple recipe renderer from inputs and outputs
-     *
-     * @param input  the list of input items
-     * @param output the list of output items
-     * @return the recipe renderer
-     */
-    @ToBeRemoved
-    @Deprecated
-    public static SimpleRecipeRenderer fromRecipe(Supplier<List<List<ItemStack>>> input, Supplier<List<ItemStack>> output) {
-        return new SimpleRecipeRenderer(input, output);
-    }
-    
-    public static SimpleRecipeRenderer fromRecipeEntries(Supplier<List<List<EntryStack>>> input, Supplier<List<EntryStack>> output) {
-        return new SimpleRecipeRenderer(input, output, 0);
-    }
-    
-    public static ItemStackRenderer fromItemStacks(List<ItemStack> stacks) {
-        return fromItemStacks(() -> stacks, true, null);
-    }
-    
-    public static ItemStackRenderer fromItemStacks(Supplier<List<ItemStack>> stacksSupplier, boolean renderCounts, @Nullable Function<ItemStack, List<String>> extraTooltipSupplier) {
-        return fromItemStacks(stacksSupplier, stack -> renderCounts ? null : "", extraTooltipSupplier);
-    }
-    
-    public static ItemStackRenderer fromItemStacks(Supplier<List<ItemStack>> stacksSupplier, @Nullable Function<ItemStack, String> countsFunction, @Nullable Function<ItemStack, List<String>> extraTooltipSupplier) {
-        return fromItemStacks(stacksSupplier, countsFunction, extraTooltipSupplier, true);
-    }
-    
-    public static ItemStackRenderer fromItemStacks(Supplier<List<ItemStack>> stacksSupplier, @Nullable Function<ItemStack, String> countsFunction, @Nullable Function<ItemStack, List<String>> extraTooltipSupplier, boolean renderOverlay) {
-        List<ItemStack> stacks = stacksSupplier.get().stream().map(ItemStack::copy).collect(Collectors.toList());
-        return new ItemStackRenderer() {
-            @Override
-            public ItemStack getItemStack() {
-                if (stacks.isEmpty())
-                    return ItemStack.EMPTY;
-                return stacks.get(MathHelper.floor((System.currentTimeMillis() / 500 % (double) stacks.size()) / 1f));
-            }
-            
-            @Override
-            protected String getCounts() {
-                return countsFunction == null ? null : countsFunction.apply(getItemStack());
-            }
-            
-            @Override
-            protected boolean renderOverlay() {
-                return renderOverlay;
-            }
-            
-            @Override
-            protected List<String> getExtraToolTips(ItemStack stack) {
-                if (extraTooltipSupplier == null)
-                    return super.getExtraToolTips(stack);
-                List<String> apply = extraTooltipSupplier.apply(stack);
-                if (apply == null)
-                    return super.getExtraToolTips(stack);
-                return apply;
-            }
-        };
-    }
-    
-    public static ItemStackRenderer fromItemStacksNoCounts(List<ItemStack> stacks) {
-        return fromItemStacks(() -> stacks, false, null);
-    }
-    
-    /**
-     * Gets the current blit offset
-     *
-     * @return the blit offset
-     */
-    @Override
-    public int getBlitOffset() {
-        return super.getBlitOffset();
-    }
-    
-    /**
-     * Sets the current blit offset
-     *
-     * @param offset the new blit offset
-     */
-    @Override
-    public void setBlitOffset(int offset) {
-        super.setBlitOffset(offset);
-    }
-    
-    /**
-     * Renders of the renderable
-     *
-     * @param x      the x coordinate of the renderable
-     * @param y      the y coordinate of the renderable
-     * @param mouseX the x coordinate of the mouse
-     * @param mouseY the y coordinate of the mouse
-     * @param delta  the delta
-     */
-    public abstract void render(int x, int y, double mouseX, double mouseY, float delta);
-    
-    public EntryStack getEntry() {
-        if (this instanceof ItemStackRenderer)
-            return EntryStack.create(((ItemStackRenderer) this).getItemStack());
-        if (this instanceof FluidRenderer)
-            return EntryStack.create(((FluidRenderer) this).getFluid());
-        return EntryStack.empty();
-    }
-    
-    @Nullable
-    public QueuedTooltip getQueuedTooltip(float delta) {
-        return null;
-    }
-    
-}

+ 1 - 22
src/main/java/me/shedaniel/rei/api/TransferRecipeDisplay.java

@@ -20,27 +20,6 @@ public interface TransferRecipeDisplay extends RecipeDisplay {
     
     int getHeight();
     
-    default List<List<ItemStack>> getOrganisedInput(ContainerInfo<Container> containerInfo, Container container) {
-        List<List<ItemStack>> list = Lists.newArrayListWithCapacity(containerInfo.getCraftingWidth(container) * containerInfo.getCraftingHeight(container));
-        for (int i = 0; i < containerInfo.getCraftingWidth(container) * containerInfo.getCraftingHeight(container); i++) {
-            list.add(Lists.newArrayList());
-        }
-        return list;
-    }
-    
-    default List<List<EntryStack>> getOrganisedInputEntries(ContainerInfo<Container> containerInfo, Container container) {
-        List<List<ItemStack>> input = getOrganisedInput(containerInfo, container);
-        if (input.isEmpty())
-            return Collections.emptyList();
-        List<List<EntryStack>> list = new ArrayList<>();
-        for (List<ItemStack> stacks : input) {
-            List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : stacks) {
-                entries.add(EntryStack.create(stack));
-            }
-            list.add(entries);
-        }
-        return list;
-    }
+    List<List<EntryStack>> getOrganisedInputEntries(ContainerInfo<Container> containerInfo, Container container);
     
 }

+ 4 - 4
src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java

@@ -5,7 +5,7 @@
 
 package me.shedaniel.rei.gui;
 
-import me.shedaniel.math.compat.RenderHelper;
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.rei.gui.widget.TextFieldWidget;
 import me.shedaniel.rei.impl.ScreenHelper;
 import net.minecraft.client.MinecraftClient;
@@ -29,11 +29,11 @@ public class OverlaySearchField extends TextFieldWidget {
     
     public void laterRender(int int_1, int int_2, float float_1) {
         GuiLighting.disable();
-        RenderHelper.disableDepthTest();
+        RenderSystem.disableDepthTest();
         setEditableColor(ContainerScreenOverlay.getEntryListWidget().children().isEmpty() && !getText().isEmpty() ? 16733525 : isSearching ? -1313241 : 14737632);
         setSuggestion(!isFocused() && getText().isEmpty() ? I18n.translate("text.rei.search.field.suggestion") : null);
         super.render(int_1, int_2, float_1);
-        RenderHelper.enableDepthTest();
+        RenderSystem.enableDepthTest();
     }
     
     @Override
@@ -76,7 +76,7 @@ public class OverlaySearchField extends TextFieldWidget {
     
     @Override
     public boolean charTyped(char char_1, int int_1) {
-        if (System.currentTimeMillis() - keybindFocusTime < 1000 && InputUtil.isKeyPressed(MinecraftClient.getInstance().window.getHandle(), keybindFocusKey)) {
+        if (System.currentTimeMillis() - keybindFocusTime < 1000 && InputUtil.isKeyPressed(MinecraftClient.getInstance().getWindow().getHandle(), keybindFocusKey)) {
             keybindFocusTime = -1;
             keybindFocusKey = -1;
             return true;

+ 4 - 5
src/main/java/me/shedaniel/rei/gui/RecipeViewingScreen.java

@@ -21,7 +21,6 @@ import net.minecraft.client.render.GuiLighting;
 import net.minecraft.client.resource.language.I18n;
 import net.minecraft.client.sound.PositionedSoundInstance;
 import net.minecraft.client.util.Window;
-import net.minecraft.item.ItemStack;
 import net.minecraft.sound.SoundEvents;
 import net.minecraft.text.LiteralText;
 import net.minecraft.text.TranslatableText;
@@ -125,7 +124,7 @@ public class RecipeViewingScreen extends Screen {
         this.largestWidth = width - 100;
         this.largestHeight = height - 40;
         int maxWidthDisplay = CollectionUtils.mapAndMax(getCurrentDisplayed(), display -> selectedCategory.getDisplayWidth((RecipeDisplay) display), (Comparator<Integer>) Comparator.naturalOrder()).orElse(150);
-        this.guiWidth = MathHelper.clamp(maxWidthDisplay, 0, largestWidth);
+        this.guiWidth = MathHelper.clamp(maxWidthDisplay + 30, 0, largestWidth);
         this.guiHeight = MathHelper.floor(MathHelper.clamp((selectedCategory.getDisplayHeight() + 7d) * (getRecipesPerPage() + 1d) + 40d, 186d, (double) largestHeight));
         this.bounds = new Rectangle(width / 2 - guiWidth / 2, height / 2 - guiHeight / 2, guiWidth, guiHeight);
         this.page = MathHelper.clamp(page, 0, getTotalPages(selectedCategory) - 1);
@@ -295,7 +294,7 @@ public class RecipeViewingScreen extends Screen {
         else
             recipeChoosePageWidget = null;
         
-        List<List<ItemStack>> workingStations = RoughlyEnoughItemsCore.getRecipeHelper().getWorkingStations(selectedCategory.getIdentifier());
+        List<List<EntryStack>> workingStations = RoughlyEnoughItemsCore.getRecipeHelper().getWorkingStations(selectedCategory.getIdentifier());
         if (!workingStations.isEmpty()) {
             int hh = MathHelper.floor((bounds.height - 16) / 18f);
             int actualHeight = Math.min(hh, workingStations.size());
@@ -306,8 +305,8 @@ public class RecipeViewingScreen extends Screen {
             int index = 0;
             List<String> list = Collections.singletonList(Formatting.YELLOW.toString() + I18n.translate("text.rei.working_station"));
             xx += (innerWidth - 1) * 18;
-            for (List<ItemStack> workingStation : workingStations) {
-                preWidgets.add(new SlotWidget(xx, yy, Renderer.fromItemStacks(() -> workingStation, true, stack -> list), true, true, true));
+            for (List<EntryStack> workingStation : workingStations) {
+                preWidgets.add(EntryWidget.create(xx, yy).entries(CollectionUtils.map(workingStation, stack -> stack.copy().setting(EntryStack.Settings.TOOLTIP_APPEND_EXTRA, s -> list))));
                 index++;
                 yy += 18;
                 if (index >= hh) {

+ 78 - 47
src/main/java/me/shedaniel/rei/gui/VillagerRecipeViewingScreen.java

@@ -7,14 +7,16 @@ package me.shedaniel.rei.gui;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import me.shedaniel.clothconfig2.api.ScissorsHandler;
 import com.mojang.blaze3d.systems.RenderSystem;
-import me.shedaniel.math.api.Point;
+import me.shedaniel.clothconfig2.ClothConfigInitializer;
+import me.shedaniel.clothconfig2.api.ScissorsHandler;
+import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget.Interpolation;
+import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget.Precision;
 import me.shedaniel.math.api.Rectangle;
 import me.shedaniel.math.impl.PointHelper;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.*;
-import me.shedaniel.rei.gui.renderers.RecipeRenderer;
+import me.shedaniel.rei.gui.entries.RecipeEntry;
 import me.shedaniel.rei.gui.widget.*;
 import me.shedaniel.rei.impl.ScreenHelper;
 import me.shedaniel.rei.utils.CollectionUtils;
@@ -27,7 +29,6 @@ import net.minecraft.client.render.Tessellator;
 import net.minecraft.client.render.VertexFormats;
 import net.minecraft.client.resource.language.I18n;
 import net.minecraft.client.sound.PositionedSoundInstance;
-import net.minecraft.item.ItemStack;
 import net.minecraft.sound.SoundEvents;
 import net.minecraft.text.LiteralText;
 import net.minecraft.text.TranslatableText;
@@ -46,11 +47,14 @@ public class VillagerRecipeViewingScreen extends Screen {
     private final List<RecipeCategory<?>> categories;
     private final List<Widget> widgets;
     private final List<ButtonWidget> buttonWidgets;
-    private final List<Renderer> recipeRenderers;
+    private final List<RecipeEntry> recipeRenderers;
     private final List<TabWidget> tabs;
     public Rectangle bounds, scrollListBounds;
     private int selectedCategoryIndex, selectedRecipeIndex;
     private double scroll;
+    private double target;
+    private long start;
+    private long duration;
     private float scrollBarAlpha = 0;
     private float scrollBarAlphaFuture = 0;
     private long scrollBarAlphaFutureTime = -1;
@@ -97,7 +101,7 @@ public class VillagerRecipeViewingScreen extends Screen {
         int guiHeight = MathHelper.clamp(category.getDisplayHeight() + 40, 166, largestHeight);
         this.bounds = new Rectangle(width / 2 - guiWidth / 2, height / 2 - guiHeight / 2, guiWidth, guiHeight);
         
-        List<List<ItemStack>> workingStations = RoughlyEnoughItemsCore.getRecipeHelper().getWorkingStations(category.getIdentifier());
+        List<List<EntryStack>> workingStations = RoughlyEnoughItemsCore.getRecipeHelper().getWorkingStations(category.getIdentifier());
         if (!workingStations.isEmpty()) {
             int ww = MathHelper.floor((bounds.width - 16) / 18f);
             int w = Math.min(ww, workingStations.size());
@@ -107,8 +111,8 @@ public class VillagerRecipeViewingScreen extends Screen {
             widgets.add(new CategoryBaseWidget(new Rectangle(xx - 6, bounds.y + bounds.height - 5, 11 + w * 18, 15 + h * 18)));
             int index = 0;
             List<String> list = Collections.singletonList(Formatting.YELLOW.toString() + I18n.translate("text.rei.working_station"));
-            for (List<ItemStack> workingStation : workingStations) {
-                widgets.add(new SlotWidget(xx, yy, Renderer.fromItemStacks(() -> workingStation, true, stack -> list), true, true, true));
+            for (List<EntryStack> workingStation : workingStations) {
+                widgets.add(EntryWidget.create(xx, yy).entries(CollectionUtils.map(workingStation, stack -> stack.copy().setting(EntryStack.Settings.TOOLTIP_APPEND_EXTRA, s -> list))));
                 index++;
                 xx += 18;
                 if (index >= ww) {
@@ -133,9 +137,9 @@ public class VillagerRecipeViewingScreen extends Screen {
         int index = 0;
         for (RecipeDisplay recipeDisplay : categoryMap.get(category)) {
             int finalIndex = index;
-            RecipeRenderer recipeRenderer;
-            recipeRenderers.add(recipeRenderer = category.getSimpleRenderer(recipeDisplay));
-            buttonWidgets.add(new ButtonWidget(bounds.x + 5, 0, recipeRenderer.getWidth(), recipeRenderer.getHeight(), "") {
+            RecipeEntry recipeEntry;
+            recipeRenderers.add(recipeEntry = category.getSimpleRenderer(recipeDisplay));
+            buttonWidgets.add(new ButtonWidget(bounds.x + 5, 0, recipeEntry.getWidth(), recipeEntry.getHeight(), "") {
                 @Override
                 public void onPressed() {
                     selectedRecipeIndex = finalIndex;
@@ -220,22 +224,6 @@ public class VillagerRecipeViewingScreen extends Screen {
             public Optional<String> getTooltips() {
                 return Optional.ofNullable(I18n.translate("text.rei.view_all_categories"));
             }
-            
-            @Override
-            public void render(int mouseX, int mouseY, float delta) {
-                RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
-                font.draw((isHovered(mouseX, mouseY) ? Formatting.UNDERLINE.toString() : "") + text, x - font.getStringWidth(text) / 2, y, getDefaultColor());
-                if (clickable && getTooltips().isPresent())
-                    if (!focused && containsMouse(mouseX, mouseY))
-                        ScreenHelper.getLastOverlay().addTooltip(QueuedTooltip.create(getTooltips().get().split("\n")));
-                    else if (focused)
-                        ScreenHelper.getLastOverlay().addTooltip(QueuedTooltip.create(new Point(x, y), getTooltips().get().split("\n")));
-            }
-            
-            @Override
-            public int getDefaultColor() {
-                return ScreenHelper.isDarkModeEnabled() ? 0xFFBBBBBB : 4210752;
-            }
         });
         
         this.children.addAll(buttonWidgets);
@@ -245,9 +233,21 @@ public class VillagerRecipeViewingScreen extends Screen {
         ScreenHelper.getLastOverlay().init();
     }
     
+    private final double clamp(double v) {
+        return clamp(v, 200);
+    }
+    
+    private final double clamp(double v, double clampExtension) {
+        return MathHelper.clamp(v, -clampExtension, getMaxScroll() + clampExtension);
+    }
+    
+    private double getMaxScroll() {
+        return Math.max(0, this.getMaxScrollPosition() - (scrollListBounds.height - 2));
+    }
+    
     @Override
     public boolean mouseClicked(double mouseX, double mouseY, int int_1) {
-        double height = CollectionUtils.sumInt(buttonWidgets, b -> b.getBounds().getHeight());
+        double height = getMaxScrollPosition();
         int actualHeight = scrollListBounds.height - 2;
         if (height > actualHeight && scrollBarAlpha > 0 && mouseY >= scrollListBounds.y + 1 && mouseY <= scrollListBounds.getMaxY() - 1) {
             double scrollbarPositionMinX = scrollListBounds.getMaxX() - 6;
@@ -269,15 +269,29 @@ public class VillagerRecipeViewingScreen extends Screen {
         return super.charTyped(char_1, int_1);
     }
     
+    public void offset(double value, boolean animated) {
+        scrollTo(target + value, animated);
+    }
+    
+    public void scrollTo(double value, boolean animated) {
+        scrollTo(value, animated, ClothConfigInitializer.getScrollDuration());
+    }
+    
+    public void scrollTo(double value, boolean animated, long duration) {
+        target = clamp(value);
+        
+        if (animated) {
+            start = System.currentTimeMillis();
+            this.duration = duration;
+        } else
+            scroll = target;
+    }
+    
     @Override
     public boolean mouseScrolled(double double_1, double double_2, double double_3) {
         double height = CollectionUtils.sumInt(buttonWidgets, b -> b.getBounds().getHeight());
         if (scrollListBounds.contains(double_1, double_2) && height > scrollListBounds.height - 2) {
-            if (double_3 > 0)
-                scroll -= 16;
-            else
-                scroll += 16;
-            scroll = MathHelper.clamp(scroll, 0, height - scrollListBounds.height + 2);
+            offset(ClothConfigInitializer.getScrollStep() * -double_3, true);
             if (scrollBarAlphaFuture == 0)
                 scrollBarAlphaFuture = 1f;
             if (System.currentTimeMillis() - scrollBarAlphaFutureTime > 300f)
@@ -304,6 +318,10 @@ public class VillagerRecipeViewingScreen extends Screen {
         return super.mouseScrolled(double_1, double_2, double_3);
     }
     
+    private double getMaxScrollPosition() {
+        return CollectionUtils.sumInt(buttonWidgets, b -> b.getBounds().getHeight());
+    }
+    
     @Override
     public void render(int mouseX, int mouseY, float delta) {
         if (RoughlyEnoughItemsCore.getConfigManager().getConfig().doesVillagerScreenHavePermanentScrollBar()) {
@@ -328,6 +346,7 @@ public class VillagerRecipeViewingScreen extends Screen {
                     scrollBarAlpha = Math.max(Math.min(1f, l / 300f), scrollBarAlpha);
             }
         }
+        updatePosition(delta);
         this.fillGradient(0, 0, this.width, this.height, -1072689136, -804253680);
         int yOffset = 0;
         this.widgets.forEach(widget -> {
@@ -350,21 +369,20 @@ public class VillagerRecipeViewingScreen extends Screen {
         for (int i = 0; i < buttonWidgets.size(); i++) {
             if (buttonWidgets.get(i).getBounds().getMaxY() > scrollListBounds.getMinY() && buttonWidgets.get(i).getBounds().getMinY() < scrollListBounds.getMaxY()) {
                 GuiLighting.disable();
-                recipeRenderers.get(i).setBlitOffset(1);
-                recipeRenderers.get(i).render(buttonWidgets.get(i).getBounds().x, buttonWidgets.get(i).getBounds().y, mouseX, mouseY, delta);
-                ScreenHelper.getLastOverlay().addTooltip(recipeRenderers.get(i).getQueuedTooltip(delta));
+                recipeRenderers.get(i).setZ(1);
+                recipeRenderers.get(i).render(buttonWidgets.get(i).getBounds(), mouseX, mouseY, delta);
+                ScreenHelper.getLastOverlay().addTooltip(recipeRenderers.get(i).getTooltip(mouseX, mouseY));
             }
         }
-        double height = CollectionUtils.sumInt(buttonWidgets, b -> b.getBounds().getHeight());
-        if (height > scrollListBounds.height - 2) {
+        double maxScroll = getMaxScrollPosition();
+        if (maxScroll > scrollListBounds.height - 2) {
             Tessellator tessellator = Tessellator.getInstance();
             BufferBuilder buffer = tessellator.getBufferBuilder();
-            double maxScroll = height - scrollListBounds.height + 2;
-            int scrollBarHeight = MathHelper.floor((scrollListBounds.height - 2) * (scrollListBounds.height - 2) / maxScroll);
-            scrollBarHeight = MathHelper.clamp(scrollBarHeight, 32, scrollListBounds.height - 2 - 8);
-            int minY = (int) (scroll * (scrollListBounds.height - 2 - scrollBarHeight) / maxScroll) + scrollListBounds.y + 1;
-            if (minY < this.scrollListBounds.y + 1)
-                minY = this.scrollListBounds.y + 1;
+            int height = (int) (((scrollListBounds.height - 2) * (scrollListBounds.height - 2)) / this.getMaxScrollPosition());
+            height = MathHelper.clamp(height, 32, scrollListBounds.height - 2 - 8);
+            height -= Math.min((scroll < 0 ? (int) -scroll : scroll > getMaxScroll() ? (int) scroll - getMaxScroll() : 0), height * .95);
+            height = Math.max(10, height);
+            int minY = (int) Math.min(Math.max((int) scroll * (scrollListBounds.height - 2 - height) / getMaxScroll() + scrollListBounds.y + 1, scrollListBounds.y + 1), scrollListBounds.getMaxY() - 1 - height);
             double scrollbarPositionMinX = scrollListBounds.getMaxX() - 6, scrollbarPositionMaxX = scrollListBounds.getMaxX() - 2;
             GuiLighting.disable();
             RenderSystem.disableTexture();
@@ -374,8 +392,8 @@ public class VillagerRecipeViewingScreen extends Screen {
             RenderSystem.shadeModel(7425);
             buffer.begin(7, VertexFormats.POSITION_COLOR);
             float b = ScreenHelper.isDarkModeEnabled() ? 0.37f : 1f;
-            buffer.vertex(scrollbarPositionMinX, minY + scrollBarHeight, 1000D).color(b, b, b, scrollBarAlpha).next();
-            buffer.vertex(scrollbarPositionMaxX, minY + scrollBarHeight, 1000D).color(b, b, b, scrollBarAlpha).next();
+            buffer.vertex(scrollbarPositionMinX, minY + height, 1000D).color(b, b, b, scrollBarAlpha).next();
+            buffer.vertex(scrollbarPositionMaxX, minY + height, 1000D).color(b, b, b, scrollBarAlpha).next();
             buffer.vertex(scrollbarPositionMaxX, minY, 1000D).color(b, b, b, scrollBarAlpha).next();
             buffer.vertex(scrollbarPositionMinX, minY, 1000D).color(b, b, b, scrollBarAlpha).next();
             tessellator.draw();
@@ -389,6 +407,19 @@ public class VillagerRecipeViewingScreen extends Screen {
         ScreenHelper.getLastOverlay().lateRender(mouseX, mouseY, delta);
     }
     
+    private void updatePosition(float delta) {
+        target = clamp(target);
+        if (target < 0) {
+            target -= target * (1 - ClothConfigInitializer.getBounceBackMultiplier()) * delta / 3;
+        } else if (target > getMaxScroll()) {
+            target = (target - getMaxScroll()) * (1 - (1 - ClothConfigInitializer.getBounceBackMultiplier()) * delta / 3) + getMaxScroll();
+        }
+        if (!Precision.almostEquals(scroll, target, Precision.FLOAT_EPSILON))
+            scroll = (float) Interpolation.expoEase(scroll, target, Math.min((System.currentTimeMillis() - start) / ((double) duration), 1));
+        else
+            scroll = target;
+    }
+    
     @Override
     public boolean mouseDragged(double mouseX, double mouseY, int int_1, double double_3, double double_4) {
         if (int_1 == 0 && scrollBarAlpha > 0 && draggingScrollBar) {
@@ -399,7 +430,7 @@ public class VillagerRecipeViewingScreen extends Screen {
                 double double_6 = Math.max(1.0D, Math.max(1d, height) / (double) (actualHeight - int_3));
                 scrollBarAlphaFutureTime = System.currentTimeMillis();
                 scrollBarAlphaFuture = 1f;
-                scroll = MathHelper.clamp(scroll + double_4 * double_6, 0, height - scrollListBounds.height + 2);
+                scroll = target = MathHelper.clamp(scroll + double_4 * double_6, 0, height - scrollListBounds.height + 2);
                 return true;
             }
         }

+ 117 - 0
src/main/java/me/shedaniel/rei/gui/entries/RecipeEntry.java

@@ -0,0 +1,117 @@
+/*
+ * Roughly Enough Items by Danielshe.
+ * Licensed under the MIT License.
+ */
+
+package me.shedaniel.rei.gui.entries;
+
+import me.shedaniel.rei.api.EntryStack;
+import me.shedaniel.rei.api.ObjectHolder;
+import me.shedaniel.rei.impl.ObjectHolderImpl;
+import net.minecraft.client.gui.DrawableHelper;
+import net.minecraft.util.Identifier;
+
+import java.util.Optional;
+
+public abstract class RecipeEntry extends DrawableHelper implements EntryStack {
+    @Override
+    public Optional<Identifier> getIdentifier() {
+        return Optional.empty();
+    }
+    
+    @Override
+    public Type getType() {
+        return Type.RENDER;
+    }
+    
+    @Override
+    public int getAmount() {
+        return 0;
+    }
+    
+    @Override
+    public void setAmount(int amount) {
+    
+    }
+    
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+    
+    @Override
+    public EntryStack copy() {
+        return this;
+    }
+    
+    @Override
+    public Object getObject() {
+        return null;
+    }
+    
+    @Override
+    public boolean equals(EntryStack stack, boolean ignoreTags, boolean ignoreAmount) {
+        return stack == this;
+    }
+    
+    @Override
+    public boolean equalsIgnoreTagsAndAmount(EntryStack stack) {
+        return stack == this;
+    }
+    
+    @Override
+    public boolean equalsIgnoreTags(EntryStack stack) {
+        return stack == this;
+    }
+    
+    @Override
+    public boolean equalsIgnoreAmount(EntryStack stack) {
+        return stack == this;
+    }
+    
+    @Override
+    public boolean equalsAll(EntryStack stack) {
+        return stack == this;
+    }
+    
+    @Override
+    public int getZ() {
+        return getBlitOffset();
+    }
+    
+    @Override
+    public void setZ(int z) {
+        setBlitOffset(z);
+    }
+    
+    @Override
+    public <T> EntryStack setting(Settings<T> settings, T value) {
+        return this;
+    }
+    
+    @Override
+    public <T> EntryStack removeSetting(Settings<T> settings) {
+        return this;
+    }
+    
+    @Override
+    public EntryStack clearSettings() {
+        return this;
+    }
+    
+    @Override
+    public <T> EntryStack addSetting(Settings<T> settings, T value) {
+        return this;
+    }
+    
+    @Override
+    public <T> ObjectHolder<T> getSetting(Settings<T> settings) {
+        return new ObjectHolderImpl<>(settings.getDefaultValue());
+    }
+    
+    public abstract int getHeight();
+    
+    public final int getWidth() {
+        return 100;
+    }
+}

+ 0 - 23
src/main/java/me/shedaniel/rei/gui/renderers/EmptyRenderer.java

@@ -1,23 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.gui.renderers;
-
-import me.shedaniel.rei.api.Renderer;
-
-public class EmptyRenderer extends Renderer {
-    
-    public static final EmptyRenderer INSTANCE = new EmptyRenderer();
-    
-    private EmptyRenderer() {
-    
-    }
-    
-    @Override
-    public void render(int x, int y, double mouseX, double mouseY, float delta) {
-    
-    }
-    
-}

+ 0 - 122
src/main/java/me/shedaniel/rei/gui/renderers/FluidRenderer.java

@@ -1,122 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.gui.renderers;
-
-import com.google.common.collect.Lists;
-import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.api.ClientHelper;
-import me.shedaniel.rei.api.Renderer;
-import me.shedaniel.rei.gui.widget.EntryListWidget;
-import me.shedaniel.rei.gui.widget.QueuedTooltip;
-import me.shedaniel.rei.impl.ScreenHelper;
-import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
-import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.render.BufferBuilder;
-import net.minecraft.client.render.GuiLighting;
-import net.minecraft.client.render.Tessellator;
-import net.minecraft.client.render.VertexFormats;
-import net.minecraft.client.texture.Sprite;
-import net.minecraft.client.texture.SpriteAtlasTexture;
-import net.minecraft.fluid.Fluid;
-import net.minecraft.util.Lazy;
-import net.minecraft.util.Pair;
-import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.registry.Registry;
-
-import javax.annotation.Nullable;
-import java.util.Collections;
-import java.util.List;
-
-public abstract class FluidRenderer extends Renderer {
-    /**
-     * @deprecated This boolean is no longer used
-     */
-    @Deprecated
-    public boolean drawTooltip = false;
-    public Lazy<Pair<Sprite, Integer>> sprite = new Lazy<>(() -> {
-        try {
-            FluidRenderHandler fluidRenderHandler = FluidRenderHandlerRegistry.INSTANCE.get(getFluid());
-            if (fluidRenderHandler == null)
-                return null;
-            Sprite[] sprites = fluidRenderHandler.getFluidSprites(MinecraftClient.getInstance().world, MinecraftClient.getInstance().world == null ? null : BlockPos.ORIGIN, getFluid().getDefaultState());
-            int color = -1;
-            if (MinecraftClient.getInstance().world != null)
-                color = fluidRenderHandler.getFluidColor(MinecraftClient.getInstance().world, BlockPos.ORIGIN, getFluid().getDefaultState());
-            return new Pair<>(sprites[0], color);
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    });
-    
-    @Override
-    public void render(int x, int y, double mouseX, double mouseY, float delta) {
-        x = x - 8;
-        y = y - 6;
-        Pair<Sprite, Integer> pair = this.sprite.get();
-        if (pair != null) {
-            Sprite sprite = pair.getLeft();
-            Integer int_5 = pair.getRight();
-            int a = 255;
-            int r = (int_5 >> 16 & 255);
-            int g = (int_5 >> 8 & 255);
-            int b = (int_5 & 255);
-            MinecraftClient.getInstance().getTextureManager().bindTexture(SpriteAtlasTexture.BLOCK_ATLAS_TEX);
-            GuiLighting.disable();
-            Tessellator tess = Tessellator.getInstance();
-            BufferBuilder bb = tess.getBufferBuilder();
-            bb.begin(7, VertexFormats.POSITION_UV_COLOR);
-            bb.vertex(x + 16, y, getBlitOffset()).texture(sprite.getMaxU(), sprite.getMinV()).color(r, g, b, a).next();
-            bb.vertex(x, y, getBlitOffset()).texture(sprite.getMinU(), sprite.getMinV()).color(r, g, b, a).next();
-            bb.vertex(x, y + 16, getBlitOffset()).texture(sprite.getMinU(), sprite.getMaxV()).color(r, g, b, a).next();
-            bb.vertex(x + 16, y + 16, getBlitOffset()).texture(sprite.getMaxU(), sprite.getMaxV()).color(r, g, b, a).next();
-            tess.draw();
-        }
-        setBlitOffset(0);
-    }
-    
-    @Nullable
-    @Override
-    public QueuedTooltip getQueuedTooltip(float delta) {
-        return QueuedTooltip.create(getTooltip(getFluid()));
-    }
-    
-    /**
-     * Queue a tooltip to the REI overlay
-     *
-     * @param fluid the fluid to queue
-     * @param delta the delta
-     * @deprecated Use {@link Renderer#getQueuedTooltip(float)} instead and queue manually
-     */
-    @Deprecated
-    protected void queueTooltip(Fluid fluid, float delta) {
-        ScreenHelper.getLastOverlay().addTooltip(getQueuedTooltip(delta));
-    }
-    
-    protected List<String> getTooltip(Fluid fluid) {
-        List<String> toolTip = Lists.newArrayList(EntryListWidget.tryGetFluidName(fluid));
-        toolTip.addAll(getExtraToolTips(fluid));
-        if (RoughlyEnoughItemsCore.getConfigManager().getConfig().shouldAppendModNames()) {
-            final String modString = ClientHelper.getInstance().getFormattedModFromIdentifier(Registry.FLUID.getId(fluid));
-            boolean alreadyHasMod = false;
-            for (String s : toolTip)
-                if (s.equalsIgnoreCase(modString)) {
-                    alreadyHasMod = true;
-                    break;
-                }
-            if (!alreadyHasMod)
-                toolTip.add(modString);
-        }
-        return toolTip;
-    }
-    
-    protected List<String> getExtraToolTips(Fluid fluid) {
-        return Collections.emptyList();
-    }
-    
-    public abstract Fluid getFluid();
-}

+ 0 - 106
src/main/java/me/shedaniel/rei/gui/renderers/ItemStackRenderer.java

@@ -1,106 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.gui.renderers;
-
-import com.google.common.collect.Lists;
-import com.mojang.blaze3d.systems.RenderSystem;
-import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.api.ClientHelper;
-import me.shedaniel.rei.api.ItemStackRenderOverlayHook;
-import me.shedaniel.rei.api.Renderer;
-import me.shedaniel.rei.gui.widget.EntryListWidget;
-import me.shedaniel.rei.gui.widget.QueuedTooltip;
-import me.shedaniel.rei.impl.ScreenHelper;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.render.item.ItemRenderer;
-import net.minecraft.item.ItemStack;
-import net.minecraft.util.Identifier;
-
-import javax.annotation.Nullable;
-import java.util.Collections;
-import java.util.List;
-
-public abstract class ItemStackRenderer extends Renderer {
-    
-    public static final Identifier CHEST_GUI_TEXTURE = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
-    /**
-     * @deprecated This boolean is no longer used
-     */
-    @Deprecated
-    public boolean drawTooltip = false;
-    
-    @Override
-    public void render(int x, int y, double mouseX, double mouseY, float delta) {
-        int l = x - 8, i1 = y - 6;
-        ItemStack stack = getItemStack();
-        ((ItemStackRenderOverlayHook) (Object) stack).rei_setRenderOverlay(renderOverlay());
-        RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
-        ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
-        itemRenderer.zOffset = getBlitOffset();
-        RenderSystem.colorMask(true, true, true, true);
-        RenderSystem.enableLighting();
-        RenderSystem.enableRescaleNormal();
-        RenderSystem.enableDepthTest();
-        itemRenderer.renderGuiItem(stack, l, i1);
-        itemRenderer.renderGuiItemOverlay(MinecraftClient.getInstance().textRenderer, stack, l, i1, getCounts());
-        itemRenderer.zOffset = 0.0F;
-        setBlitOffset(0);
-    }
-    
-    /**
-     * Queue a tooltip to the REI overlay
-     *
-     * @param itemStack the stack to queue
-     * @param delta     the delta
-     * @deprecated Use {@link Renderer#getQueuedTooltip(float)} instead and queue manually
-     */
-    @Deprecated
-    protected void queueTooltip(ItemStack itemStack, float delta) {
-        ScreenHelper.getLastOverlay().addTooltip(QueuedTooltip.create(getTooltip(itemStack)));
-    }
-    
-    @Nullable
-    @Override
-    public QueuedTooltip getQueuedTooltip(float delta) {
-        return QueuedTooltip.create(getTooltip(getItemStack()));
-    }
-    
-    protected boolean renderCounts() {
-        return true;
-    }
-    
-    protected boolean renderOverlay() {
-        return true;
-    }
-    
-    protected String getCounts() {
-        return renderCounts() ? null : "";
-    }
-    
-    protected List<String> getTooltip(ItemStack itemStack) {
-        List<String> toolTip = Lists.newArrayList(EntryListWidget.tryGetItemStackToolTip(itemStack, true));
-        toolTip.addAll(getExtraToolTips(itemStack));
-        if (RoughlyEnoughItemsCore.getConfigManager().getConfig().shouldAppendModNames()) {
-            final String modString = ClientHelper.getInstance().getFormattedModFromItem(itemStack.getItem());
-            boolean alreadyHasMod = false;
-            for (String s : toolTip)
-                if (s.equalsIgnoreCase(modString)) {
-                    alreadyHasMod = true;
-                    break;
-                }
-            if (!alreadyHasMod)
-                toolTip.add(modString);
-        }
-        return toolTip;
-    }
-    
-    protected List<String> getExtraToolTips(ItemStack stack) {
-        return Collections.emptyList();
-    }
-    
-    public abstract ItemStack getItemStack();
-    
-}

+ 0 - 18
src/main/java/me/shedaniel/rei/gui/renderers/RecipeRenderer.java

@@ -1,18 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.gui.renderers;
-
-import me.shedaniel.rei.api.Renderer;
-
-public abstract class RecipeRenderer extends Renderer {
-    
-    public abstract int getHeight();
-    
-    public final int getWidth() {
-        return 100;
-    }
-    
-}

+ 40 - 58
src/main/java/me/shedaniel/rei/gui/renderers/SimpleRecipeRenderer.java → src/main/java/me/shedaniel/rei/gui/renderers/SimpleRecipeEntry.java

@@ -6,13 +6,14 @@
 package me.shedaniel.rei.gui.renderers;
 
 import com.google.common.collect.Lists;
+import me.shedaniel.math.api.Rectangle;
 import me.shedaniel.rei.api.EntryStack;
-import me.shedaniel.rei.api.Renderer;
-import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
+import me.shedaniel.rei.gui.entries.RecipeEntry;
+import me.shedaniel.rei.gui.widget.EntryWidget;
 import me.shedaniel.rei.gui.widget.QueuedTooltip;
+import me.shedaniel.rei.utils.CollectionUtils;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.render.GuiLighting;
-import net.minecraft.fluid.Fluid;
 import net.minecraft.item.ItemStack;
 import net.minecraft.util.Identifier;
 import net.minecraft.util.Pair;
@@ -26,7 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
-public class SimpleRecipeRenderer extends RecipeRenderer {
+public class SimpleRecipeEntry extends RecipeEntry {
     
     private static final Comparator<EntryStack> ENTRY_COMPARATOR = (o1, o2) -> {
         if (o1.getType() == EntryStack.Type.FLUID) {
@@ -53,19 +54,12 @@ public class SimpleRecipeRenderer extends RecipeRenderer {
         return i1.getItem().hashCode() - i2.getItem().hashCode();
     };
     private static final Identifier CHEST_GUI_TEXTURE = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
-    private List<Renderer> inputRenderer;
-    private Renderer outputRenderer;
-    private QueuedTooltip lastTooltip;
+    private List<EntryWidget> inputWidgets;
+    private EntryWidget outputWidget;
     
-    @Deprecated
-    public SimpleRecipeRenderer(Supplier<List<List<ItemStack>>> input, Supplier<List<ItemStack>> output) {
-        this(() -> (List<List<EntryStack>>) input.get().stream().map(s -> s.stream().map(EntryStack::create).collect(Collectors.toList())).collect(Collectors.toList()),
-                () -> output.get().stream().map(EntryStack::create).collect(Collectors.toList()), 0);
-    }
-    
-    public SimpleRecipeRenderer(Supplier<List<List<EntryStack>>> input, Supplier<List<EntryStack>> output, int forDifferentConstructor) {
+    protected SimpleRecipeEntry(List<List<EntryStack>> input, List<EntryStack> output) {
         List<Pair<List<EntryStack>, AtomicInteger>> newList = Lists.newArrayList();
-        List<Pair<List<EntryStack>, Integer>> a = input.get().stream().map(stacks -> new Pair<>(stacks, stacks.stream().map(EntryStack::getAmount).max(Integer::compareTo).orElse(1))).collect(Collectors.toList());
+        List<Pair<List<EntryStack>, Integer>> a = input.stream().map(stacks -> new Pair<>(stacks, stacks.stream().map(EntryStack::getAmount).max(Integer::compareTo).orElse(1))).collect(Collectors.toList());
         for (Pair<List<EntryStack>, Integer> pair : a) {
             Optional<Pair<List<EntryStack>, AtomicInteger>> any = newList.stream().filter(pairr -> equalsList(pair.getLeft(), pairr.getLeft())).findAny();
             if (any.isPresent()) {
@@ -80,31 +74,18 @@ public class SimpleRecipeRenderer extends RecipeRenderer {
                 s.setAmount(pair.getRight().get());
                 return s;
             }).collect(Collectors.toList()));
-        this.inputRenderer = b.stream().filter(stacks -> !stacks.isEmpty()).map(stacks -> fromEntries(stacks)).collect(Collectors.toList());
-        this.outputRenderer = fromEntries(output.get().stream().filter(stack -> !stack.isEmpty()).collect(Collectors.toList()));
+        this.inputWidgets = b.stream().filter(stacks -> !stacks.isEmpty()).map(stacks -> {
+            return EntryWidget.create(0, 0).entries(stacks).noBackground().noHighlight().noTooltips();
+        }).collect(Collectors.toList());
+        this.outputWidget = EntryWidget.create(0, 0).entries(CollectionUtils.filter(output, stack -> !stack.isEmpty())).noBackground().noHighlight().noTooltips();
     }
     
-    @Deprecated
-    private static Renderer fromEntries(List<EntryStack> entries) {
-        boolean isItem = true;
-        for (EntryStack entry : entries) {
-            if (entry.getType() != EntryStack.Type.ITEM)
-                isItem = false;
-        }
-        if (isItem)
-            return Renderer.fromItemStacks(entries.stream().map(EntryStack::getItemStack).collect(Collectors.toList()));
-        boolean isFluid = true;
-        for (EntryStack entry : entries) {
-            if (entry.getType() != EntryStack.Type.FLUID)
-                isFluid = false;
-        }
-        
-        if (isFluid) {
-            List<Fluid> fluids = entries.stream().map(EntryStack::getFluid).collect(Collectors.toList());
-            if (!fluids.isEmpty())
-                return Renderer.fromFluid(fluids.get(0));
-        }
-        return Renderer.empty();
+    public static RecipeEntry create(Supplier<List<List<EntryStack>>> input, Supplier<List<EntryStack>> output) {
+        return create(input.get(), output.get());
+    }
+    
+    public static RecipeEntry create(List<List<EntryStack>> input, List<EntryStack> output) {
+        return new SimpleRecipeEntry(input, output);
     }
     
     public static boolean equalsList(List<EntryStack> list_1, List<EntryStack> list_2) {
@@ -121,42 +102,43 @@ public class SimpleRecipeRenderer extends RecipeRenderer {
     }
     
     @Override
-    public void render(int x, int y, double mouseX, double mouseY, float delta) {
-        lastTooltip = null;
-        int xx = x + 4, yy = y + 2;
+    public void render(Rectangle bounds, int mouseX, int mouseY, float delta) {
+        int xx = bounds.x + 4, yy = bounds.y + 2;
         int j = 0;
         int itemsPerLine = getItemsPerLine();
-        for (Renderer itemStackRenderer : inputRenderer) {
-            itemStackRenderer.setBlitOffset(getBlitOffset() + 50);
-            if (lastTooltip == null && MinecraftClient.getInstance().currentScreen instanceof VillagerRecipeViewingScreen && mouseX >= xx && mouseX <= xx + 16 && mouseY >= yy && mouseY <= yy + 16) {
-                lastTooltip = itemStackRenderer.getQueuedTooltip(delta);
-            }
-            itemStackRenderer.render(xx + 8, yy + 6, mouseX, mouseY, delta);
+        for (EntryWidget entryWidget : inputWidgets) {
+            entryWidget.setZ(getZ() + 50);
+            entryWidget.getBounds().setLocation(xx, yy);
+            entryWidget.render(mouseX, mouseY, delta);
             xx += 18;
             j++;
             if (j >= getItemsPerLine() - 2) {
                 yy += 18;
-                xx = x + 5;
+                xx = bounds.x + 4;
                 j = 0;
             }
         }
-        xx = x + 5 + 18 * (getItemsPerLine() - 2);
-        yy = y + getHeight() / 2 - 8;
+        xx = bounds.x + 4 + 18 * (getItemsPerLine() - 2);
+        yy = bounds.y + getHeight() / 2 - 8;
         GuiLighting.disable();
         MinecraftClient.getInstance().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
         blit(xx, yy, 0, 28, 18, 18);
         xx += 18;
-        outputRenderer.setBlitOffset(getBlitOffset() + 50);
-        outputRenderer.render(xx + 8, yy + 6, mouseX, mouseY, delta);
-        if (lastTooltip == null && MinecraftClient.getInstance().currentScreen instanceof VillagerRecipeViewingScreen && mouseX >= xx && mouseX <= xx + 16 && mouseY >= yy && mouseY <= yy + 16) {
-            lastTooltip = outputRenderer.getQueuedTooltip(delta);
-        }
+        outputWidget.setZ(getZ() + 50);
+        outputWidget.getBounds().setLocation(xx, yy);
+        outputWidget.render(mouseX, mouseY, delta);
     }
     
     @Nullable
     @Override
-    public QueuedTooltip getQueuedTooltip(float delta) {
-        return lastTooltip;
+    public QueuedTooltip getTooltip(int mouseX, int mouseY) {
+        for (EntryWidget widget : inputWidgets) {
+            if (widget.containsMouse(mouseX, mouseY))
+                return widget.getCurrentTooltip(mouseX, mouseY);
+        }
+        if (outputWidget.containsMouse(mouseX, mouseY))
+            return outputWidget.getCurrentTooltip(mouseX, mouseY);
+        return null;
     }
     
     @Override
@@ -165,7 +147,7 @@ public class SimpleRecipeRenderer extends RecipeRenderer {
     }
     
     public int getItemsHeight() {
-        return MathHelper.ceil(((float) inputRenderer.size()) / (getItemsPerLine() - 2));
+        return MathHelper.ceil(((float) inputWidgets.size()) / (getItemsPerLine() - 2));
     }
     
     public int getItemsPerLine() {

+ 0 - 1
src/main/java/me/shedaniel/rei/gui/toast/CopyRecipeIdentifierToast.java

@@ -5,7 +5,6 @@
 
 package me.shedaniel.rei.gui.toast;
 
-import com.mojang.blaze3d.platform.GlStateManager;
 import com.mojang.blaze3d.systems.RenderSystem;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.toast.Toast;

+ 0 - 1
src/main/java/me/shedaniel/rei/gui/widget/ButtonWidget.java

@@ -8,7 +8,6 @@ package me.shedaniel.rei.gui.widget;
 import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Point;
 import me.shedaniel.math.api.Rectangle;
-import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.rei.impl.ScreenHelper;
 import net.minecraft.client.gui.Element;
 import net.minecraft.client.sound.PositionedSoundInstance;

+ 10 - 4
src/main/java/me/shedaniel/rei/gui/widget/ClickableLabelWidget.java

@@ -7,7 +7,6 @@ package me.shedaniel.rei.gui.widget;
 
 import me.shedaniel.math.api.Point;
 import me.shedaniel.rei.impl.ScreenHelper;
-import net.minecraft.util.Formatting;
 
 import java.util.Optional;
 
@@ -15,16 +14,23 @@ public abstract class ClickableLabelWidget extends LabelWidget {
     
     public boolean focused;
     public boolean clickable;
+    public int hoveredColor;
     
     public ClickableLabelWidget(int x, int y, String text, boolean clickable) {
         super(x, y, text);
         this.clickable = clickable;
+        this.hoveredColor = ScreenHelper.isDarkModeEnabled() ? -1 : 0xFF66FFCC;
     }
     
     public ClickableLabelWidget(int x, int y, String text) {
         this(x, y, text, true);
     }
     
+    public LabelWidget hoveredColor(int hoveredColor) {
+        this.hoveredColor = hoveredColor;
+        return this;
+    }
+    
     @Override
     public void render(int mouseX, int mouseY, float delta) {
         int color = getDefaultColor();
@@ -32,9 +38,9 @@ public abstract class ClickableLabelWidget extends LabelWidget {
             color = getHoveredColor();
         int width = font.getStringWidth(text);
         if (isHasShadows())
-            font.drawWithShadow((isHovered(mouseX, mouseY) ? Formatting.UNDERLINE.toString() : "") + text, x - width / 2, y, color);
+            font.drawWithShadow(text, x - width / 2, y, color);
         else
-            font.draw((isHovered(mouseX, mouseY) ? Formatting.UNDERLINE.toString() : "") + text, x - width / 2, y, color);
+            font.draw(text, x - width / 2, y, color);
         if (clickable && getTooltips().isPresent())
             if (!focused && containsMouse(mouseX, mouseY))
                 ScreenHelper.getLastOverlay().addTooltip(QueuedTooltip.create(getTooltips().get().split("\n")));
@@ -43,7 +49,7 @@ public abstract class ClickableLabelWidget extends LabelWidget {
     }
     
     public int getHoveredColor() {
-        return ScreenHelper.isDarkModeEnabled() ? -1 : 0xFF66FFCC;
+        return hoveredColor;
     }
     
     @Override

+ 1 - 1
src/main/java/me/shedaniel/rei/gui/widget/CraftableToggleButtonWidget.java

@@ -36,7 +36,7 @@ public abstract class CraftableToggleButtonWidget extends ButtonWidget {
         GuiLighting.disable();
         super.render(mouseX, mouseY, delta);
         
-//        GuiLighting.enableForItems();
+        //        GuiLighting.enableForItems();
         this.itemRenderer.zOffset = getBlitOffset();
         this.itemRenderer.renderGuiItem(new ItemStack(Blocks.CRAFTING_TABLE), getBounds().x + 2, getBounds().y + 2);
         this.itemRenderer.zOffset = 0.0F;

+ 0 - 48
src/main/java/me/shedaniel/rei/gui/widget/DetailedButtonWidget.java

@@ -1,48 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.gui.widget;
-
-import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
-import net.minecraft.text.Text;
-
-@ToBeRemoved
-@Deprecated
-public class DetailedButtonWidget extends ButtonWidget {
-    
-    private DetailedButtonWidget.PressAction pressAction;
-    
-    public DetailedButtonWidget(Rectangle rectangle, Text text, PressAction pressAction) {
-        super(rectangle, text);
-        this.pressAction = pressAction;
-    }
-    
-    public DetailedButtonWidget(Rectangle rectangle, String text, PressAction pressAction) {
-        super(rectangle, text);
-        this.pressAction = pressAction;
-    }
-    
-    public DetailedButtonWidget(int x, int y, int width, int height, String text, PressAction pressAction) {
-        super(x, y, width, height, text);
-        this.pressAction = pressAction;
-    }
-    
-    public DetailedButtonWidget(int x, int y, int width, int height, Text text, PressAction pressAction) {
-        super(x, y, width, height, text);
-        this.pressAction = pressAction;
-    }
-    
-    @Override
-    public void onPressed() {
-        if (pressAction != null)
-            pressAction.onPress(this);
-    }
-    
-    public interface PressAction {
-        void onPress(ButtonWidget var1);
-    }
-    
-}

+ 7 - 15
src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java

@@ -6,16 +6,18 @@
 package me.shedaniel.rei.gui.widget;
 
 import com.google.common.collect.Lists;
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.clothconfig2.ClothConfigInitializer;
 import me.shedaniel.clothconfig2.api.ScissorsHandler;
 import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget.Interpolation;
 import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget.Precision;
 import me.shedaniel.math.api.Rectangle;
-import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.impl.PointHelper;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.api.*;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
+import me.shedaniel.rei.api.ClientHelper;
+import me.shedaniel.rei.api.DisplayHelper;
+import me.shedaniel.rei.api.EntryStack;
+import me.shedaniel.rei.api.RecipeHelper;
 import me.shedaniel.rei.gui.config.ItemCheatingMode;
 import me.shedaniel.rei.gui.config.ItemListOrdering;
 import me.shedaniel.rei.impl.ScreenHelper;
@@ -102,16 +104,6 @@ public class EntryListWidget extends Widget {
         return Collections.singletonList(tryGetItemStackName(itemStack));
     }
     
-    @ToBeRemoved
-    @Deprecated
-    public static String tryGetEntryName(Entry stack) {
-        if (stack.getEntryType() == Entry.Type.ITEM)
-            return tryGetItemStackName(stack.getItemStack());
-        else if (stack.getEntryType() == Entry.Type.FLUID)
-            return tryGetFluidName(stack.getFluid());
-        return "";
-    }
-    
     public static String tryGetEntryStackName(EntryStack stack) {
         if (stack.getType() == EntryStack.Type.ITEM)
             return tryGetItemStackName(stack.getItemStack());
@@ -357,7 +349,7 @@ public class EntryListWidget extends Widget {
         this.widgets = Lists.newCopyOnWriteArrayList();
         calculateListSize(rectangle);
         if (currentDisplayed.isEmpty() || processSearchTerm)
-            currentDisplayed = processSearchTerm(searchTerm, RoughlyEnoughItemsCore.getEntryRegistry().getStacksList(), new ArrayList<>(ScreenHelper.inventoryStacks));
+            currentDisplayed = processSearchTerm(searchTerm, RoughlyEnoughItemsCore.getEntryRegistry().getStacksList(), CollectionUtils.map(ScreenHelper.inventoryStacks, EntryStack::create));
         int startX = rectangle.getCenterX() - width * 9;
         int startY = rectangle.getCenterY() - height * 9;
         this.listArea = new Rectangle(startX, startY, width * 18, height * 18);
@@ -446,7 +438,7 @@ public class EntryListWidget extends Widget {
         return currentDisplayed;
     }
     
-    private List<EntryStack> processSearchTerm(String searchTerm, List<EntryStack> ol, List<ItemStack> inventoryItems) {
+    private List<EntryStack> processSearchTerm(String searchTerm, List<EntryStack> ol, List<EntryStack> inventoryItems) {
         lastSearchArgument.clear();
         List<EntryStack> os = new LinkedList<>(ol);
         if (RoughlyEnoughItemsCore.getConfigManager().getConfig().getItemListOrdering() != ItemListOrdering.registry)

+ 15 - 14
src/main/java/me/shedaniel/rei/gui/widget/EntryWidget.java

@@ -5,12 +5,11 @@
 
 package me.shedaniel.rei.gui.widget;
 
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.math.compat.RenderHelper;
 import me.shedaniel.math.impl.PointHelper;
 import me.shedaniel.rei.api.ClientHelper;
 import me.shedaniel.rei.api.EntryStack;
-import me.shedaniel.rei.api.annotations.Experimental;
 import me.shedaniel.rei.impl.ScreenHelper;
 import net.minecraft.client.gui.Element;
 import net.minecraft.util.Identifier;
@@ -21,7 +20,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
-@Experimental
 public class EntryWidget extends WidgetWithBounds {
     
     protected static final Identifier RECIPE_GUI = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
@@ -138,30 +136,33 @@ public class EntryWidget extends WidgetWithBounds {
     
     protected void drawCurrentEntry(int mouseX, int mouseY, float delta) {
         EntryStack entry = getCurrentEntry();
-        entry.setZ(200);
+        entry.setZ(100);
         entry.render(getInnerBounds(), mouseX, mouseY, delta);
     }
     
     protected void queueTooltip(int mouseX, int mouseY, float delta) {
-        EntryStack entry = getCurrentEntry();
-        QueuedTooltip tooltip = entry.getTooltip(mouseX, mouseY);
+        QueuedTooltip tooltip = getCurrentTooltip(mouseX, mouseY);
         if (tooltip != null) {
             ScreenHelper.getLastOverlay().addTooltip(tooltip);
         }
     }
     
+    public QueuedTooltip getCurrentTooltip(int mouseX, int mouseY) {
+        return getCurrentEntry().getTooltip(mouseX, mouseY);
+    }
+    
     protected void drawHighlighted(int mouseX, int mouseY, float delta) {
-        RenderHelper.disableLighting();
-        RenderHelper.disableDepthTest();
-        RenderHelper.colorMask(true, true, true, false);
+        RenderSystem.disableLighting();
+        RenderSystem.disableDepthTest();
+        RenderSystem.colorMask(true, true, true, false);
         int color = ScreenHelper.isDarkModeEnabled() ? -1877929711 : -2130706433;
-        blitOffset = 300;
+        setZ(300);
         Rectangle bounds = getInnerBounds();
         fillGradient(bounds.x, bounds.y, bounds.getMaxX(), bounds.getMaxY(), color, color);
-        blitOffset = 0;
-        RenderHelper.colorMask(true, true, true, true);
-        RenderHelper.enableLighting();
-        RenderHelper.enableDepthTest();
+        setZ(0);
+        RenderSystem.colorMask(true, true, true, true);
+        RenderSystem.enableLighting();
+        RenderSystem.enableDepthTest();
     }
     
     @Override

+ 5 - 0
src/main/java/me/shedaniel/rei/gui/widget/LabelWidget.java

@@ -43,6 +43,11 @@ public class LabelWidget extends WidgetWithBounds {
         this.defaultColor = defaultColor;
     }
     
+    public LabelWidget color(int defaultColor) {
+        this.defaultColor = defaultColor;
+        return this;
+    }
+    
     @Override
     public Rectangle getBounds() {
         int width = font.getStringWidth(text);

+ 2 - 9
src/main/java/me/shedaniel/rei/gui/widget/PanelWidget.java

@@ -5,24 +5,17 @@
 
 package me.shedaniel.rei.gui.widget;
 
-import com.mojang.blaze3d.platform.GlStateManager;
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.math.compat.RenderHelper;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.api.annotations.Experimental;
 import me.shedaniel.rei.gui.config.RecipeScreenType;
 import me.shedaniel.rei.impl.ScreenHelper;
-import net.minecraft.client.render.BufferBuilder;
 import net.minecraft.client.render.GuiLighting;
-import net.minecraft.client.render.Tessellator;
-import net.minecraft.client.render.VertexFormats;
 import net.minecraft.util.Identifier;
 
 import java.util.Collections;
 import java.util.List;
 
-@Experimental
-@Deprecated
 public class PanelWidget extends WidgetWithBounds {
     
     private static final Identifier CHEST_GUI_TEXTURE = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
@@ -65,7 +58,7 @@ public class PanelWidget extends WidgetWithBounds {
         float green = ((color >> 8) & 0xFF) / 255f;
         float blue = ((color >> 0) & 0xFF) / 255f;
         float alpha = ((color >> 32) & 0xFF) / 255f;
-        RenderHelper.color4f(red, green, blue, alpha);
+        RenderSystem.color4f(red, green, blue, alpha);
         GuiLighting.disable();
         minecraft.getTextureManager().bindTexture(ScreenHelper.isDarkModeEnabled() ? CHEST_GUI_TEXTURE_DARK : CHEST_GUI_TEXTURE);
         int x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;

+ 1 - 1
src/main/java/me/shedaniel/rei/gui/widget/RecipeArrowWidget.java

@@ -5,8 +5,8 @@
 
 package me.shedaniel.rei.gui.widget;
 
-import me.shedaniel.math.api.Rectangle;
 import com.mojang.blaze3d.systems.RenderSystem;
+import me.shedaniel.math.api.Rectangle;
 import me.shedaniel.rei.plugin.DefaultPlugin;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.Element;

+ 0 - 8
src/main/java/me/shedaniel/rei/gui/widget/RecipeBaseWidget.java

@@ -5,10 +5,8 @@
 
 package me.shedaniel.rei.gui.widget;
 
-import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Rectangle;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
 
 public class RecipeBaseWidget extends PanelWidget {
     
@@ -18,12 +16,6 @@ public class RecipeBaseWidget extends PanelWidget {
     
     @Override
     protected int getYTextureOffset() {
-        return getTextureOffset();
-    }
-    
-    @ToBeRemoved
-    @Deprecated
-    protected int getTextureOffset() {
         return RoughlyEnoughItemsCore.getConfigManager().getConfig().isUsingLightGrayRecipeBorder() ? 0 : 66;
     }
     

+ 0 - 318
src/main/java/me/shedaniel/rei/gui/widget/SlotWidget.java

@@ -1,318 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.gui.widget;
-
-import com.google.common.collect.Lists;
-import com.mojang.blaze3d.systems.RenderSystem;
-import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.math.impl.PointHelper;
-import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.api.ClientHelper;
-import me.shedaniel.rei.api.EntryStack;
-import me.shedaniel.rei.api.Renderer;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
-import me.shedaniel.rei.gui.renderers.FluidRenderer;
-import me.shedaniel.rei.gui.renderers.ItemStackRenderer;
-import me.shedaniel.rei.impl.ScreenHelper;
-import me.shedaniel.rei.utils.CollectionUtils;
-import net.minecraft.client.gui.Element;
-import net.minecraft.fluid.Fluid;
-import net.minecraft.item.ItemStack;
-import net.minecraft.util.Formatting;
-import net.minecraft.util.Identifier;
-import net.minecraft.util.math.MathHelper;
-import net.minecraft.util.registry.Registry;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.function.Function;
-
-@SuppressWarnings("deprecation")
-public class SlotWidget extends WidgetWithBounds {
-    
-    public static final Identifier RECIPE_GUI = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
-    public static final Identifier RECIPE_GUI_DARK = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer_dark.png");
-    private static final Function<ItemStack, Renderer> ITEM_STACK_RENDERER = Renderer::fromItemStack;
-    private Rectangle bounds;
-    private List<Renderer> renderers = new LinkedList<>();
-    private boolean drawBackground, showToolTips, clickToMoreRecipes, drawHighlightedBackground;
-    
-    public SlotWidget(int x, int y, Renderer renderer, boolean drawBackground, boolean showToolTips) {
-        this(x, y, Collections.singletonList(renderer), drawBackground, showToolTips);
-    }
-    
-    public SlotWidget(int x, int y, Renderer renderer, boolean drawBackground, boolean showToolTips, boolean clickToMoreRecipes) {
-        this(x, y, Collections.singletonList(renderer), drawBackground, showToolTips, clickToMoreRecipes);
-    }
-    
-    public SlotWidget(int x, int y, List<Renderer> renderers, boolean drawBackground, boolean showToolTips) {
-        this.renderers = renderers;
-        this.drawBackground = drawBackground;
-        this.showToolTips = showToolTips;
-        this.bounds = new Rectangle(x - 1, y - 1, 18, 18);
-        this.clickToMoreRecipes = false;
-        this.drawHighlightedBackground = true;
-    }
-    
-    public SlotWidget(int x, int y, List<Renderer> itemList, boolean drawBackground, boolean showToolTips, boolean clickToMoreRecipes) {
-        this(x, y, itemList, drawBackground, showToolTips);
-        this.clickToMoreRecipes = clickToMoreRecipes;
-    }
-    
-    /**
-     * @see WidgetWithBounds#getBounds()
-     */
-    @ToBeRemoved
-    @Deprecated
-    public int getX() {
-        return bounds.x + 1;
-    }
-    
-    /**
-     * @see WidgetWithBounds#getBounds()
-     */
-    @ToBeRemoved
-    @Deprecated
-    public void setX(int x) {
-        bounds.x = x - 1;
-    }
-    
-    /**
-     * @see WidgetWithBounds#getBounds()
-     */
-    @ToBeRemoved
-    @Deprecated
-    public int getY() {
-        return bounds.y + 1;
-    }
-    
-    /**
-     * @see WidgetWithBounds#getBounds()
-     */
-    @ToBeRemoved
-    @Deprecated
-    public void setY(int y) {
-        bounds.y = y - 1;
-    }
-    
-    public boolean isShowToolTips() {
-        return showToolTips;
-    }
-    
-    public void setShowToolTips(boolean showToolTips) {
-        this.showToolTips = showToolTips;
-    }
-    
-    public boolean isClickToMoreRecipes() {
-        return clickToMoreRecipes;
-    }
-    
-    public void setClickToMoreRecipes(boolean clickToMoreRecipes) {
-        this.clickToMoreRecipes = clickToMoreRecipes;
-    }
-    
-    public boolean isDrawHighlightedBackground() {
-        return drawHighlightedBackground;
-    }
-    
-    public void setDrawHighlightedBackground(boolean drawHighlightedBackground) {
-        this.drawHighlightedBackground = drawHighlightedBackground;
-    }
-    
-    @Override
-    public List<? extends Element> children() {
-        return Collections.emptyList();
-    }
-    
-    public boolean isDrawBackground() {
-        return drawBackground;
-    }
-    
-    public void setDrawBackground(boolean drawBackground) {
-        this.drawBackground = drawBackground;
-    }
-    
-    @Override
-    public void render(int mouseX, int mouseY, float delta) {
-        Renderer renderer = getCurrentRenderer();
-        boolean darkTheme = ScreenHelper.isDarkModeEnabled();
-        if (drawBackground) {
-            minecraft.getTextureManager().bindTexture(darkTheme ? RECIPE_GUI_DARK : RECIPE_GUI);
-            blit(bounds.x, bounds.y, 0, 222, bounds.width, bounds.height);
-        }
-        boolean highlighted = containsMouse(mouseX, mouseY);
-        renderer.setBlitOffset(200);
-        renderer.render(bounds.x + 9, bounds.y + 7, mouseX, mouseY, delta);
-        if (highlighted && showToolTips) {
-            QueuedTooltip queuedTooltip = renderer.getQueuedTooltip(delta);
-            if (queuedTooltip != null) {
-                ScreenHelper.getLastOverlay().addTooltip(queuedTooltip);
-            }
-        }
-        if (drawHighlightedBackground && highlighted) {
-            RenderSystem.disableLighting();
-            RenderSystem.disableDepthTest();
-            RenderSystem.colorMask(true, true, true, false);
-            int color = darkTheme ? -1877929711 : -2130706433;
-            setBlitOffset(300);
-            fillGradient(bounds.x + 1, bounds.y + 1, bounds.getMaxX() - 1, bounds.getMaxY() - 1, color, color);
-            setBlitOffset(0);
-            RenderSystem.colorMask(true, true, true, true);
-            RenderSystem.enableLighting();
-            RenderSystem.enableDepthTest();
-        }
-    }
-    /**
-     * @deprecated Not used anymore, see {@link Renderer#getQueuedTooltip(float)}
-     */
-    @ToBeRemoved
-    @Deprecated
-    protected void queueTooltip(Fluid fluid, float delta) {
-        ScreenHelper.getLastOverlay().addTooltip(QueuedTooltip.create(getTooltip(fluid)));
-    }
-    
-    /**
-     * @deprecated Not used anymore, see {@link Renderer#getQueuedTooltip(float)}
-     */
-    @ToBeRemoved
-    @Deprecated
-    private List<String> getTooltip(Fluid fluid) {
-        List<String> toolTip = Lists.newArrayList(EntryListWidget.tryGetFluidName(fluid));
-        toolTip.addAll(getExtraFluidToolTips(fluid));
-        if (RoughlyEnoughItemsCore.getConfigManager().getConfig().shouldAppendModNames()) {
-            final String modString = ClientHelper.getInstance().getFormattedModFromIdentifier(Registry.FLUID.getId(fluid));
-            boolean alreadyHasMod = false;
-            for (String s : toolTip)
-                if (s.equalsIgnoreCase(modString)) {
-                    alreadyHasMod = true;
-                    break;
-                }
-            if (!alreadyHasMod)
-                toolTip.add(modString);
-        }
-        return toolTip;
-    }
-    
-    /**
-     * @deprecated Not used anymore, see {@link Renderer#getQueuedTooltip(float)}
-     */
-    @ToBeRemoved
-    @Deprecated
-    protected void queueTooltip(ItemStack itemStack, float delta) {
-        ScreenHelper.getLastOverlay().addTooltip(QueuedTooltip.create(getTooltip(itemStack)));
-    }
-    
-    /**
-     * @deprecated Not used anymore, see {@link Renderer#getQueuedTooltip(float)}
-     */
-    @ToBeRemoved
-    @Deprecated
-    protected List<String> getTooltip(ItemStack itemStack) {
-        List<String> toolTip = Lists.newArrayList(EntryListWidget.tryGetItemStackToolTip(itemStack, true));
-        toolTip.addAll(getExtraItemToolTips(itemStack));
-        if (RoughlyEnoughItemsCore.getConfigManager().getConfig().shouldAppendModNames()) {
-            final String modString = ClientHelper.getInstance().getFormattedModFromItem(itemStack.getItem());
-            String s1 = ClientHelper.getInstance().getModFromItem(itemStack.getItem()).toLowerCase(Locale.ROOT);
-            if (!modString.isEmpty()) {
-                toolTip.removeIf(s -> !s.equals(toolTip.get(0)) && Formatting.strip(s).equalsIgnoreCase(s1));
-                toolTip.add(modString);
-            }
-        }
-        return toolTip;
-    }
-    
-    /**
-     * @deprecated See {@link ItemStackRenderer#getExtraToolTips(ItemStack)}
-     */
-    @ToBeRemoved
-    @Deprecated
-    protected List<String> getExtraItemToolTips(ItemStack stack) {
-        return Collections.emptyList();
-    }
-    
-    /**
-     * @deprecated See {@link FluidRenderer#getExtraToolTips(Fluid)}
-     */
-    @ToBeRemoved
-    @Deprecated
-    protected List<String> getExtraFluidToolTips(Fluid fluid) {
-        return Collections.emptyList();
-    }
-    
-    @ToBeRemoved
-    @Deprecated
-    public ItemStack getCurrentItemStack() {
-        if (getCurrentRenderer() instanceof ItemStackRenderer)
-            return ((ItemStackRenderer) getCurrentRenderer()).getItemStack();
-        return ItemStack.EMPTY;
-    }
-    
-    public Renderer getCurrentRenderer() {
-        if (renderers.isEmpty())
-            return Renderer.empty();
-        return renderers.get(MathHelper.floor((System.currentTimeMillis() / 500 % (double) renderers.size()) / 1f));
-    }
-    
-    /**
-     * @param itemList the list of items
-     * @deprecated Use {@link SlotWidget#setRenderers(List)}
-     */
-    @ToBeRemoved
-    @Deprecated
-    public void setItemList(List<ItemStack> itemList) {
-        setRenderers(CollectionUtils.map(itemList, ITEM_STACK_RENDERER));
-    }
-    
-    public void setRenderers(List<Renderer> renderers) {
-        this.renderers = renderers;
-    }
-    
-    @Override
-    public Rectangle getBounds() {
-        return bounds;
-    }
-    
-    @Override
-    public boolean mouseClicked(double mouseX, double mouseY, int button) {
-        if (!clickToMoreRecipes)
-            return false;
-        EntryStack entry = getCurrentRenderer().getEntry();
-        if (getBounds().contains(mouseX, mouseY))
-            if (button == 0)
-                return ClientHelper.getInstance().executeRecipeKeyBind(entry);
-            else if (button == 1)
-                return ClientHelper.getInstance().executeUsageKeyBind(entry);
-        return false;
-    }
-    
-    @ToBeRemoved
-    @Deprecated
-    public boolean isCurrentRendererItem() {
-        return getCurrentRenderer() instanceof ItemStackRenderer;
-    }
-    
-    @ToBeRemoved
-    @Deprecated
-    public boolean isCurrentRendererFluid() {
-        return getCurrentRenderer() instanceof FluidRenderer;
-    }
-    
-    @Override
-    public boolean keyPressed(int int_1, int int_2, int int_3) {
-        if (!clickToMoreRecipes)
-            return false;
-        EntryStack entry = getCurrentRenderer().getEntry();
-        if (getBounds().contains(PointHelper.fromMouse()))
-            if (ClientHelper.getInstance().getRecipeKeyBinding().matchesKey(int_1, int_2))
-                return ClientHelper.getInstance().executeRecipeKeyBind(entry);
-            else if (ClientHelper.getInstance().getUsageKeyBinding().matchesKey(int_1, int_2))
-                return ClientHelper.getInstance().executeUsageKeyBind(entry);
-        return false;
-    }
-    
-}

+ 1 - 1
src/main/java/me/shedaniel/rei/gui/widget/TabWidget.java

@@ -5,8 +5,8 @@
 
 package me.shedaniel.rei.gui.widget;
 
-import me.shedaniel.math.api.Rectangle;
 import com.mojang.blaze3d.systems.RenderSystem;
+import me.shedaniel.math.api.Rectangle;
 import me.shedaniel.rei.api.ClientHelper;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeCategory;

+ 2 - 2
src/main/java/me/shedaniel/rei/gui/widget/Widget.java

@@ -27,11 +27,11 @@ public abstract class Widget extends AbstractParentElement implements Drawable {
     protected final TextRenderer font = minecraft.textRenderer;
     
     public int getZ() {
-        return this.blitOffset;
+        return this.getBlitOffset();
     }
     
     public void setZ(int z) {
-        this.blitOffset = z;
+        this.setBlitOffset(z);
     }
     
 }

+ 2 - 2
src/main/java/me/shedaniel/rei/impl/AbstractEntryStack.java

@@ -68,11 +68,11 @@ public abstract class AbstractEntryStack extends DrawableHelper implements Entry
     
     @Override
     public int getZ() {
-        return blitOffset;
+        return getBlitOffset();
     }
     
     @Override
     public void setZ(int z) {
-        blitOffset = z;
+        setBlitOffset(z);
     }
 }

+ 1 - 0
src/main/java/me/shedaniel/rei/impl/BaseBoundsHandlerImpl.java

@@ -97,6 +97,7 @@ public class BaseBoundsHandlerImpl implements BaseBoundsHandler {
         int hashCode = 31 + (rectangle == null ? 0 : rectangle.hashCode());
         for (Rectangle e : exclusionZones)
             hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
+        // hashCode -= (e == null ? 0 : e.hashCode());
         return hashCode;
     }
     

+ 0 - 6
src/main/java/me/shedaniel/rei/impl/EmptyEntryStack.java

@@ -6,7 +6,6 @@
 package me.shedaniel.rei.impl;
 
 import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.rei.api.Entry;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.gui.widget.QueuedTooltip;
 import net.minecraft.util.Identifier;
@@ -48,11 +47,6 @@ public class EmptyEntryStack extends AbstractEntryStack {
         return true;
     }
     
-    @Override
-    public Entry toEntry() {
-        return null;
-    }
-    
     @Override
     public EntryStack copy() {
         return this;

+ 0 - 53
src/main/java/me/shedaniel/rei/impl/FluidEntry.java

@@ -1,53 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.impl;
-
-import me.shedaniel.rei.api.Entry;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
-import net.minecraft.fluid.Fluid;
-import net.minecraft.item.ItemStack;
-
-import javax.annotation.Nullable;
-
-@ToBeRemoved
-@Deprecated
-public class FluidEntry implements Entry {
-    private Fluid fluid;
-    
-    @Deprecated
-    public FluidEntry(Fluid fluid) {
-        this.fluid = fluid;
-    }
-    
-    @Override
-    public Type getEntryType() {
-        return Type.FLUID;
-    }
-    
-    @Nullable
-    @Override
-    public ItemStack getItemStack() {
-        return null;
-    }
-    
-    @Nullable
-    @Override
-    public Fluid getFluid() {
-        return fluid;
-    }
-    
-    @Override
-    public Entry clone() {
-        return this;
-    }
-    
-    @Override
-    public boolean equalsEntry(Entry other, boolean checkTags) {
-        if (other.getEntryType() == Type.FLUID) {
-            return other.getFluid().matchesType(getFluid());
-        } else return false;
-    }
-}

+ 0 - 6
src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java

@@ -9,7 +9,6 @@ import com.google.common.collect.Lists;
 import me.shedaniel.math.api.Rectangle;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.ClientHelper;
-import me.shedaniel.rei.api.Entry;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.gui.widget.EntryListWidget;
 import me.shedaniel.rei.gui.widget.QueuedTooltip;
@@ -91,11 +90,6 @@ public class FluidEntryStack extends AbstractEntryStack {
         return amount <= 0 || fluid == Fluids.EMPTY;
     }
     
-    @Override
-    public Entry toEntry() {
-        return Entry.create(getFluid());
-    }
-    
     @Override
     public EntryStack copy() {
         EntryStack stack = EntryStack.create(fluid, amount);

+ 6 - 13
src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java

@@ -6,11 +6,10 @@
 package me.shedaniel.rei.impl;
 
 import com.google.common.collect.Lists;
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.math.compat.RenderHelper;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.ClientHelper;
-import me.shedaniel.rei.api.Entry;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.ItemStackRenderOverlayHook;
 import me.shedaniel.rei.gui.widget.EntryListWidget;
@@ -61,11 +60,6 @@ public class ItemEntryStack extends AbstractEntryStack {
         return itemStack.isEmpty();
     }
     
-    @Override
-    public Entry toEntry() {
-        return Entry.create(getItemStack());
-    }
-    
     @Override
     public EntryStack copy() {
         EntryStack stack = EntryStack.create(getItemStack().copy());
@@ -140,14 +134,13 @@ public class ItemEntryStack extends AbstractEntryStack {
         if (getSetting(Settings.RENDER).value().get()) {
             ItemStack stack = getItemStack().copy();
             ((ItemStackRenderOverlayHook) (Object) stack).rei_setRenderOverlay(getSetting(Settings.Item.RENDER_OVERLAY).value().get());
-            RenderHelper.color4f(1.0F, 1.0F, 1.0F, 1.0F);
+            RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
             ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
             itemRenderer.zOffset = getZ();
-            GuiLighting.enableForItems();
-            RenderHelper.colorMask(true, true, true, true);
-            RenderHelper.enableLighting();
-            RenderHelper.enableRescaleNormal();
-            RenderHelper.enableDepthTest();
+            RenderSystem.colorMask(true, true, true, true);
+            RenderSystem.enableLighting();
+            RenderSystem.enableRescaleNormal();
+            RenderSystem.enableDepthTest();
             int i1 = bounds.getCenterX() - 8;
             int i2 = bounds.getCenterY() - 8;
             itemRenderer.renderGuiItem(stack, i1, i2);

+ 0 - 53
src/main/java/me/shedaniel/rei/impl/ItemStackEntry.java

@@ -1,53 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.impl;
-
-import me.shedaniel.rei.api.Entry;
-import me.shedaniel.rei.api.annotations.ToBeRemoved;
-import net.minecraft.fluid.Fluid;
-import net.minecraft.item.ItemStack;
-
-import javax.annotation.Nullable;
-
-@ToBeRemoved
-@Deprecated
-public class ItemStackEntry implements Entry {
-    private ItemStack itemStack;
-    
-    @Deprecated
-    public ItemStackEntry(ItemStack itemStack) {
-        this.itemStack = itemStack;
-    }
-    
-    @Override
-    public Type getEntryType() {
-        return Type.ITEM;
-    }
-    
-    @Nullable
-    @Override
-    public ItemStack getItemStack() {
-        return itemStack;
-    }
-    
-    @Nullable
-    @Override
-    public Fluid getFluid() {
-        return null;
-    }
-    
-    @Override
-    public Entry clone() {
-        return Entry.create(getItemStack().copy());
-    }
-    
-    @Override
-    public boolean equalsEntry(Entry other, boolean checkTags) {
-        if (other.getEntryType() == Type.ITEM) {
-            return checkTags ? ItemStack.areEqualIgnoreDamage(other.getItemStack(), getItemStack()) : other.getItemStack().isItemEqualIgnoreDamage(getItemStack());
-        } else return false;
-    }
-}

+ 9 - 11
src/main/java/me/shedaniel/rei/impl/RecipeHelperImpl.java

@@ -15,7 +15,6 @@ import net.fabricmc.loader.api.FabricLoader;
 import net.fabricmc.loader.api.SemanticVersion;
 import net.fabricmc.loader.api.Version;
 import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
-import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.recipe.RecipeManager;
 import net.minecraft.util.ActionResult;
@@ -49,13 +48,13 @@ public class RecipeHelperImpl implements RecipeHelper {
     private final Map<Identifier, List<RecipeDisplay>> recipeCategoryListMap = Maps.newHashMap();
     private final List<RecipeCategory> categories = Lists.newArrayList();
     private final Map<Identifier, ButtonAreaSupplier> speedCraftAreaSupplierMap = Maps.newHashMap();
-    private final Map<Identifier, List<List<ItemStack>>> categoryWorkingStations = Maps.newHashMap();
+    private final Map<Identifier, List<List<EntryStack>>> categoryWorkingStations = Maps.newHashMap();
     private final List<DisplayVisibilityHandler> displayVisibilityHandlers = Lists.newArrayList();
     private final List<LiveRecipeGenerator<?>> liveRecipeGenerators = Lists.newArrayList();
     private RecipeManager recipeManager;
     
     @Override
-    public List<EntryStack> findCraftableEntriesByItems(List<ItemStack> inventoryItems) {
+    public List<EntryStack> findCraftableEntriesByItems(List<EntryStack> inventoryItems) {
         List<EntryStack> craftables = new ArrayList<>();
         for (List<RecipeDisplay> value : recipeCategoryListMap.values())
             for (RecipeDisplay recipeDisplay : value) {
@@ -67,10 +66,9 @@ public class RecipeHelperImpl implements RecipeHelper {
                         continue;
                     }
                     boolean slotDone = false;
-                    for (ItemStack possibleType : inventoryItems) {
-                        EntryStack possibleEntryStack = EntryStack.create(possibleType);
+                    for (EntryStack possibleType : inventoryItems) {
                         for (EntryStack slotPossible : slot)
-                            if (possibleEntryStack.equals(slotPossible)) {
+                            if (possibleType.equals(slotPossible)) {
                                 slotsCraftable++;
                                 slotDone = true;
                                 break;
@@ -93,17 +91,17 @@ public class RecipeHelperImpl implements RecipeHelper {
     }
     
     @Override
-    public void registerWorkingStations(Identifier category, List<ItemStack>... workingStations) {
+    public void registerWorkingStations(Identifier category, List<EntryStack>... workingStations) {
         categoryWorkingStations.get(category).addAll(Arrays.asList(workingStations));
     }
     
     @Override
-    public void registerWorkingStations(Identifier category, ItemStack... workingStations) {
+    public void registerWorkingStations(Identifier category, EntryStack... workingStations) {
         categoryWorkingStations.get(category).addAll(Arrays.asList(workingStations).stream().map(Collections::singletonList).collect(Collectors.toList()));
     }
     
     @Override
-    public List<List<ItemStack>> getWorkingStations(Identifier category) {
+    public List<List<EntryStack>> getWorkingStations(Identifier category) {
         return categoryWorkingStations.get(category);
     }
     
@@ -249,7 +247,7 @@ public class RecipeHelperImpl implements RecipeHelper {
         });
         RoughlyEnoughItemsCore.LOGGER.info("[REI] Loading %d plugins: %s", plugins.size(), plugins.stream().map(REIPluginEntry::getPluginIdentifier).map(Identifier::toString).collect(Collectors.joining(", ")));
         Collections.reverse(plugins);
-        RoughlyEnoughItemsCore.getEntryRegistry().getModifiableEntryList().clear();
+        RoughlyEnoughItemsCore.getEntryRegistry().getStacksList().clear();
         Version reiVersion = FabricLoader.getInstance().getModContainer("roughlyenoughitems").get().getMetadata().getVersion();
         if (!(reiVersion instanceof SemanticVersion))
             RoughlyEnoughItemsCore.LOGGER.warn("[REI] Roughly Enough Items is not using semantic versioning, will be ignoring plugins' minimum versions!");
@@ -301,7 +299,7 @@ public class RecipeHelperImpl implements RecipeHelper {
         ScreenHelper.getOptionalOverlay().ifPresent(overlay -> overlay.shouldReInit = true);
         
         long usedTime = System.currentTimeMillis() - startTime;
-        RoughlyEnoughItemsCore.LOGGER.info("[REI] Registered %d stack entries, %d recipes displays, %d bounds handler, %d visibility handlers and %d categories (%s) in %d ms.", RoughlyEnoughItemsCore.getEntryRegistry().getEntryList().size(), recipeCount.get(), RoughlyEnoughItemsCore.getDisplayHelper().getAllBoundsHandlers().size(), getDisplayVisibilityHandlers().size(), categories.size(), String.join(", ", categories.stream().map(RecipeCategory::getCategoryName).collect(Collectors.toList())), usedTime);
+        RoughlyEnoughItemsCore.LOGGER.info("[REI] Registered %d stack entries, %d recipes displays, %d bounds handler, %d visibility handlers and %d categories (%s) in %d ms.", RoughlyEnoughItemsCore.getEntryRegistry().getStacksList().size(), recipeCount.get(), RoughlyEnoughItemsCore.getDisplayHelper().getAllBoundsHandlers().size(), getDisplayVisibilityHandlers().size(), categories.size(), String.join(", ", categories.stream().map(RecipeCategory::getCategoryName).collect(Collectors.toList())), usedTime);
     }
     
     @Override

+ 1 - 1
src/main/java/me/shedaniel/rei/mixin/MixinBrewingRecipeRegistry.java

@@ -54,7 +54,7 @@ public class MixinBrewingRecipeRegistry {
         if (!REGISTERED_POTION_TYPES.contains(potion_2))
             rei_registerPotionType(potion_2);
         for (Ingredient type : SELF_POTION_TYPES) {
-            for (ItemStack stack : type.getStackArray()) {
+            for (ItemStack stack : type.getMatchingStacksClient()) {
                 DefaultPlugin.registerBrewingDisplay(new DefaultBrewingDisplay(PotionUtil.setPotion(stack.copy(), potion_1), Ingredient.ofItems(new ItemConvertible[]{item_1}), PotionUtil.setPotion(stack.copy(), potion_2)));
             }
         }

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

@@ -272,14 +272,14 @@ public class DefaultPlugin implements REIPluginV0 {
         if (!RoughlyEnoughItemsCore.getConfigManager().getConfig().isLoadingDefaultPlugin()) {
             return;
         }
-        recipeHelper.registerWorkingStations(CRAFTING, new ItemStack(Items.CRAFTING_TABLE));
-        recipeHelper.registerWorkingStations(SMELTING, new ItemStack(Items.FURNACE));
-        recipeHelper.registerWorkingStations(SMOKING, new ItemStack(Items.SMOKER));
-        recipeHelper.registerWorkingStations(BLASTING, new ItemStack(Items.BLAST_FURNACE));
-        recipeHelper.registerWorkingStations(CAMPFIRE, new ItemStack(Items.CAMPFIRE));
-        recipeHelper.registerWorkingStations(BREWING, new ItemStack(Items.BREWING_STAND));
-        recipeHelper.registerWorkingStations(STONE_CUTTING, new ItemStack(Items.STONECUTTER));
-        recipeHelper.registerWorkingStations(COMPOSTING, new ItemStack(Items.COMPOSTER));
+        recipeHelper.registerWorkingStations(CRAFTING, EntryStack.create(Items.CRAFTING_TABLE));
+        recipeHelper.registerWorkingStations(SMELTING, EntryStack.create(Items.FURNACE));
+        recipeHelper.registerWorkingStations(SMOKING, EntryStack.create(Items.SMOKER));
+        recipeHelper.registerWorkingStations(BLASTING, EntryStack.create(Items.BLAST_FURNACE));
+        recipeHelper.registerWorkingStations(CAMPFIRE, EntryStack.create(Items.CAMPFIRE));
+        recipeHelper.registerWorkingStations(BREWING, EntryStack.create(Items.BREWING_STAND));
+        recipeHelper.registerWorkingStations(STONE_CUTTING, EntryStack.create(Items.STONECUTTER));
+        recipeHelper.registerWorkingStations(COMPOSTING, EntryStack.create(Items.COMPOSTER));
         recipeHelper.registerAutoCraftButtonArea(CAMPFIRE, bounds -> null);
         recipeHelper.registerAutoCraftButtonArea(COMPOSTING, bounds -> null);
         recipeHelper.registerScreenClickArea(new Rectangle(88, 32, 28, 23), CraftingTableScreen.class, CRAFTING);

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

@@ -10,6 +10,7 @@ import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.impl.ScreenHelper;
 import me.shedaniel.rei.listeners.RecipeBookGuiHooks;
 import me.shedaniel.rei.plugin.blasting.DefaultBlastingDisplay;
+import me.shedaniel.rei.plugin.cooking.DefaultCookingDisplay;
 import me.shedaniel.rei.plugin.crafting.DefaultCraftingDisplay;
 import me.shedaniel.rei.plugin.smelting.DefaultSmeltingDisplay;
 import me.shedaniel.rei.plugin.smoking.DefaultSmokingDisplay;
@@ -54,36 +55,8 @@ public class DefaultRecipeBookHandler implements AutoTransferHandler {
                 context.getMinecraft().interactionManager.clickRecipe(container.syncId, recipe, Screen.hasShiftDown());
                 ScreenHelper.getLastOverlay().init();
             }
-        } else if (display instanceof DefaultSmeltingDisplay) {
-            DefaultSmeltingDisplay defaultDisplay = (DefaultSmeltingDisplay) display;
-            if (defaultDisplay.getOptionalRecipe().isPresent()) {
-                Recipe<?> recipe = (defaultDisplay).getOptionalRecipe().get();
-                if (!context.getMinecraft().player.getRecipeBook().contains(recipe))
-                    return Result.createFailed(I18n.translate("error.rei.recipe.not.unlocked"));
-                if (!context.isActuallyCrafting())
-                    return Result.createSuccessful();
-                context.getMinecraft().openScreen(context.getContainerScreen());
-                if (context.getContainerScreen() instanceof RecipeBookProvider)
-                    ((RecipeBookGuiHooks) ((RecipeBookProvider) context.getContainerScreen()).getRecipeBookGui()).rei_getGhostSlots().reset();
-                context.getMinecraft().interactionManager.clickRecipe(container.syncId, recipe, Screen.hasShiftDown());
-                ScreenHelper.getLastOverlay().init();
-            }
-        } else if (display instanceof DefaultSmokingDisplay) {
-            DefaultSmokingDisplay defaultDisplay = (DefaultSmokingDisplay) display;
-            if (defaultDisplay.getOptionalRecipe().isPresent()) {
-                Recipe<?> recipe = (defaultDisplay).getOptionalRecipe().get();
-                if (!context.getMinecraft().player.getRecipeBook().contains(recipe))
-                    return Result.createFailed(I18n.translate("error.rei.recipe.not.unlocked"));
-                if (!context.isActuallyCrafting())
-                    return Result.createSuccessful();
-                context.getMinecraft().openScreen(context.getContainerScreen());
-                if (context.getContainerScreen() instanceof RecipeBookProvider)
-                    ((RecipeBookGuiHooks) ((RecipeBookProvider) context.getContainerScreen()).getRecipeBookGui()).rei_getGhostSlots().reset();
-                context.getMinecraft().interactionManager.clickRecipe(container.syncId, recipe, Screen.hasShiftDown());
-                ScreenHelper.getLastOverlay().init();
-            }
-        } else if (display instanceof DefaultBlastingDisplay) {
-            DefaultBlastingDisplay defaultDisplay = (DefaultBlastingDisplay) display;
+        } else if (display instanceof DefaultCookingDisplay) {
+            DefaultCookingDisplay defaultDisplay = (DefaultCookingDisplay) display;
             if (defaultDisplay.getOptionalRecipe().isPresent()) {
                 Recipe<?> recipe = (defaultDisplay).getOptionalRecipe().get();
                 if (!context.getMinecraft().player.getRecipeBook().contains(recipe))

+ 1 - 1
src/main/java/me/shedaniel/rei/plugin/brewing/DefaultBrewingCategory.java

@@ -5,9 +5,9 @@
 
 package me.shedaniel.rei.plugin.brewing;
 
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Point;
 import me.shedaniel.math.api.Rectangle;
-import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeCategory;
 import me.shedaniel.rei.gui.widget.EntryWidget;

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

@@ -30,7 +30,7 @@ public class DefaultBrewingDisplay implements RecipeDisplay {
         if (this.input.getItem() instanceof PotionItem)
             this.input = this.input.setting(EntryStack.Settings.CHECK_TAGS, EntryStack.Settings.TRUE);
         this.reactant = new ArrayList<>();
-        for (ItemStack stack : reactant.getStackArray()) {
+        for (ItemStack stack : reactant.getMatchingStacksClient()) {
             EntryStack entryStack = EntryStack.create(stack);
             if (stack.getItem() instanceof PotionItem)
                 entryStack.setting(EntryStack.Settings.CHECK_TAGS, EntryStack.Settings.TRUE);

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

@@ -5,9 +5,9 @@
 
 package me.shedaniel.rei.plugin.campfire;
 
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Point;
 import me.shedaniel.math.api.Rectangle;
-import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeCategory;
 import me.shedaniel.rei.gui.widget.EntryWidget;

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

@@ -36,7 +36,7 @@ public class DefaultCampfireDisplay implements RecipeDisplay {
     public DefaultCampfireDisplay(DefaultedList<Ingredient> ingredients, ItemStack output, int cookTime) {
         this.inputs = ingredients.stream().map(i -> {
             List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : i.getStackArray()) {
+            for (ItemStack stack : i.getMatchingStacksClient()) {
                 entries.add(EntryStack.create(stack));
             }
             return entries;

+ 14 - 6
src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingCategory.java

@@ -6,13 +6,14 @@
 package me.shedaniel.rei.plugin.composting;
 
 import com.google.common.collect.Lists;
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Point;
 import me.shedaniel.math.api.Rectangle;
-import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeCategory;
-import me.shedaniel.rei.gui.renderers.RecipeRenderer;
+import me.shedaniel.rei.gui.entries.RecipeEntry;
 import me.shedaniel.rei.gui.widget.EntryWidget;
+import me.shedaniel.rei.gui.widget.QueuedTooltip;
 import me.shedaniel.rei.gui.widget.RecipeBaseWidget;
 import me.shedaniel.rei.gui.widget.Widget;
 import me.shedaniel.rei.plugin.DefaultPlugin;
@@ -24,6 +25,7 @@ import net.minecraft.item.ItemConvertible;
 import net.minecraft.util.Identifier;
 import net.minecraft.util.math.MathHelper;
 
+import javax.annotation.Nullable;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
@@ -48,16 +50,22 @@ public class DefaultCompostingCategory implements RecipeCategory<DefaultComposti
     }
     
     @Override
-    public RecipeRenderer getSimpleRenderer(DefaultCompostingDisplay recipe) {
-        return new RecipeRenderer() {
+    public RecipeEntry getSimpleRenderer(DefaultCompostingDisplay recipe) {
+        return new RecipeEntry() {
             @Override
             public int getHeight() {
                 return 10 + MinecraftClient.getInstance().textRenderer.fontHeight;
             }
             
+            @Nullable
+            @Override
+            public QueuedTooltip getTooltip(int mouseX, int mouseY) {
+                return null;
+            }
+            
             @Override
-            public void render(int x, int y, double mouseX, double mouseY, float delta) {
-                MinecraftClient.getInstance().textRenderer.draw(I18n.translate("text.rei.composting.page", recipe.getPage() + 1), x + 5, y + 6, -1);
+            public void render(Rectangle rectangle, int mouseX, int mouseY, float delta) {
+                MinecraftClient.getInstance().textRenderer.draw(I18n.translate("text.rei.composting.page", recipe.getPage() + 1), rectangle.x + 5, rectangle.y + 6, -1);
             }
         };
     }

+ 9 - 8
src/main/java/me/shedaniel/rei/plugin/cooking/DefaultCookingCategory.java

@@ -5,14 +5,14 @@
 
 package me.shedaniel.rei.plugin.cooking;
 
+import com.mojang.blaze3d.systems.RenderSystem;
 import it.unimi.dsi.fastutil.ints.IntList;
 import me.shedaniel.math.api.Point;
 import me.shedaniel.math.api.Rectangle;
-import me.shedaniel.math.compat.RenderHelper;
 import me.shedaniel.rei.api.EntryStack;
-import me.shedaniel.rei.api.Renderer;
 import me.shedaniel.rei.api.TransferRecipeCategory;
-import me.shedaniel.rei.gui.renderers.RecipeRenderer;
+import me.shedaniel.rei.gui.entries.RecipeEntry;
+import me.shedaniel.rei.gui.renderers.SimpleRecipeEntry;
 import me.shedaniel.rei.gui.widget.EntryWidget;
 import me.shedaniel.rei.gui.widget.RecipeArrowWidget;
 import me.shedaniel.rei.gui.widget.RecipeBaseWidget;
@@ -26,6 +26,7 @@ import net.minecraft.util.Identifier;
 import net.minecraft.util.math.MathHelper;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.function.Supplier;
@@ -44,11 +45,11 @@ public class DefaultCookingCategory implements TransferRecipeCategory<DefaultCoo
     @Override
     public void renderRedSlots(List<Widget> widgets, Rectangle bounds, DefaultCookingDisplay display, IntList redSlots) {
         Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 27);
-        RenderHelper.translatef(0, 0, 400);
+        RenderSystem.translatef(0, 0, 400);
         if (redSlots.contains(0)) {
             DrawableHelper.fill(startPoint.x + 1, startPoint.y + 1, startPoint.x + 1 + 16, startPoint.y + 1 + 16, 822018048);
         }
-        RenderHelper.translatef(0, 0, -400);
+        RenderSystem.translatef(0, 0, -400);
     }
     
     @Override
@@ -58,7 +59,7 @@ public class DefaultCookingCategory implements TransferRecipeCategory<DefaultCoo
             @Override
             public void render(int mouseX, int mouseY, float delta) {
                 super.render(mouseX, mouseY, delta);
-                RenderHelper.color4f(1.0F, 1.0F, 1.0F, 1.0F);
+                RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
                 GuiLighting.disable();
                 MinecraftClient.getInstance().getTextureManager().bindTexture(DefaultPlugin.getDisplayTexture());
                 blit(startPoint.x, startPoint.y, 0, 54, 82, 54);
@@ -75,8 +76,8 @@ public class DefaultCookingCategory implements TransferRecipeCategory<DefaultCoo
     }
     
     @Override
-    public RecipeRenderer getSimpleRenderer(DefaultCookingDisplay recipe) {
-        return Renderer.fromRecipeEntries(() -> Arrays.asList(recipe.getInputEntries().get(0)), recipe::getOutputEntries);
+    public RecipeEntry getSimpleRenderer(DefaultCookingDisplay recipe) {
+        return SimpleRecipeEntry.create(Collections.singletonList(recipe.getInputEntries().get(0)), recipe.getOutputEntries());
     }
     
     @Override

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

@@ -8,6 +8,7 @@ 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.minecraft.block.entity.FurnaceBlockEntity;
 import net.minecraft.client.resource.language.I18n;
 import net.minecraft.container.Container;
@@ -17,7 +18,10 @@ import net.minecraft.recipe.AbstractCookingRecipe;
 import net.minecraft.util.Formatting;
 import net.minecraft.util.Identifier;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
@@ -29,7 +33,7 @@ public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
         this.recipe = recipe;
         this.input = recipe.getPreviewInputs().stream().map(i -> {
             List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : i.getStackArray()) {
+            for (ItemStack stack : i.getMatchingStacksClient()) {
                 entries.add(EntryStack.create(stack));
             }
             return entries;
@@ -78,7 +82,8 @@ public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
     }
     
     @Override
-    public List<List<ItemStack>> getOrganisedInput(ContainerInfo<Container> containerInfo, Container container) {
-        return recipe.getPreviewInputs().stream().map(i -> Arrays.asList(i.getStackArray())).collect(Collectors.toList());
+    public List<List<EntryStack>> getOrganisedInputEntries(ContainerInfo<Container> containerInfo, Container container) {
+        return CollectionUtils.map(recipe.getPreviewInputs(), i -> CollectionUtils.map(i.getMatchingStacksClient(), EntryStack::create));
     }
+    
 }

+ 3 - 7
src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingCategory.java

@@ -6,16 +6,14 @@
 package me.shedaniel.rei.plugin.crafting;
 
 import com.google.common.collect.Lists;
+import com.mojang.blaze3d.systems.RenderSystem;
 import it.unimi.dsi.fastutil.ints.IntList;
 import me.shedaniel.math.api.Point;
 import me.shedaniel.math.api.Rectangle;
 import me.shedaniel.rei.api.EntryStack;
-import com.mojang.blaze3d.systems.RenderSystem;
-import me.shedaniel.rei.api.Renderer;
 import me.shedaniel.rei.api.TransferRecipeCategory;
 import me.shedaniel.rei.gui.widget.EntryWidget;
 import me.shedaniel.rei.gui.widget.RecipeBaseWidget;
-import me.shedaniel.rei.gui.widget.SlotWidget;
 import me.shedaniel.rei.gui.widget.Widget;
 import me.shedaniel.rei.plugin.DefaultPlugin;
 import net.minecraft.block.Blocks;
@@ -23,11 +21,9 @@ import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.DrawableHelper;
 import net.minecraft.client.render.GuiLighting;
 import net.minecraft.client.resource.language.I18n;
-import net.minecraft.item.ItemStack;
 import net.minecraft.util.Identifier;
 
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.function.Supplier;
@@ -51,8 +47,8 @@ public class DefaultCraftingCategory implements TransferRecipeCategory<DefaultCr
     }
     
     @Override
-    public Renderer getIcon() {
-        return Renderer.fromItemStack(new ItemStack(Blocks.CRAFTING_TABLE));
+    public EntryStack getLogo() {
+        return EntryStack.create(Blocks.CRAFTING_TABLE);
     }
     
     @Override

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

@@ -28,7 +28,7 @@ public class DefaultShapedDisplay implements DefaultCraftingDisplay {
         this.display = recipe;
         this.input = recipe.getPreviewInputs().stream().map(i -> {
             List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : i.getStackArray()) {
+            for (ItemStack stack : i.getMatchingStacksClient()) {
                 if (stack.getItem() instanceof PotionItem)
                     entries.add(EntryStack.create(stack).setting(EntryStack.Settings.CHECK_TAGS, EntryStack.Settings.TRUE));
                 else entries.add(EntryStack.create(stack));

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

@@ -28,7 +28,7 @@ public class DefaultShapelessDisplay implements DefaultCraftingDisplay {
         this.display = recipe;
         this.input = recipe.getPreviewInputs().stream().map(i -> {
             List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : i.getStackArray()) {
+            for (ItemStack stack : i.getMatchingStacksClient()) {
                 if (stack.getItem() instanceof PotionItem)
                     entries.add(EntryStack.create(stack).setting(EntryStack.Settings.CHECK_TAGS, EntryStack.Settings.TRUE));
                 else entries.add(EntryStack.create(stack));

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

@@ -5,12 +5,11 @@
 
 package me.shedaniel.rei.plugin.stonecutting;
 
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Point;
 import me.shedaniel.math.api.Rectangle;
-import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeCategory;
-import me.shedaniel.rei.api.Renderer;
 import me.shedaniel.rei.gui.widget.EntryWidget;
 import me.shedaniel.rei.gui.widget.RecipeBaseWidget;
 import me.shedaniel.rei.gui.widget.Widget;
@@ -19,7 +18,6 @@ import net.minecraft.block.Blocks;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.render.GuiLighting;
 import net.minecraft.client.resource.language.I18n;
-import net.minecraft.item.ItemStack;
 import net.minecraft.util.Identifier;
 
 import java.util.Arrays;

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

@@ -35,7 +35,7 @@ public class DefaultStoneCuttingDisplay implements RecipeDisplay {
     public DefaultStoneCuttingDisplay(DefaultedList<Ingredient> ingredients, ItemStack output) {
         this.inputs = ingredients.stream().map(i -> {
             List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : i.getStackArray()) {
+            for (ItemStack stack : i.getMatchingStacksClient()) {
                 entries.add(EntryStack.create(stack));
             }
             return entries;

+ 1 - 1
src/main/java/me/shedaniel/rei/plugin/stripping/DefaultStrippingCategory.java

@@ -5,9 +5,9 @@
 
 package me.shedaniel.rei.plugin.stripping;
 
+import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.math.api.Point;
 import me.shedaniel.math.api.Rectangle;
-import com.mojang.blaze3d.systems.RenderSystem;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeCategory;
 import me.shedaniel.rei.gui.widget.EntryWidget;

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

@@ -1,3 +1,8 @@
+/*
+ * Roughly Enough Items by Danielshe.
+ * Licensed under the MIT License.
+ */
+
 package me.shedaniel.rei.utils;
 
 import me.shedaniel.rei.api.EntryStack;
@@ -151,6 +156,14 @@ public class CollectionUtils {
         return sum;
     }
     
+    public static final <T> int sumInt(List<Integer> list) {
+        int sum = 0;
+        for (Integer t : list) {
+            sum += t;
+        }
+        return sum;
+    }
+    
     public static final <T> double sumDouble(List<T> list, Function<T, Double> function) {
         double sum = 0;
         for (T t : list) {
@@ -158,4 +171,12 @@ public class CollectionUtils {
         }
         return sum;
     }
+    
+    public static final <T> double sumDouble(List<Double> list) {
+        double sum = 0;
+        for (Double t : list) {
+            sum += t;
+        }
+        return sum;
+    }
 }