Procházet zdrojové kódy

up to 4x faster search

Unknown před 6 roky
rodič
revize
8d8f43ca96
43 změnil soubory, kde provedl 275 přidání a 185 odebrání
  1. 16 0
      src/main/java/me/shedaniel/rei/api/AutoCraftingHandler.java
  2. 1 1
      src/main/java/me/shedaniel/rei/api/DisplayHelper.java
  3. 5 3
      src/main/java/me/shedaniel/rei/api/DisplaySettings.java
  4. 3 1
      src/main/java/me/shedaniel/rei/api/DisplayVisibilityHandler.java
  5. 4 4
      src/main/java/me/shedaniel/rei/api/RecipeCategory.java
  6. 1 8
      src/main/java/me/shedaniel/rei/api/RecipeDisplay.java
  7. 5 1
      src/main/java/me/shedaniel/rei/api/RecipeHelper.java
  8. 0 33
      src/main/java/me/shedaniel/rei/api/RelativePoint.java
  9. 6 17
      src/main/java/me/shedaniel/rei/api/Renderable.java
  10. 12 1
      src/main/java/me/shedaniel/rei/api/Renderer.java
  11. 1 0
      src/main/java/me/shedaniel/rei/client/ClientHelperImpl.java
  12. 30 2
      src/main/java/me/shedaniel/rei/client/ConfigObject.java
  13. 42 6
      src/main/java/me/shedaniel/rei/client/RecipeHelperImpl.java
  14. 9 5
      src/main/java/me/shedaniel/rei/client/ScreenHelper.java
  15. 26 6
      src/main/java/me/shedaniel/rei/client/SearchArgument.java
  16. 7 5
      src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
  17. 1 1
      src/main/java/me/shedaniel/rei/gui/PreRecipeViewingScreen.java
  18. 1 1
      src/main/java/me/shedaniel/rei/gui/config/DisplayVisibility.java
  19. 1 1
      src/main/java/me/shedaniel/rei/gui/config/ItemCheatingMode.java
  20. 1 1
      src/main/java/me/shedaniel/rei/gui/config/ItemListOrdering.java
  21. 0 1
      src/main/java/me/shedaniel/rei/gui/config/ItemListOrderingConfig.java
  22. 4 2
      src/main/java/me/shedaniel/rei/gui/config/RecipeScreenType.java
  23. 1 0
      src/main/java/me/shedaniel/rei/gui/renderables/EmptyRenderer.java
  24. 6 3
      src/main/java/me/shedaniel/rei/gui/widget/AutoCraftingButtonWidget.java
  25. 30 32
      src/main/java/me/shedaniel/rei/gui/widget/ItemListOverlay.java
  26. 1 1
      src/main/java/me/shedaniel/rei/gui/widget/RecipeBaseWidget.java
  27. 3 3
      src/main/java/me/shedaniel/rei/gui/widget/RecipeChoosePageWidget.java
  28. 4 6
      src/main/java/me/shedaniel/rei/gui/widget/SlotWidget.java
  29. 0 16
      src/main/java/me/shedaniel/rei/listeners/CreativePlayerInventoryScreenHooks.java
  30. 2 1
      src/main/java/me/shedaniel/rei/plugin/DefaultAutoCraftingPlugin.java
  31. 2 1
      src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java
  32. 26 0
      src/main/java/me/shedaniel/rei/plugin/autocrafting/AutoCraftingTableHandler.java
  33. 1 1
      src/main/java/me/shedaniel/rei/plugin/blasting/DefaultBlastingDisplay.java
  34. 1 1
      src/main/java/me/shedaniel/rei/plugin/campfire/DefaultCampfireDisplay.java
  35. 9 6
      src/main/java/me/shedaniel/rei/plugin/composting/DefaultCompostingCategory.java
  36. 1 2
      src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingDisplay.java
  37. 1 1
      src/main/java/me/shedaniel/rei/plugin/smelting/DefaultSmeltingDisplay.java
  38. 1 1
      src/main/java/me/shedaniel/rei/plugin/smoking/DefaultSmokingDisplay.java
  39. 4 4
      src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingCategory.java
  40. 1 1
      src/main/java/me/shedaniel/rei/plugin/stonecutting/DefaultStoneCuttingDisplay.java
  41. 4 3
      src/main/java/me/shedaniel/rei/utils/ClothScreenRegistry.java
  42. 1 1
      src/main/resources/fabric.mod.json
  43. 0 1
      src/main/resources/listeners.roughlyenoughitems.json

+ 16 - 0
src/main/java/me/shedaniel/rei/api/AutoCraftingHandler.java

@@ -0,0 +1,16 @@
+package me.shedaniel.rei.api;
+
+import me.shedaniel.rei.gui.ContainerScreenOverlay;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
+
+public interface AutoCraftingHandler {
+    
+    default double getPriority() {
+        return 0d;
+    }
+    
+    boolean handle(MinecraftClient minecraft, Screen recipeViewingScreen, AbstractContainerScreen<?> parentScreen, ContainerScreenOverlay overlay);
+    
+}

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

@@ -60,7 +60,7 @@ public interface DisplayHelper {
          *
          * @return the base class
          */
-        Class getBaseSupportedClass();
+        Class<?> getBaseSupportedClass();
         
         /**
          * Gets the left bounds of the overlay

+ 5 - 3
src/main/java/me/shedaniel/rei/api/DisplaySettings.java

@@ -13,7 +13,7 @@ public interface DisplaySettings<T extends RecipeDisplay> {
      * @param category the category of the display
      * @return the height
      */
-    int getDisplayHeight(RecipeCategory category);
+    int getDisplayHeight(RecipeCategory<?> category);
     
     /**
      * Gets the recipe display width
@@ -22,17 +22,19 @@ public interface DisplaySettings<T extends RecipeDisplay> {
      * @param display  the display of the recipe
      * @return the width
      */
-    int getDisplayWidth(RecipeCategory category, T display);
+    int getDisplayWidth(RecipeCategory<?> category, T display);
     
     /**
      * Gets the maximum amount of recipe displays of the category displayed at the same time.
+     *
      * @param category the category of the displays
      * @return the maximum amount
      */
-    int getMaximumRecipePerPage(RecipeCategory category);
+    int getMaximumRecipePerPage(RecipeCategory<?> category);
     
     /**
      * Gets the fixed amount of recipes per page.
+     *
      * @return the amount of recipes, returns -1 if not fixed
      */
     default int getFixedRecipesPerPage() {

+ 3 - 1
src/main/java/me/shedaniel/rei/api/DisplayVisibilityHandler.java

@@ -5,6 +5,8 @@
 
 package me.shedaniel.rei.api;
 
+import me.shedaniel.rei.gui.config.DisplayVisibility;
+
 public interface DisplayVisibilityHandler {
     
     /**
@@ -26,6 +28,6 @@ public interface DisplayVisibilityHandler {
      * @param display  the display of the recipe
      * @return the visibility
      */
-    DisplayVisibility handleDisplay(RecipeCategory category, RecipeDisplay display);
+    DisplayVisibility handleDisplay(RecipeCategory<?> category, RecipeDisplay display);
     
 }

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

@@ -104,20 +104,20 @@ public interface RecipeCategory<T extends RecipeDisplay> {
      *
      * @return the display settings
      */
-    default DisplaySettings getDisplaySettings() {
+    default DisplaySettings<T> getDisplaySettings() {
         return new DisplaySettings<T>() {
             @Override
-            public int getDisplayHeight(RecipeCategory category) {
+            public int getDisplayHeight(RecipeCategory<?> category) {
                 return 66;
             }
             
             @Override
-            public int getDisplayWidth(RecipeCategory category, T display) {
+            public int getDisplayWidth(RecipeCategory<?> category, T display) {
                 return 150;
             }
             
             @Override
-            public int getMaximumRecipePerPage(RecipeCategory category) {
+            public int getMaximumRecipePerPage(RecipeCategory<?> category) {
                 return 99;
             }
         };

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

@@ -13,7 +13,7 @@ import net.minecraft.util.Identifier;
 import java.util.List;
 import java.util.Optional;
 
-public interface RecipeDisplay<T extends Recipe> {
+public interface RecipeDisplay {
     
     /**
      * @return a list of items
@@ -50,11 +50,4 @@ public interface RecipeDisplay<T extends Recipe> {
         return Optional.empty();
     }
     
-    /**
-     * @return the optional recipe
-     * @deprecated stop
-     */
-    @Deprecated
-    default Optional<? extends Recipe> getRecipe() {return null;}
-    
 }

+ 5 - 1
src/main/java/me/shedaniel/rei/api/RecipeHelper.java

@@ -26,6 +26,10 @@ public interface RecipeHelper {
         return RoughlyEnoughItemsCore.getRecipeHelper();
     }
     
+    AutoCraftingHandler registerAutoCraftingHandler(AutoCraftingHandler handler);
+    
+    List<AutoCraftingHandler> getSortedAutoCraftingHandler();
+    
     /**
      * Gets the total recipe count registered
      *
@@ -204,7 +208,7 @@ public interface RecipeHelper {
      * @param liveRecipeGenerator the generator to register
      * @apiNote Still work in progress
      */
-    void registerLiveRecipeGenerator(LiveRecipeGenerator liveRecipeGenerator);
+    void registerLiveRecipeGenerator(LiveRecipeGenerator<?> liveRecipeGenerator);
     
     <T extends Recipe<?>> void registerRecipes(Identifier category, Class<T> recipeClass, Function<T, RecipeDisplay> mappingFunction);
     

+ 0 - 33
src/main/java/me/shedaniel/rei/api/RelativePoint.java

@@ -1,33 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.api;
-
-public class RelativePoint {
-    
-    private double relativeX, relativeY;
-    
-    public RelativePoint(double relativeX, double relativeY) {
-        this.relativeX = relativeX;
-        this.relativeY = relativeY;
-    }
-    
-    public double getRelativeX() {
-        return relativeX;
-    }
-    
-    public double getRelativeY() {
-        return relativeY;
-    }
-    
-    public double getX(double width) {
-        return width * relativeX;
-    }
-    
-    public double getY(double height) {
-        return height * relativeY;
-    }
-    
-}

+ 6 - 17
src/main/java/me/shedaniel/rei/api/Renderable.java

@@ -17,7 +17,7 @@ import java.util.function.Supplier;
 /**
  * The base class for renderables
  */
-public interface Renderable {
+public class Renderable {
     
     /**
      * Gets an item stack renderer by an item stack supplier
@@ -25,7 +25,7 @@ public interface Renderable {
      * @param supplier the supplier for getting the item stack
      * @return the item stack renderer
      */
-    static ItemStackRenderer fromItemStackSupplier(Supplier<ItemStack> supplier) {
+    public static ItemStackRenderer fromItemStackSupplier(Supplier<ItemStack> supplier) {
         return new ItemStackRenderer() {
             @Override
             public ItemStack getItemStack() {
@@ -40,7 +40,7 @@ public interface Renderable {
      * @param stack the item stack to be displayed
      * @return the item stack renderer
      */
-    static ItemStackRenderer fromItemStack(ItemStack stack) {
+    public static ItemStackRenderer fromItemStack(ItemStack stack) {
         return fromItemStackSupplier(() -> stack);
     }
     
@@ -49,7 +49,7 @@ public interface Renderable {
      *
      * @return an empty renderer
      */
-    static EmptyRenderer empty() {
+    public static EmptyRenderer empty() {
         return EmptyRenderer.INSTANCE;
     }
     
@@ -60,11 +60,11 @@ public interface Renderable {
      * @param output the list of output items
      * @return the recipe renderer
      */
-    static SimpleRecipeRenderer fromRecipe(Supplier<List<List<ItemStack>>> input, Supplier<List<ItemStack>> output) {
+    public static SimpleRecipeRenderer fromRecipe(Supplier<List<List<ItemStack>>> input, Supplier<List<ItemStack>> output) {
         return new SimpleRecipeRenderer(input, output);
     }
     
-    static ItemStackRenderer fromItemStacks(List<ItemStack> stacks) {
+    public static ItemStackRenderer fromItemStacks(List<ItemStack> stacks) {
         return new ItemStackRenderer() {
             @Override
             public ItemStack getItemStack() {
@@ -74,15 +74,4 @@ public interface Renderable {
             }
         };
     }
-    
-    /**
-     * 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
-     */
-    void render(int x, int y, double mouseX, double mouseY, float delta);
 }

+ 12 - 1
src/main/java/me/shedaniel/rei/api/Renderer.java

@@ -7,7 +7,7 @@ package me.shedaniel.rei.api;
 
 import net.minecraft.client.gui.DrawableHelper;
 
-public abstract class Renderer extends DrawableHelper implements Renderable {
+public abstract class Renderer extends DrawableHelper {
     /**
      * Gets the current blit offset
      *
@@ -25,4 +25,15 @@ public abstract class Renderer extends DrawableHelper implements Renderable {
     public void setBlitOffset(int offset) {
         this.blitOffset = 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);
 }

+ 1 - 0
src/main/java/me/shedaniel/rei/client/ClientHelperImpl.java

@@ -17,6 +17,7 @@ import me.shedaniel.rei.api.RecipeHelper;
 import me.shedaniel.rei.gui.PreRecipeViewingScreen;
 import me.shedaniel.rei.gui.RecipeViewingScreen;
 import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
+import me.shedaniel.rei.gui.config.RecipeScreenType;
 import net.fabricmc.api.ClientModInitializer;
 import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
 import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;

+ 30 - 2
src/main/java/me/shedaniel/rei/client/ConfigObject.java

@@ -6,8 +6,9 @@
 package me.shedaniel.rei.client;
 
 import blue.endless.jankson.Comment;
-import me.shedaniel.rei.api.ItemCheatingMode;
-import me.shedaniel.rei.api.RelativePoint;
+import me.shedaniel.rei.gui.config.ItemCheatingMode;
+import me.shedaniel.rei.gui.config.ItemListOrdering;
+import me.shedaniel.rei.gui.config.RecipeScreenType;
 
 public class ConfigObject {
     
@@ -58,4 +59,31 @@ public class ConfigObject {
             "The location of choose page dialog, will automatically be set to your last location so there is no need to change this.")
     public RelativePoint choosePageDialogPoint = new RelativePoint(.5, .5);
     
+    public static class RelativePoint {
+        
+        private double relativeX, relativeY;
+        
+        public RelativePoint(double relativeX, double relativeY) {
+            this.relativeX = relativeX;
+            this.relativeY = relativeY;
+        }
+        
+        public double getRelativeX() {
+            return relativeX;
+        }
+        
+        public double getRelativeY() {
+            return relativeY;
+        }
+        
+        public double getX(double width) {
+            return width * relativeX;
+        }
+        
+        public double getY(double height) {
+            return height * relativeY;
+        }
+        
+    }
+    
 }

+ 42 - 6
src/main/java/me/shedaniel/rei/client/RecipeHelperImpl.java

@@ -9,6 +9,11 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.*;
+import me.shedaniel.rei.gui.ContainerScreenOverlay;
+import me.shedaniel.rei.gui.config.DisplayVisibility;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
 import net.minecraft.item.ItemStack;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.recipe.RecipeManager;
@@ -37,7 +42,8 @@ public class RecipeHelperImpl implements RecipeHelper {
         VISIBILITY_HANDLER_COMPARATOR = comparator.reversed();
     }
     
-    public final List<RecipeFunction> recipeFunctions = Lists.newArrayList();
+    private final List<AutoCraftingHandler> autoCraftingHandlers = Lists.newArrayList();
+    private final List<RecipeFunction> recipeFunctions = Lists.newArrayList();
     private final AtomicInteger recipeCount = new AtomicInteger();
     private final Map<Identifier, List<RecipeDisplay>> recipeCategoryListMap = Maps.newHashMap();
     private final Map<Identifier, DisplaySettings> categoryDisplaySettingsMap = Maps.newHashMap();
@@ -45,7 +51,7 @@ public class RecipeHelperImpl implements RecipeHelper {
     private final Map<Identifier, ButtonAreaSupplier> speedCraftAreaSupplierMap = Maps.newHashMap();
     private final Map<Identifier, List<List<ItemStack>>> categoryWorkingStations = Maps.newHashMap();
     private final List<DisplayVisibilityHandler> displayVisibilityHandlers = Lists.newArrayList();
-    private final List<LiveRecipeGenerator> liveRecipeGenerators = Lists.newArrayList();
+    private final List<LiveRecipeGenerator<?>> liveRecipeGenerators = Lists.newArrayList();
     private RecipeManager recipeManager;
     
     @Override
@@ -81,7 +87,6 @@ public class RecipeHelperImpl implements RecipeHelper {
     @Override
     public void registerCategory(RecipeCategory category) {
         categories.add(category);
-        categoryDisplaySettingsMap.put(category.getIdentifier(), category.getDisplaySettings());
         recipeCategoryListMap.put(category.getIdentifier(), Lists.newLinkedList());
         categoryWorkingStations.put(category.getIdentifier(), Lists.newLinkedList());
     }
@@ -218,10 +223,10 @@ public class RecipeHelperImpl implements RecipeHelper {
         this.categories.clear();
         this.speedCraftAreaSupplierMap.clear();
         this.categoryWorkingStations.clear();
-        this.categoryDisplaySettingsMap.clear();
         this.recipeFunctions.clear();
         this.displayVisibilityHandlers.clear();
         this.liveRecipeGenerators.clear();
+        this.autoCraftingHandlers.clear();
         ((DisplayHelperImpl) RoughlyEnoughItemsCore.getDisplayHelper()).resetCache();
         BaseBoundsHandler baseBoundsHandler = new BaseBoundsHandlerImpl();
         RoughlyEnoughItemsCore.getDisplayHelper().registerBoundsHandler(baseBoundsHandler);
@@ -266,7 +271,7 @@ public class RecipeHelperImpl implements RecipeHelper {
         if (getDisplayVisibilityHandlers().isEmpty())
             registerRecipeVisibilityHandler(new DisplayVisibilityHandler() {
                 @Override
-                public DisplayVisibility handleDisplay(RecipeCategory category, RecipeDisplay display) {
+                public DisplayVisibility handleDisplay(RecipeCategory<?> category, RecipeDisplay display) {
                     return DisplayVisibility.ALWAYS_VISIBLE;
                 }
                 
@@ -275,10 +280,41 @@ public class RecipeHelperImpl implements RecipeHelper {
                     return -1f;
                 }
             });
+        registerAutoCraftingHandler(new AutoCraftingHandler() {
+            @Override
+            public double getPriority() {
+                return -Double.MAX_VALUE;
+            }
+            
+            @Override
+            public boolean handle(MinecraftClient minecraft, Screen recipeViewingScreen, AbstractContainerScreen<?> parentScreen, ContainerScreenOverlay overlay) {
+                minecraft.openScreen(parentScreen);
+                ScreenHelper.getLastOverlay().init();
+                return true;
+            }
+        });
+        
+        // Clear Cache
+        ((DisplayHelperImpl) RoughlyEnoughItemsCore.getDisplayHelper()).resetCache();
+        this.categoryDisplaySettingsMap.clear();
+        getAllCategories().forEach(category -> categoryDisplaySettingsMap.put(category.getIdentifier(), category.getDisplaySettings()));
+        ScreenHelper.getOptionalOverlay().ifPresent(overlay -> overlay.shouldReInit = true);
+        
         long usedTime = System.currentTimeMillis() - startTime;
         RoughlyEnoughItemsCore.LOGGER.info("[REI] Registered %d recipes displays, %d bounds handler, %d visibility " + "handlers and %d categories (%s) in %d ms.", recipeCount.get(), RoughlyEnoughItemsCore.getDisplayHelper().getAllBoundsHandlers().size(), getDisplayVisibilityHandlers().size(), categories.size(), String.join(", ", categories.stream().map(RecipeCategory::getCategoryName).collect(Collectors.toList())), usedTime);
     }
     
+    @Override
+    public AutoCraftingHandler registerAutoCraftingHandler(AutoCraftingHandler handler) {
+        autoCraftingHandlers.add(handler);
+        return handler;
+    }
+    
+    @Override
+    public List<AutoCraftingHandler> getSortedAutoCraftingHandler() {
+        return autoCraftingHandlers.stream().sorted(Comparator.comparingDouble(AutoCraftingHandler::getPriority).reversed()).collect(Collectors.toList());
+    }
+    
     @Override
     public int getRecipeCount() {
         return recipeCount.get();
@@ -361,7 +397,7 @@ public class RecipeHelperImpl implements RecipeHelper {
     }
     
     @Override
-    public void registerLiveRecipeGenerator(LiveRecipeGenerator liveRecipeGenerator) {
+    public void registerLiveRecipeGenerator(LiveRecipeGenerator<?> liveRecipeGenerator) {
         liveRecipeGenerators.add(liveRecipeGenerator);
     }
     

+ 9 - 5
src/main/java/me/shedaniel/rei/client/ScreenHelper.java

@@ -18,8 +18,8 @@ import net.minecraft.client.util.Window;
 import net.minecraft.item.ItemStack;
 import org.apache.logging.log4j.util.TriConsumer;
 
-import java.awt.*;
 import java.util.List;
+import java.util.Optional;
 
 public class ScreenHelper implements ClientModInitializer {
     
@@ -37,6 +37,10 @@ public class ScreenHelper implements ClientModInitializer {
         overlayVisible = !overlayVisible;
     }
     
+    public static Optional<ContainerScreenOverlay> getOptionalOverlay() {
+        return Optional.ofNullable(overlay);
+    }
+    
     public static ContainerScreenOverlay getLastOverlay(boolean reset, boolean setPage) {
         if (overlay == null || reset) {
             overlay = new ContainerScreenOverlay();
@@ -63,13 +67,13 @@ public class ScreenHelper implements ClientModInitializer {
     
     public static void drawHoveringWidget(int x, int y, TriConsumer<Integer, Integer, Float> consumer, int width, int height, float delta) {
         Window window = MinecraftClient.getInstance().window;
-        drawHoveringWidget(new Dimension(window.getScaledWidth(), window.getScaledHeight()), x, y, consumer, width, height, delta);
+        drawHoveringWidget(window.getScaledWidth(), window.getScaledHeight(), x, y, consumer, width, height, delta);
     }
     
-    public static void drawHoveringWidget(Dimension dimension, int x, int y, TriConsumer<Integer, Integer, Float> consumer, int width, int height, float delta) {
+    public static void drawHoveringWidget(int screenWidth, int screenHeight, int x, int y, TriConsumer<Integer, Integer, Float> consumer, int width, int height, float delta) {
         int actualX = Math.max(x + 12, 6);
-        int actualY = Math.min(y - height / 2, dimension.height - height - 6);
-        if (actualX + width > dimension.width)
+        int actualY = Math.min(y - height / 2, screenHeight - height - 6);
+        if (actualX + width > screenWidth)
             actualX -= 24 + width;
         if (actualY < 6)
             actualY += 24;

+ 26 - 6
src/main/java/me/shedaniel/rei/client/SearchArgument.java

@@ -5,18 +5,19 @@
 
 package me.shedaniel.rei.client;
 
+import java.util.Locale;
 import java.util.function.Function;
 import java.util.regex.Pattern;
 
 public class SearchArgument {
     
-    public static final Function<Integer, Boolean> INCLUDE = integer -> integer > -1;
-    public static final Function<Integer, Boolean> NOT_INCLUDE = integer -> integer <= -1;
+    public static final SearchArgument ALWAYS = new SearchArgument(ArgumentType.ALWAYS, "", true);
     private ArgumentType argumentType;
     private String text;
+    public final Function<String, Boolean> INCLUDE = s -> boyerMooreHorspoolSearch(text, s) > -1;
+    public final Function<String, Boolean> NOT_INCLUDE = s -> boyerMooreHorspoolSearch(text, s) <= -1;
     private boolean include;
     private Pattern pattern;
-    public static final SearchArgument ALWAYS = new SearchArgument(ArgumentType.ALWAYS, "", true);
     
     public SearchArgument(ArgumentType argumentType, String text, boolean include) {
         this(argumentType, text, include, true);
@@ -24,12 +25,31 @@ public class SearchArgument {
     
     public SearchArgument(ArgumentType argumentType, String text, boolean include, boolean autoLowerCase) {
         this.argumentType = argumentType;
-        this.text = autoLowerCase ? text.toLowerCase() : text;
+        this.text = autoLowerCase ? text.toLowerCase(Locale.ROOT) : text;
         this.include = include;
     }
     
-    public static Function<Integer, Boolean> getFunction(boolean include) {
-        return include ? SearchArgument.INCLUDE : SearchArgument.NOT_INCLUDE;
+    public static int boyerMooreHorspoolSearch(CharSequence pattern, CharSequence text) {
+        int shift[] = new int[256];
+        for(int k = 0; k < 256; k++)
+            shift[k] = pattern.length();
+        for(int k = 0; k < pattern.length() - 1; k++)
+            shift[pattern.charAt(k)] = pattern.length() - 1 - k;
+        int i = 0, j = 0;
+        while ((i + pattern.length()) <= text.length()) {
+            j = pattern.length() - 1;
+            while (text.charAt(i + j) == pattern.charAt(j)) {
+                j -= 1;
+                if (j < 0)
+                    return i;
+            }
+            i = i + shift[text.charAt(i + pattern.length() - 1)];
+        }
+        return -1;
+    }
+    
+    public Function<String, Boolean> getFunction(boolean include) {
+        return include ? INCLUDE : NOT_INCLUDE;
     }
     
     public ArgumentType getArgumentType() {

+ 7 - 5
src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java

@@ -37,10 +37,8 @@ import net.minecraft.util.math.MathHelper;
 import net.minecraft.world.GameMode;
 
 import java.awt.*;
-import java.util.LinkedList;
 import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
+import java.util.*;
 import java.util.stream.Collectors;
 
 public class ContainerScreenOverlay extends AbstractParentElement implements Drawable {
@@ -51,6 +49,7 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
     private static int page = 0;
     private static ItemListOverlay itemListOverlay;
     private final List<Widget> widgets = Lists.newLinkedList();
+    public boolean shouldReInit = false;
     private Rectangle rectangle;
     private Window window;
     private CraftableToggleButtonWidget toggleButtonWidget;
@@ -65,6 +64,7 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
     }
     
     public void init(boolean setPage) {
+        this.shouldReInit = false;
         //Update Variables
         this.children().clear();
         this.window = MinecraftClient.getInstance().window;
@@ -183,12 +183,12 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
                     return false;
                 }
             });
-            int xxx = RoughlyEnoughItemsCore.getConfigManager().getConfig().mirrorItemPanel ? window.getScaledWidth() -30 : 10;
+            int xxx = RoughlyEnoughItemsCore.getConfigManager().getConfig().mirrorItemPanel ? window.getScaledWidth() - 30 : 10;
             for(Weather weather : Weather.values()) {
                 widgets.add(new ButtonWidget(xxx, 35, 20, 20, "") {
                     @Override
                     public void onPressed() {
-                        MinecraftClient.getInstance().player.sendChatMessage(RoughlyEnoughItemsCore.getConfigManager().getConfig().weatherCommand.replaceAll("\\{weather}", weather.name().toLowerCase()));
+                        MinecraftClient.getInstance().player.sendChatMessage(RoughlyEnoughItemsCore.getConfigManager().getConfig().weatherCommand.replaceAll("\\{weather}", weather.name().toLowerCase(Locale.ROOT)));
                     }
                     
                     @Override
@@ -346,6 +346,8 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
     public void render(int mouseX, int mouseY, float delta) {
         List<ItemStack> currentStacks = ClientHelper.getInstance().getInventoryItemsTypes();
         if (RoughlyEnoughItemsCore.getDisplayHelper().getBaseBoundsHandler() != null && RoughlyEnoughItemsCore.getDisplayHelper().getBaseBoundsHandler().shouldRecalculateArea(!RoughlyEnoughItemsCore.getConfigManager().getConfig().mirrorItemPanel, rectangle))
+            shouldReInit = true;
+        if (shouldReInit)
             init(true);
         else if (RoughlyEnoughItemsCore.getConfigManager().isCraftableOnlyEnabled() && (!hasSameListContent(new LinkedList<>(ScreenHelper.inventoryStacks), currentStacks) || (currentStacks.size() != ScreenHelper.inventoryStacks.size()))) {
             ScreenHelper.inventoryStacks = ClientHelper.getInstance().getInventoryItemsTypes();

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

@@ -10,7 +10,7 @@ import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.ClientHelper;
 import me.shedaniel.rei.api.RecipeCategory;
 import me.shedaniel.rei.api.RecipeDisplay;
-import me.shedaniel.rei.client.RecipeScreenType;
+import me.shedaniel.rei.gui.config.RecipeScreenType;
 import me.shedaniel.rei.client.ScreenHelper;
 import me.shedaniel.rei.gui.widget.ButtonWidget;
 import me.shedaniel.rei.gui.widget.HighlightableWidget;

+ 1 - 1
src/main/java/me/shedaniel/rei/api/DisplayVisibility.java → src/main/java/me/shedaniel/rei/gui/config/DisplayVisibility.java

@@ -3,7 +3,7 @@
  * Licensed under the MIT License.
  */
 
-package me.shedaniel.rei.api;
+package me.shedaniel.rei.gui.config;
 
 public enum DisplayVisibility {
     ALWAYS_VISIBLE,

+ 1 - 1
src/main/java/me/shedaniel/rei/api/ItemCheatingMode.java → src/main/java/me/shedaniel/rei/gui/config/ItemCheatingMode.java

@@ -3,7 +3,7 @@
  * Licensed under the MIT License.
  */
 
-package me.shedaniel.rei.api;
+package me.shedaniel.rei.gui.config;
 
 public enum ItemCheatingMode {
     REI_LIKE,

+ 1 - 1
src/main/java/me/shedaniel/rei/client/ItemListOrdering.java → src/main/java/me/shedaniel/rei/gui/config/ItemListOrdering.java

@@ -3,7 +3,7 @@
  * Licensed under the MIT License.
  */
 
-package me.shedaniel.rei.client;
+package me.shedaniel.rei.gui.config;
 
 public enum ItemListOrdering {
     

+ 0 - 1
src/main/java/me/shedaniel/rei/gui/config/ItemListOrderingConfig.java

@@ -5,7 +5,6 @@
 
 package me.shedaniel.rei.gui.config;
 
-import me.shedaniel.rei.client.ItemListOrdering;
 import net.minecraft.client.resource.language.I18n;
 
 public enum ItemListOrderingConfig {

+ 4 - 2
src/main/java/me/shedaniel/rei/client/RecipeScreenType.java → src/main/java/me/shedaniel/rei/gui/config/RecipeScreenType.java

@@ -3,10 +3,12 @@
  * Licensed under the MIT License.
  */
 
-package me.shedaniel.rei.client;
+package me.shedaniel.rei.gui.config;
 
 import net.minecraft.client.resource.language.I18n;
 
+import java.util.Locale;
+
 public enum RecipeScreenType {
     UNSET,
     ORIGINAL,
@@ -14,6 +16,6 @@ public enum RecipeScreenType {
     
     @Override
     public String toString() {
-        return I18n.translate("text.rei.config.recipe_screen_type." + name().toLowerCase());
+        return I18n.translate("text.rei.config.recipe_screen_type." + name().toLowerCase(Locale.ROOT));
     }
 }

+ 1 - 0
src/main/java/me/shedaniel/rei/gui/renderables/EmptyRenderer.java

@@ -15,4 +15,5 @@ public class EmptyRenderer extends Renderer {
     public void render(int x, int y, double mouseX, double mouseY, float delta) {
     
     }
+    
 }

+ 6 - 3
src/main/java/me/shedaniel/rei/gui/widget/AutoCraftingButtonWidget.java

@@ -5,7 +5,9 @@
 
 package me.shedaniel.rei.gui.widget;
 
+import me.shedaniel.rei.api.AutoCraftingHandler;
 import me.shedaniel.rei.api.RecipeDisplay;
+import me.shedaniel.rei.api.RecipeHelper;
 import me.shedaniel.rei.client.ScreenHelper;
 import net.minecraft.ChatFormat;
 import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
@@ -18,7 +20,7 @@ import java.util.function.Supplier;
 
 public class AutoCraftingButtonWidget extends ButtonWidget {
     
-    private final Supplier<RecipeDisplay<?>> displaySupplier;
+    private final Supplier<RecipeDisplay> displaySupplier;
     private String extraTooltip;
     private AbstractContainerScreen<?> containerScreen;
     
@@ -32,8 +34,9 @@ public class AutoCraftingButtonWidget extends ButtonWidget {
     
     @Override
     public void onPressed() {
-        minecraft.openScreen(containerScreen);
-        ScreenHelper.getLastOverlay().init();
+        for(AutoCraftingHandler autoCraftingHandler : RecipeHelper.getInstance().getSortedAutoCraftingHandler())
+            if (autoCraftingHandler.handle(minecraft,minecraft.currentScreen, containerScreen, ScreenHelper.getLastOverlay()))
+                break;
     }
     
     @Override

+ 30 - 32
src/main/java/me/shedaniel/rei/gui/widget/ItemListOverlay.java

@@ -10,11 +10,11 @@ import me.shedaniel.cloth.api.ClientUtils;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.ClientHelper;
 import me.shedaniel.rei.api.DisplayHelper;
-import me.shedaniel.rei.api.ItemCheatingMode;
 import me.shedaniel.rei.api.RecipeHelper;
-import me.shedaniel.rei.client.ItemListOrdering;
 import me.shedaniel.rei.client.ScreenHelper;
 import me.shedaniel.rei.client.SearchArgument;
+import me.shedaniel.rei.gui.config.ItemCheatingMode;
+import me.shedaniel.rei.gui.config.ItemListOrdering;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.item.TooltipContext;
 import net.minecraft.client.network.ClientPlayerEntity;
@@ -30,10 +30,9 @@ import net.minecraft.util.registry.Registry;
 import org.apache.commons.lang3.StringUtils;
 
 import java.awt.*;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 public class ItemListOverlay extends Widget {
@@ -100,26 +99,24 @@ public class ItemListOverlay extends Widget {
     public static boolean filterItem(ItemStack itemStack, List<SearchArgument[]> arguments) {
         if (arguments.isEmpty())
             return true;
-        String mod = ClientHelper.getInstance().getModFromItem(itemStack.getItem()).toLowerCase();
-        String tooltips = tryGetItemStackToolTip(itemStack, true).stream().skip(1).collect(Collectors.joining("")).replace(SPACE, EMPTY).toLowerCase();
-        String name = tryGetItemStackName(itemStack).replace(SPACE, EMPTY).toLowerCase();
+        AtomicReference<String> mod = null, tooltips = null, name = null;
         for(SearchArgument[] arguments1 : arguments) {
             boolean b = true;
             for(SearchArgument argument : arguments1) {
                 if (argument.getArgumentType().equals(SearchArgument.ArgumentType.ALWAYS))
                     return true;
                 if (argument.getArgumentType().equals(SearchArgument.ArgumentType.MOD))
-                    if (SearchArgument.getFunction(!argument.isInclude()).apply(mod.indexOf(argument.getText()))) {
+                    if (argument.getFunction(!argument.isInclude()).apply(fillMod(itemStack, mod))) {
                         b = false;
                         break;
                     }
                 if (argument.getArgumentType().equals(SearchArgument.ArgumentType.TOOLTIP))
-                    if (SearchArgument.getFunction(!argument.isInclude()).apply(tooltips.indexOf(argument.getText()))) {
+                    if (argument.getFunction(!argument.isInclude()).apply(fillTooltip(itemStack, tooltips))) {
                         b = false;
                         break;
                     }
                 if (argument.getArgumentType().equals(SearchArgument.ArgumentType.TEXT))
-                    if (SearchArgument.getFunction(!argument.isInclude()).apply(name.indexOf(argument.getText()))) {
+                    if (argument.getFunction(!argument.isInclude()).apply(fillName(itemStack, name))) {
                         b = false;
                         break;
                     }
@@ -130,6 +127,24 @@ public class ItemListOverlay extends Widget {
         return false;
     }
     
+    private static String fillMod(ItemStack itemStack, AtomicReference<String> mod) {
+        if (mod == null)
+            mod = new AtomicReference<>(ClientHelper.getInstance().getModFromItem(itemStack.getItem()).toLowerCase(Locale.ROOT));
+        return mod.get();
+    }
+    
+    private static String fillTooltip(ItemStack itemStack, AtomicReference<String> mod) {
+        if (mod == null)
+            mod = new AtomicReference<>(tryGetItemStackToolTip(itemStack, false).stream().collect(Collectors.joining("")).replace(SPACE, EMPTY).toLowerCase(Locale.ROOT));
+        return mod.get();
+    }
+    
+    private static String fillName(ItemStack itemStack, AtomicReference<String> mod) {
+        if (mod == null)
+            mod = new AtomicReference<>(tryGetItemStackName(itemStack).replace(SPACE, EMPTY).toLowerCase(Locale.ROOT));
+        return mod.get();
+    }
+    
     public int getFullTotalSlotsPerPage() {
         return width * height;
     }
@@ -274,7 +289,10 @@ public class ItemListOverlay extends Widget {
             else
                 lastSearchArgument.add(new SearchArgument[]{SearchArgument.ALWAYS});
         });
-        os.stream().filter(itemStack -> filterItem(itemStack, lastSearchArgument)).forEachOrdered(stacks::add);
+        if (lastSearchArgument.isEmpty())
+            os.forEach(stacks::add);
+        else
+            os.stream().filter(itemStack -> filterItem(itemStack, lastSearchArgument)).forEachOrdered(stacks::add);
         if (!RoughlyEnoughItemsCore.getConfigManager().isCraftableOnlyEnabled() || stacks.isEmpty() || inventoryItems.isEmpty())
             return stacks;
         List<ItemStack> workingItems = Lists.newArrayList(RecipeHelper.getInstance().findCraftableByItems(inventoryItems));
@@ -285,26 +303,6 @@ public class ItemListOverlay extends Widget {
         return lastSearchArgument;
     }
     
-    private boolean filterItem(ItemStack itemStack, SearchArgument... arguments) {
-        if (arguments.length == 0)
-            return true;
-        String mod = ClientHelper.getInstance().getModFromItem(itemStack.getItem()).toLowerCase();
-        String tooltips = tryGetItemStackToolTip(itemStack, false).stream().skip(1).collect(Collectors.joining("")).replace(SPACE, EMPTY).toLowerCase();
-        String name = tryGetItemStackName(itemStack).replace(SPACE, EMPTY).toLowerCase();
-        for(SearchArgument argument : arguments) {
-            if (argument.getArgumentType().equals(SearchArgument.ArgumentType.MOD))
-                if (SearchArgument.getFunction(!argument.isInclude()).apply(mod.indexOf(argument.getText())))
-                    return false;
-            if (argument.getArgumentType().equals(SearchArgument.ArgumentType.TOOLTIP))
-                if (SearchArgument.getFunction(!argument.isInclude()).apply(tooltips.indexOf(argument.getText())))
-                    return false;
-            if (argument.getArgumentType().equals(SearchArgument.ArgumentType.TEXT))
-                if (SearchArgument.getFunction(!argument.isInclude()).apply(name.indexOf(argument.getText())))
-                    return false;
-        }
-        return true;
-    }
-    
     public void calculateListSize(Rectangle rect) {
         int xOffset = 0, yOffset = 0;
         width = 0;

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

@@ -7,7 +7,7 @@ package me.shedaniel.rei.gui.widget;
 
 import com.mojang.blaze3d.platform.GlStateManager;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.client.RecipeScreenType;
+import me.shedaniel.rei.gui.config.RecipeScreenType;
 import me.shedaniel.rei.client.ScreenHelper;
 import net.minecraft.client.render.GuiLighting;
 import net.minecraft.util.Identifier;

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

@@ -9,7 +9,7 @@ import com.google.common.collect.Lists;
 import com.mojang.blaze3d.platform.GlStateManager;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.ConfigManager;
-import me.shedaniel.rei.api.RelativePoint;
+import me.shedaniel.rei.client.ConfigObject;
 import me.shedaniel.rei.gui.RecipeViewingScreen;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.render.GuiLighting;
@@ -44,7 +44,7 @@ public class RecipeChoosePageWidget extends DraggableWidget {
     
     private static Point getPointFromConfig() {
         Window window = MinecraftClient.getInstance().window;
-        RelativePoint point = RoughlyEnoughItemsCore.getConfigManager().getConfig().choosePageDialogPoint;
+        ConfigObject.RelativePoint point = RoughlyEnoughItemsCore.getConfigManager().getConfig().choosePageDialogPoint;
         return new Point((int) point.getX(window.getScaledWidth()), (int) point.getY(window.getScaledHeight()));
     }
     
@@ -184,7 +184,7 @@ public class RecipeChoosePageWidget extends DraggableWidget {
     public void onMouseReleaseMidPoint(Point midPoint) {
         ConfigManager configManager = RoughlyEnoughItemsCore.getConfigManager();
         Window window = minecraft.window;
-        configManager.getConfig().choosePageDialogPoint = new RelativePoint(midPoint.getX() / window.getScaledWidth(), midPoint.getY() / window.getScaledHeight());
+        configManager.getConfig().choosePageDialogPoint = new ConfigObject.RelativePoint(midPoint.getX() / window.getScaledWidth(), midPoint.getY() / window.getScaledHeight());
         try {
             configManager.saveConfig();
         } catch (IOException e) {

+ 4 - 6
src/main/java/me/shedaniel/rei/gui/widget/SlotWidget.java

@@ -20,19 +20,17 @@ import net.minecraft.util.Identifier;
 import net.minecraft.util.math.MathHelper;
 
 import java.awt.*;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 public class SlotWidget extends HighlightableWidget {
     
     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");
+    protected int x, y;
     private List<Renderer> renderers = new LinkedList<>();
     private boolean drawBackground, showToolTips, clickToMoreRecipes, drawHighlightedBackground;
-    protected int x, y;
     
     public SlotWidget(int x, int y, ItemStack itemStack, boolean drawBackground, boolean showToolTips) {
         this(x, y, Collections.singletonList(itemStack), drawBackground, showToolTips);
@@ -155,10 +153,10 @@ public class SlotWidget extends HighlightableWidget {
     protected List<String> getTooltip(ItemStack itemStack) {
         final String modString = ClientHelper.getInstance().getFormattedModFromItem(itemStack.getItem());
         List<String> toolTip = Lists.newArrayList(ItemListOverlay.tryGetItemStackToolTip(itemStack, true));
-        String s1 = ClientHelperImpl.instance.getFormattedModNoItalicFromItem(itemStack.getItem()).toLowerCase();
+        String s1 = ClientHelperImpl.instance.getFormattedModNoItalicFromItem(itemStack.getItem()).toLowerCase(Locale.ROOT);
         toolTip.addAll(getExtraToolTips(itemStack));
         if (!modString.isEmpty()) {
-            toolTip.removeIf(s -> s.toLowerCase().contains(s1));
+            toolTip.removeIf(s -> s.toLowerCase(Locale.ROOT).contains(s1));
             toolTip.add(modString);
         }
         return toolTip;

+ 0 - 16
src/main/java/me/shedaniel/rei/listeners/CreativePlayerInventoryScreenHooks.java

@@ -1,16 +0,0 @@
-/*
- * Roughly Enough Items by Danielshe.
- * Licensed under the MIT License.
- */
-
-package me.shedaniel.rei.listeners;
-
-import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.gen.Accessor;
-
-@Mixin(CreativeInventoryScreen.class)
-public interface CreativePlayerInventoryScreenHooks {
-    @Accessor("selectedTab")
-    int rei_getSelectedTab();
-}

+ 2 - 1
src/main/java/me/shedaniel/rei/plugin/DefaultAutoCraftingPlugin.java

@@ -5,6 +5,7 @@ import me.shedaniel.rei.api.PluginDisabler;
 import me.shedaniel.rei.api.PluginFunction;
 import me.shedaniel.rei.api.REIPluginEntry;
 import me.shedaniel.rei.api.RecipeHelper;
+import me.shedaniel.rei.plugin.autocrafting.AutoCraftingTableHandler;
 import net.minecraft.util.Identifier;
 
 public class DefaultAutoCraftingPlugin implements REIPluginEntry {
@@ -28,7 +29,7 @@ public class DefaultAutoCraftingPlugin implements REIPluginEntry {
     
     @Override
     public void registerOthers(RecipeHelper recipeHelper) {
-    
+        recipeHelper.registerAutoCraftingHandler(new AutoCraftingTableHandler());
     }
     
 }

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

@@ -12,6 +12,7 @@ import me.shedaniel.rei.api.*;
 import me.shedaniel.rei.client.ScreenHelper;
 import me.shedaniel.rei.gui.RecipeViewingScreen;
 import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
+import me.shedaniel.rei.gui.config.DisplayVisibility;
 import me.shedaniel.rei.plugin.blasting.DefaultBlastingCategory;
 import me.shedaniel.rei.plugin.blasting.DefaultBlastingDisplay;
 import me.shedaniel.rei.plugin.brewing.DefaultBrewingCategory;
@@ -279,7 +280,7 @@ public class DefaultPlugin implements REIPluginEntry {
         recipeHelper.registerSpeedCraftButtonArea(DefaultPlugin.CAMPFIRE, bounds -> new Rectangle((int) bounds.getMaxX() - 16, bounds.y + 6, 10, 10));
         recipeHelper.registerRecipeVisibilityHandler(new DisplayVisibilityHandler() {
             @Override
-            public DisplayVisibility handleDisplay(RecipeCategory category, RecipeDisplay display) {
+            public DisplayVisibility handleDisplay(RecipeCategory<?> category, RecipeDisplay display) {
                 return DisplayVisibility.ALWAYS_VISIBLE;
             }
             

+ 26 - 0
src/main/java/me/shedaniel/rei/plugin/autocrafting/AutoCraftingTableHandler.java

@@ -0,0 +1,26 @@
+package me.shedaniel.rei.plugin.autocrafting;
+
+import me.shedaniel.rei.api.AutoCraftingHandler;
+import me.shedaniel.rei.client.ScreenHelper;
+import me.shedaniel.rei.gui.ContainerScreenOverlay;
+import me.shedaniel.rei.listeners.RecipeBookGuiHooks;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
+import net.minecraft.client.gui.screen.ingame.CraftingTableScreen;
+import net.minecraft.container.CraftingTableContainer;
+
+public class AutoCraftingTableHandler implements AutoCraftingHandler {
+    @Override
+    public boolean handle(MinecraftClient minecraft, Screen recipeViewingScreen, AbstractContainerScreen<?> parentScreen, ContainerScreenOverlay overlay) {
+        if (parentScreen instanceof CraftingTableScreen) {
+            CraftingTableScreen craftingTableScreen = (CraftingTableScreen) parentScreen;
+            minecraft.openScreen(craftingTableScreen);
+            ((RecipeBookGuiHooks) craftingTableScreen.getRecipeBookGui()).rei_getGhostSlots().reset();
+            CraftingTableContainer container = craftingTableScreen.getContainer();
+            ScreenHelper.getLastOverlay().init();
+            return true;
+        }
+        return false;
+    }
+}

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

@@ -20,7 +20,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-public class DefaultBlastingDisplay implements RecipeDisplay<BlastingRecipe> {
+public class DefaultBlastingDisplay implements RecipeDisplay {
     
     private BlastingRecipe display;
     private List<List<ItemStack>> input;

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

@@ -20,7 +20,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-public class DefaultCampfireDisplay implements RecipeDisplay<CampfireCookingRecipe> {
+public class DefaultCampfireDisplay implements RecipeDisplay {
     
     private List<List<ItemStack>> inputs;
     private List<ItemStack> output;

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

@@ -7,7 +7,10 @@ package me.shedaniel.rei.plugin.composting;
 
 import com.google.common.collect.Lists;
 import com.mojang.blaze3d.platform.GlStateManager;
-import me.shedaniel.rei.api.*;
+import me.shedaniel.rei.api.DisplaySettings;
+import me.shedaniel.rei.api.RecipeCategory;
+import me.shedaniel.rei.api.Renderable;
+import me.shedaniel.rei.api.Renderer;
 import me.shedaniel.rei.gui.renderables.RecipeRenderer;
 import me.shedaniel.rei.gui.widget.RecipeBaseWidget;
 import me.shedaniel.rei.gui.widget.SlotWidget;
@@ -97,20 +100,20 @@ public class DefaultCompostingCategory implements RecipeCategory<DefaultComposti
     }
     
     @Override
-    public DisplaySettings getDisplaySettings() {
-        return new DisplaySettings() {
+    public DisplaySettings<DefaultCompostingDisplay> getDisplaySettings() {
+        return new DisplaySettings<DefaultCompostingDisplay>() {
             @Override
-            public int getDisplayHeight(RecipeCategory iRecipeCategory) {
+            public int getDisplayHeight(RecipeCategory<?> recipeCategory) {
                 return 140;
             }
             
             @Override
-            public int getDisplayWidth(RecipeCategory iRecipeCategory, RecipeDisplay display) {
+            public int getDisplayWidth(RecipeCategory<?> recipeCategory, DefaultCompostingDisplay display) {
                 return 150;
             }
             
             @Override
-            public int getMaximumRecipePerPage(RecipeCategory iRecipeCategory) {
+            public int getMaximumRecipePerPage(RecipeCategory<?> recipeCategory) {
                 return -1;
             }
             

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

@@ -7,10 +7,9 @@ package me.shedaniel.rei.plugin.crafting;
 
 import me.shedaniel.rei.api.RecipeDisplay;
 import me.shedaniel.rei.plugin.DefaultPlugin;
-import net.minecraft.recipe.Recipe;
 import net.minecraft.util.Identifier;
 
-public interface DefaultCraftingDisplay<T> extends RecipeDisplay<Recipe> {
+public interface DefaultCraftingDisplay<T> extends RecipeDisplay {
     
     @Override
     default Identifier getRecipeCategory() {

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

@@ -20,7 +20,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-public class DefaultSmeltingDisplay implements RecipeDisplay<SmeltingRecipe> {
+public class DefaultSmeltingDisplay implements RecipeDisplay {
     
     private SmeltingRecipe display;
     private List<List<ItemStack>> input;

+ 1 - 1
src/main/java/me/shedaniel/rei/plugin/smoking/DefaultSmokingDisplay.java

@@ -20,7 +20,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-public class DefaultSmokingDisplay implements RecipeDisplay<SmokingRecipe> {
+public class DefaultSmokingDisplay implements RecipeDisplay {
     
     private SmokingRecipe display;
     private List<List<ItemStack>> input;

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

@@ -63,20 +63,20 @@ public class DefaultStoneCuttingCategory implements RecipeCategory<DefaultStoneC
     }
     
     @Override
-    public DisplaySettings getDisplaySettings() {
+    public DisplaySettings<DefaultStoneCuttingDisplay> getDisplaySettings() {
         return new DisplaySettings<DefaultStoneCuttingDisplay>() {
             @Override
-            public int getDisplayHeight(RecipeCategory category) {
+            public int getDisplayHeight(RecipeCategory<?> category) {
                 return 36;
             }
             
             @Override
-            public int getDisplayWidth(RecipeCategory category, DefaultStoneCuttingDisplay display) {
+            public int getDisplayWidth(RecipeCategory<?> category, DefaultStoneCuttingDisplay display) {
                 return 150;
             }
             
             @Override
-            public int getMaximumRecipePerPage(RecipeCategory category) {
+            public int getMaximumRecipePerPage(RecipeCategory<?> category) {
                 return 99;
             }
         };

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

@@ -20,7 +20,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-public class DefaultStoneCuttingDisplay implements RecipeDisplay<StonecuttingRecipe> {
+public class DefaultStoneCuttingDisplay implements RecipeDisplay {
     
     private List<List<ItemStack>> inputs;
     private List<ItemStack> output;

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

@@ -15,10 +15,10 @@ import me.shedaniel.clothconfig2.gui.entries.IntegerSliderEntry;
 import me.shedaniel.clothconfig2.gui.entries.StringListEntry;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.ConfigManager;
-import me.shedaniel.rei.api.ItemCheatingMode;
-import me.shedaniel.rei.client.RecipeScreenType;
 import me.shedaniel.rei.client.ScreenHelper;
+import me.shedaniel.rei.gui.config.ItemCheatingMode;
 import me.shedaniel.rei.gui.config.ItemListOrderingConfig;
+import me.shedaniel.rei.gui.config.RecipeScreenType;
 import me.shedaniel.rei.gui.credits.CreditsScreen;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.screen.Screen;
@@ -26,6 +26,7 @@ import net.minecraft.client.gui.widget.ButtonWidget;
 import net.minecraft.client.resource.language.I18n;
 
 import java.io.IOException;
+import java.util.Locale;
 import java.util.Optional;
 
 public class ClothScreenRegistry {
@@ -72,7 +73,7 @@ public class ClothScreenRegistry {
         appearance.addEntry(new BooleanListEntry("text.rei.config.villager_screen_permanent_scroll_bar", configManager.getConfig().villagerScreenPermanentScrollBar, RESET, () -> false, bool -> configManager.getConfig().villagerScreenPermanentScrollBar = bool, () -> getConfigTooltip("villager_screen_permanent_scroll_bar")));
         ConfigCategory action = builder.getOrCreateCategory("text.rei.config.action");
         action.addEntry(new EnumListEntry<>("text.rei.config.item_cheating_mode", ItemCheatingMode.class, configManager.getConfig().itemCheatingMode, RESET, () -> ItemCheatingMode.REI_LIKE, i -> configManager.getConfig().itemCheatingMode = i, e -> {
-            return I18n.translate("text.rei.config.item_cheating_mode." + e.name().toLowerCase());
+            return I18n.translate("text.rei.config.item_cheating_mode." + e.name().toLowerCase(Locale.ROOT));
         }, () -> getConfigTooltip("item_cheating_mode")));
         action.addEntry(new StringListEntry("text.rei.give_command", configManager.getConfig().giveCommand, RESET, () -> "/give {player_name} {item_identifier}{nbt} {count}", s -> configManager.getConfig().giveCommand = s, () -> getConfigTooltip("give_command")));
         action.addEntry(new StringListEntry("text.rei.gamemode_command", configManager.getConfig().gamemodeCommand, RESET, () -> "/gamemode {gamemode}", s -> configManager.getConfig().gamemodeCommand = s, () -> getConfigTooltip("gamemode_command")));

+ 1 - 1
src/main/resources/fabric.mod.json

@@ -36,7 +36,7 @@
     "cloth": "*"
   },
   "recommends": {
-    "cloth-config": ">=0.1.0"
+    "cloth-config2": ">=0.1.0"
   },
   "mixins": [
     "mixin.roughlyenoughitems.json",

+ 0 - 1
src/main/resources/listeners.roughlyenoughitems.json

@@ -6,7 +6,6 @@
   "mixins": [],
   "client": [
     "ContainerScreenHooks",
-    "CreativePlayerInventoryScreenHooks",
     "RecipeBookGuiHooks",
     "AbstractInventoryScreenHooks"
   ],