浏览代码

v2.5.2.76

Unknown 6 年之前
父节点
当前提交
47103ec47d

+ 15 - 12
CHANGELOG.md

@@ -1,12 +1,15 @@
-# v2.5.1.75
+## v2.5.2.76
+- New DisplayVisibilityHandler
+- Fixed [#49](https://github.com/shedaniel/RoughlyEnoughItems/issues/49): REI Overlay added twice
+## v2.5.1.75
 - Using Cloth events instead of overwriting methods \o/ (Please update [Cloth](https://minecraft.curseforge.com/projects/cloth))
-# v2.5.1.74
+## v2.5.1.74
 - Updated to 19w13a
-# v2.5.0.73
+## v2.5.0.73
 - Made REI crash better (lmao wut)
-# v2.5.0.72
+## v2.5.0.72
 - Updated to 19w12b
-# v2.5.0.71
+## v2.5.0.71
 - Removed mouseScrolled Override in mixins
 - Added spectator mode in gamemode switcher
 - Gamemodes & Weather are now translatable: [#47](https://github.com/shedaniel/RoughlyEnoughItems/issues/47)
@@ -17,26 +20,26 @@
 - Removed disabling credits option
 - Update to 19w12a
 - New config screen from [Cloth](https://minecraft.curseforge.com/projects/cloth)
-# v2.4.2.68
+## v2.4.2.68
 - Fixed [Cloth](https://minecraft.curseforge.com/projects/cloth) missing message
-# v2.4.2.67
+## v2.4.2.67
 - Fixed pages being weird
 - Added Portuguese
-# v2.4.2.66
+## v2.4.2.66
 - Removed Mod Menu hooks, will hook into Mod Menu itself in the future
 - Improved gui widgets
-# v2.4.1.65
+## v2.4.1.65
 - [Cloth](https://minecraft.curseforge.com/projects/cloth) is now required for REI to run
 - Update to 19w11a
-# v2.4.0.63
+## v2.4.0.63
 - First implementation of [Cloth](https://minecraft.curseforge.com/projects/cloth), [Cloth](https://minecraft.curseforge.com/projects/cloth) is still not required for REI to boot but it will be a must have dependency when 19w11a comes.
 - Used [Cloth](https://minecraft.curseforge.com/projects/cloth) for hooking up [Mod Menu](https://minecraft.curseforge.com/projects/modmenu/) config. Example: [https://streamable.com/ivbsj](https://streamable.com/ivbsj)
 - Changed config `true / false` to `Yes / No`
-# v2.4.0.61
+## v2.4.0.61
 - Config with comments
 - Fix creative inventory even more
 - No longer uses Fabric internals
 - Config to disable Recipe Book
 - Fixes [Issue #27: Second page react as first page recipes](https://github.com/shedaniel/RoughlyEnoughItems/issues/27)
-# v2.3.2.56
+## v2.3.2.56
 - Removed Plugin Update Checker

+ 1 - 1
gradle.properties

@@ -1,4 +1,4 @@
-mod_version=2.5.1.75
+mod_version=2.6.0.76
 minecraft_version=19w13b
 yarn_version=19w13b.1
 fabric_version=0.2.6.117

+ 0 - 8
src/main/java/me/shedaniel/rei/api/DisplaySettings.java

@@ -12,12 +12,4 @@ public interface DisplaySettings<T extends RecipeDisplay> {
         return -1;
     }
     
-    default VisableType canDisplay(T display) {
-        return VisableType.ALWAYS;
-    }
-    
-    public static enum VisableType {
-        ALWAYS, PASS, NEVER;
-    }
-    
 }

+ 5 - 0
src/main/java/me/shedaniel/rei/api/DisplayVisibility.java

@@ -0,0 +1,5 @@
+package me.shedaniel.rei.api;
+
+public enum DisplayVisibility {
+    ALWAYS_VISIBLE, CONFIG_OPTIONAL, NEVER_VISIBLE, PASS
+}

+ 11 - 0
src/main/java/me/shedaniel/rei/api/DisplayVisibilityHandler.java

@@ -0,0 +1,11 @@
+package me.shedaniel.rei.api;
+
+public interface DisplayVisibilityHandler {
+    
+    default float getPriority() {
+        return 0f;
+    }
+    
+    DisplayVisibility handleDisplay(RecipeCategory category, RecipeDisplay display);
+    
+}

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

@@ -1,5 +1,5 @@
 package me.shedaniel.rei.api;
 
 public enum PluginFunction {
-    REGISTER_ITEMS, REGISTER_CATEGORIES, REGISTER_RECIPE_DISPLAYS, REGISTER_SPEED_CRAFT;
+    REGISTER_ITEMS, REGISTER_CATEGORIES, REGISTER_RECIPE_DISPLAYS, REGISTER_SPEED_CRAFT, REGISTER_OTHERS;
 }

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

@@ -4,13 +4,16 @@ public interface REIPlugin {
     
     default void onFirstLoad(PluginDisabler pluginDisabler) {}
     
-    void registerItems(ItemRegistry itemRegistry);
+    default void registerItems(ItemRegistry itemRegistry) {}
     
-    void registerPluginCategories(RecipeHelper recipeHelper);
+    default void registerPluginCategories(RecipeHelper recipeHelper) {}
     
-    void registerRecipeDisplays(RecipeHelper recipeHelper);
+    default void registerRecipeDisplays(RecipeHelper recipeHelper) {}
     
-    void registerSpeedCraft(RecipeHelper recipeHelper);
+    @Deprecated
+    default void registerSpeedCraft(RecipeHelper recipeHelper) {}
+    
+    default void registerOthers(RecipeHelper recipeHelper) {}
     
     default int getPriority() {
         return 0;

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

@@ -51,14 +51,6 @@ public interface RecipeCategory<T extends RecipeDisplay> {
         };
     }
     
-    default boolean canDisplay(RecipeDisplay display) {
-        if (getDisplaySettings().canDisplay(display) == DisplaySettings.VisableType.ALWAYS)
-            return true;
-        if (getDisplaySettings().canDisplay(display) == DisplaySettings.VisableType.NEVER)
-            return false;
-        return RoughlyEnoughItemsCore.getConfigManager().getConfig().preferVisibleRecipes;
-    }
-    
     default int getDisplayHeight() {
         return getDisplaySettings().getDisplayHeight(this);
     }

+ 10 - 0
src/main/java/me/shedaniel/rei/api/RecipeHelper.java

@@ -35,10 +35,20 @@ public interface RecipeHelper {
     
     void registerSpeedCraftButtonArea(Identifier category, ButtonAreaSupplier rectangle);
     
+    void registerDefaultSpeedCraftButtonArea(Identifier category);
+    
     List<SpeedCraftFunctional> getSpeedCraftFunctional(RecipeCategory category);
     
     void registerSpeedCraftFunctional(Identifier category, SpeedCraftFunctional functional);
     
     Map<RecipeCategory, List<RecipeDisplay>> getAllRecipes();
     
+    void registerRecipeVisibilityHandler(DisplayVisibilityHandler visibilityHandler);
+    
+    void unregisterRecipeVisibilityHandler(DisplayVisibilityHandler visibilityHandler);
+    
+    List<DisplayVisibilityHandler> getDisplayVisibilityHandlers();
+    
+    boolean isDisplayVisible(RecipeDisplay display, boolean respectConfig);
+    
 }

+ 3 - 0
src/main/java/me/shedaniel/rei/client/ConfigObject.java

@@ -45,6 +45,9 @@ public class ConfigObject {
     
     public boolean preferVisibleRecipes = false;
     
+    @Comment("Enable support for old REI plugins which uses registerSpeedCraft")
+    public boolean enableLegacySpeedCraftSupport = false;
+    
     @Comment("The location of choose page dialog")
     public RelativePoint choosePageDialogPoint = new RelativePoint(.5, .5);
     

+ 72 - 5
src/main/java/me/shedaniel/rei/client/RecipeHelperImpl.java

@@ -16,11 +16,17 @@ import java.util.stream.Collectors;
 
 public class RecipeHelperImpl implements RecipeHelper {
     
+    private static final Comparator VISIBILITY_HANDLER_COMPARATOR = Comparator.comparingDouble(value -> {
+        if (value instanceof DisplayVisibilityHandler)
+            return (double) ((DisplayVisibilityHandler) value).getPriority();
+        return -Double.MAX_VALUE;
+    }).reversed();
     private final AtomicInteger recipeCount = new AtomicInteger();
     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<SpeedCraftFunctional>> speedCraftFunctionalMap = Maps.newHashMap();
+    private final List<DisplayVisibilityHandler> displayVisibilityHandlers = Lists.newArrayList();
     private RecipeManager recipeManager;
     
     @Override
@@ -81,8 +87,11 @@ public class RecipeHelperImpl implements RecipeHelper {
         Map<RecipeCategory, List<RecipeDisplay>> recipeCategoryListMap = Maps.newLinkedHashMap();
         categories.forEach(category -> {
             if (categoriesMap.containsKey(category.getIdentifier()) && !categoriesMap.get(category.getIdentifier()).isEmpty())
-                recipeCategoryListMap.put(category, categoriesMap.get(category.getIdentifier()).stream().filter(display -> category.canDisplay(display)).collect(Collectors.toList()));
+                recipeCategoryListMap.put(category, categoriesMap.get(category.getIdentifier()).stream().filter(display -> isDisplayVisible(display, true)).collect(Collectors.toList()));
         });
+        for(RecipeCategory category : Lists.newArrayList(recipeCategoryListMap.keySet()))
+            if (recipeCategoryListMap.get(category).isEmpty())
+                recipeCategoryListMap.remove(category);
         return recipeCategoryListMap;
     }
     
@@ -119,8 +128,11 @@ public class RecipeHelperImpl implements RecipeHelper {
         Map<RecipeCategory, List<RecipeDisplay>> recipeCategoryListMap = Maps.newLinkedHashMap();
         categories.forEach(category -> {
             if (categoriesMap.containsKey(category.getIdentifier()) && !categoriesMap.get(category.getIdentifier()).isEmpty())
-                recipeCategoryListMap.put(category, categoriesMap.get(category.getIdentifier()).stream().filter(display -> category.canDisplay(display)).collect(Collectors.toList()));
+                recipeCategoryListMap.put(category, categoriesMap.get(category.getIdentifier()).stream().filter(display -> isDisplayVisible(display, true)).collect(Collectors.toList()));
         });
+        for(RecipeCategory category : Lists.newArrayList(recipeCategoryListMap.keySet()))
+            if (recipeCategoryListMap.get(category).isEmpty())
+                recipeCategoryListMap.remove(category);
         return recipeCategoryListMap;
     }
     
@@ -132,7 +144,7 @@ public class RecipeHelperImpl implements RecipeHelper {
     @Override
     public Optional<ButtonAreaSupplier> getSpeedCraftButtonArea(RecipeCategory category) {
         if (!speedCraftAreaSupplierMap.containsKey(category.getIdentifier()))
-            return Optional.of(bounds -> new Rectangle((int) bounds.getMaxX() - 16, (int) bounds.getMaxY() - 16, 10, 10));
+            return Optional.empty();
         return Optional.ofNullable(speedCraftAreaSupplierMap.get(category.getIdentifier()));
     }
     
@@ -141,6 +153,11 @@ public class RecipeHelperImpl implements RecipeHelper {
         speedCraftAreaSupplierMap.put(category, rectangle);
     }
     
+    @Override
+    public void registerDefaultSpeedCraftButtonArea(Identifier category) {
+        registerSpeedCraftButtonArea(category, bounds -> new Rectangle((int) bounds.getMaxX() - 16, (int) bounds.getMaxY() - 16, 10, 10));
+    }
+    
     @Override
     public List<SpeedCraftFunctional> getSpeedCraftFunctional(RecipeCategory category) {
         if (speedCraftFunctionalMap.get(category.getIdentifier()) == null)
@@ -163,6 +180,8 @@ public class RecipeHelperImpl implements RecipeHelper {
         this.categories.clear();
         this.speedCraftAreaSupplierMap.clear();
         this.speedCraftFunctionalMap.clear();
+        this.displayVisibilityHandlers.clear();
+        
         List<REIPlugin> plugins = new LinkedList<>(RoughlyEnoughItemsCore.getPlugins());
         plugins.sort((first, second) -> {
             return second.getPriority() - first.getPriority();
@@ -181,9 +200,23 @@ public class RecipeHelperImpl implements RecipeHelper {
                 plugin.registerPluginCategories(this);
             if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_RECIPE_DISPLAYS))
                 plugin.registerRecipeDisplays(this);
-            if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_SPEED_CRAFT))
+            if (RoughlyEnoughItemsCore.getConfigManager().getConfig().enableLegacySpeedCraftSupport && pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_SPEED_CRAFT))
                 plugin.registerSpeedCraft(this);
+            if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_OTHERS))
+                plugin.registerOthers(this);
         });
+        if (getDisplayVisibilityHandlers().size() == 0)
+            registerRecipeVisibilityHandler(new DisplayVisibilityHandler() {
+                @Override
+                public DisplayVisibility handleDisplay(RecipeCategory category, RecipeDisplay display) {
+                    return DisplayVisibility.ALWAYS_VISIBLE;
+                }
+                
+                @Override
+                public float getPriority() {
+                    return -1f;
+                }
+            });
         RoughlyEnoughItemsCore.LOGGER.info("[REI] Registered Categories: " + String.join(", ", categories.stream().map(RecipeCategory::getCategoryName).collect(Collectors.toList())));
         RoughlyEnoughItemsCore.LOGGER.info("[REI] Registered %d recipes.", recipeCount.get());
     }
@@ -200,9 +233,43 @@ public class RecipeHelperImpl implements RecipeHelper {
         recipeCategoryListMap.forEach((identifier, recipeDisplays) -> tempMap.put(identifier, new LinkedList<>(recipeDisplays)));
         categories.forEach(category -> {
             if (tempMap.containsKey(category.getIdentifier()))
-                map.put(category, tempMap.get(category.getIdentifier()).stream().filter(display -> category.canDisplay(display)).collect(Collectors.toList()));
+                map.put(category, tempMap.get(category.getIdentifier()).stream().filter(display -> isDisplayVisible(display, true)).collect(Collectors.toList()));
         });
+        for(RecipeCategory category : Lists.newArrayList(map.keySet()))
+            if (map.get(category).isEmpty())
+                map.remove(category);
         return map;
     }
     
+    @Override
+    public void registerRecipeVisibilityHandler(DisplayVisibilityHandler visibilityHandler) {
+        displayVisibilityHandlers.add(visibilityHandler);
+    }
+    
+    @Override
+    public void unregisterRecipeVisibilityHandler(DisplayVisibilityHandler visibilityHandler) {
+        displayVisibilityHandlers.remove(visibilityHandler);
+    }
+    
+    @Override
+    public List<DisplayVisibilityHandler> getDisplayVisibilityHandlers() {
+        return Collections.unmodifiableList(displayVisibilityHandlers);
+    }
+    
+    @Override
+    public boolean isDisplayVisible(RecipeDisplay display, boolean respectConfig) {
+        RecipeCategory category = getCategory(display.getRecipeCategory());
+        List<DisplayVisibilityHandler> list = Lists.newArrayList(getDisplayVisibilityHandlers());
+        list.sort((o1, o2) -> VISIBILITY_HANDLER_COMPARATOR.compare(o1, o2));
+        for(DisplayVisibilityHandler displayVisibilityHandler : list) {
+            DisplayVisibility visibility = displayVisibilityHandler.handleDisplay(category, display);
+            if (visibility != DisplayVisibility.PASS) {
+                if (visibility == DisplayVisibility.CONFIG_OPTIONAL)
+                    return RoughlyEnoughItemsCore.getConfigManager().getConfig().preferVisibleRecipes || !respectConfig;
+                return visibility == DisplayVisibility.ALWAYS_VISIBLE;
+            }
+        }
+        return true;
+    }
+    
 }

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

@@ -34,7 +34,7 @@ public class ScreenHelper implements ClientModInitializer {
     public static ContainerScreenOverlay getLastOverlay(boolean reset, boolean setPage) {
         if (overlay == null || reset) {
             overlay = new ContainerScreenOverlay();
-            overlay.onInitialized(setPage);
+            overlay.init(setPage);
         }
         return overlay;
     }

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

@@ -36,7 +36,7 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
     public static String searchTerm = "";
     private static int page = 0;
     private static ItemListOverlay itemListOverlay;
-    private final List<Widget> widgets = Lists.newArrayList();
+    private final List<Widget> widgets = Lists.newLinkedList();
     private Rectangle rectangle;
     private Window window;
     private ButtonWidget buttonLeft, buttonRight;
@@ -46,18 +46,18 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
         return itemListOverlay;
     }
     
-    public void onInitialized() {
-        onInitialized(false);
+    public void init() {
+        init(false);
     }
     
-    public void onInitialized(boolean setPage) {
+    public void init(boolean setPage) {
         //Update Variables
-        this.widgets.clear();
+        this.children().clear();
         this.window = MinecraftClient.getInstance().window;
         this.rectangle = calculateBoundary();
         this.lastLeft = getLeft();
         widgets.add(this.itemListOverlay = new ItemListOverlay(page));
-        this.itemListOverlay.updateList(getItemListArea(), page, searchTerm);
+        itemListOverlay.updateList(getItemListArea(), page, searchTerm);
         
         widgets.add(buttonLeft = new ButtonWidget(rectangle.x, rectangle.y + 5, 16, 16, new TranslatableTextComponent("text.rei.left_arrow")) {
             @Override
@@ -313,7 +313,7 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
     public void render(int mouseX, int mouseY, float partialTicks) {
         List<ItemStack> currentStacks = ClientHelper.getInventoryItemsTypes();
         if (getLeft() != lastLeft)
-            onInitialized(true);
+            init(true);
         else if (RoughlyEnoughItemsCore.getConfigManager().isCraftableOnlyEnabled() && (!hasSameListContent(new LinkedList<>(ScreenHelper.inventoryStacks), currentStacks) || (currentStacks.size() != ScreenHelper.inventoryStacks.size()))) {
             ScreenHelper.inventoryStacks = ClientHelper.getInventoryItemsTypes();
             itemListOverlay.updateList(getItemListArea(), page, searchTerm);
@@ -441,10 +441,10 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
     public boolean charTyped(char char_1, int int_1) {
         if (!ScreenHelper.isOverlayVisible())
             return false;
-        for(Element listener : children())
+        for(Element listener : widgets)
             if (listener.charTyped(char_1, int_1))
                 return true;
-        return super.charTyped(char_1, int_1);
+        return false;
     }
     
     @Override
@@ -456,7 +456,7 @@ public class ContainerScreenOverlay extends AbstractParentElement implements Dra
     public boolean mouseClicked(double double_1, double double_2, int int_1) {
         if (!ScreenHelper.isOverlayVisible())
             return false;
-        for(Element element : this.children()) {
+        for(Element element : widgets) {
             if (element.mouseClicked(double_1, double_2, int_1)) {
                 this.method_20084(element);
                 if (int_1 == 0)

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

@@ -83,7 +83,7 @@ public class RecipeViewingScreen extends Screen {
         }
         if ((int_1 == 256 || this.minecraft.options.keyInventory.matchesKey(int_1, int_2)) && this.shouldCloseOnEsc()) {
             MinecraftClient.getInstance().openScreen(ScreenHelper.getLastContainerScreen());
-            ScreenHelper.getLastOverlay().onInitialized();
+            ScreenHelper.getLastOverlay().init();
             return true;
         }
         if (int_1 == 258) {

+ 2 - 2
src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java

@@ -23,7 +23,7 @@ public class CreditsScreen extends Screen {
         if (int_1 == 256 && this.shouldCloseOnEsc()) {
             this.minecraft.openScreen(parent);
             if (parent instanceof ContainerScreen)
-                ScreenHelper.getLastOverlay().onInitialized();
+                ScreenHelper.getLastOverlay().init();
             return true;
         }
         return super.keyPressed(int_1, int_2, int_3);
@@ -40,7 +40,7 @@ public class CreditsScreen extends Screen {
             @Override
             public void onPressed() {
                 CreditsScreen.this.minecraft.openScreen(parent);
-                ScreenHelper.getLastOverlay().onInitialized();
+                ScreenHelper.getLastOverlay().init();
             }
         });
     }

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

@@ -0,0 +1,41 @@
+package me.shedaniel.rei.gui.widget;
+
+import net.minecraft.text.TextComponent;
+
+import java.awt.*;
+
+public class DetailedButtonWidget extends ButtonWidget {
+    
+    private DetailedButtonWidget.PressAction pressAction;
+    
+    public DetailedButtonWidget(Rectangle rectangle, TextComponent 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, TextComponent 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);
+    }
+    
+}

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

@@ -80,10 +80,10 @@ public class ItemListOverlay extends Widget {
     
     public void updateList(Rectangle bounds, int page, String searchTerm) {
         this.rectangle = bounds;
-        this.widgets = Lists.newLinkedList();
-        currentDisplayed = processSearchTerm(searchTerm, RoughlyEnoughItemsCore.getItemRegisterer().getItemList(), ScreenHelper.inventoryStacks);
         this.page = page;
+        this.widgets = Lists.newLinkedList();
         calculateListSize(rectangle);
+        currentDisplayed = processSearchTerm(searchTerm, RoughlyEnoughItemsCore.getItemRegisterer().getItemList(), ScreenHelper.inventoryStacks);
         double startX = rectangle.getCenterX() - width * 9;
         double startY = rectangle.getCenterY() - height * 9;
         this.listArea = new Rectangle((int) startX, (int) startY, width * 18, height * 18);
@@ -91,7 +91,7 @@ public class ItemListOverlay extends Widget {
             int j = i + page * getTotalSlotsPerPage();
             if (j >= currentDisplayed.size())
                 break;
-            ItemSlotWidget slotWidget = new ItemSlotWidget((int) (startX + (i % width) * 18), (int) (startY + MathHelper.floor(i / width) * 18), Collections.singletonList(currentDisplayed.get(j)), false, true, true) {
+            widgets.add(new ItemSlotWidget((int) (startX + (i % width) * 18), (int) (startY + MathHelper.floor(i / width) * 18), Collections.singletonList(currentDisplayed.get(j)), false, true, true) {
                 @Override
                 protected void drawToolTip(ItemStack itemStack, float delta) {
                     ClientPlayerEntity player = minecraft.player;
@@ -115,9 +115,7 @@ public class ItemListOverlay extends Widget {
                     }
                     return false;
                 }
-            };
-            if (true || this.rectangle.contains(slotWidget.getBounds()))
-                widgets.add(slotWidget);
+            });
         }
     }
     
@@ -220,7 +218,7 @@ public class ItemListOverlay extends Widget {
         return true;
     }
     
-    private void calculateListSize(Rectangle rect) {
+    public void calculateListSize(Rectangle rect) {
         int xOffset = 0, yOffset = 0;
         width = 0;
         height = 0;

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

@@ -23,7 +23,7 @@ public class SpeedCraftingButtonWidget extends ButtonWidget {
     @Override
     public void onPressed() {
         minecraft.openScreen(ScreenHelper.getLastContainerScreen());
-        ScreenHelper.getLastOverlay().onInitialized();
+        ScreenHelper.getLastOverlay().init();
         functional.performAutoCraft(ScreenHelper.getLastContainerScreen(), displaySupplier.get());
     }
     

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

@@ -122,10 +122,22 @@ public class DefaultPlugin implements REIPlugin {
     }
     
     @Override
-    public void registerSpeedCraft(RecipeHelper recipeHelper) {
-        recipeHelper.registerSpeedCraftButtonArea(DefaultPlugin.CAMPFIRE, null);
-        recipeHelper.registerSpeedCraftButtonArea(DefaultPlugin.STONE_CUTTING, null);
-        recipeHelper.registerSpeedCraftButtonArea(DefaultPlugin.BREWING, null);
+    public void registerOthers(RecipeHelper recipeHelper) {
+        recipeHelper.registerRecipeVisibilityHandler(new DisplayVisibilityHandler() {
+            @Override
+            public DisplayVisibility handleDisplay(RecipeCategory category, RecipeDisplay display) {
+                return DisplayVisibility.ALWAYS_VISIBLE;
+            }
+            
+            @Override
+            public float getPriority() {
+                return -1f;
+            }
+        });
+        recipeHelper.registerDefaultSpeedCraftButtonArea(DefaultPlugin.CRAFTING);
+        recipeHelper.registerDefaultSpeedCraftButtonArea(DefaultPlugin.SMELTING);
+        recipeHelper.registerDefaultSpeedCraftButtonArea(DefaultPlugin.SMOKING);
+        recipeHelper.registerDefaultSpeedCraftButtonArea(DefaultPlugin.BLASTING);
         recipeHelper.registerSpeedCraftFunctional(DefaultPlugin.CRAFTING, new SpeedCraftFunctional<DefaultCraftingDisplay>() {
             @Override
             public Class[] getFunctioningFor() {

+ 18 - 6
src/main/java/me/shedaniel/rei/utils/ClothRegistry.java

@@ -1,5 +1,6 @@
 package me.shedaniel.rei.utils;
 
+import com.google.common.collect.Lists;
 import javafx.util.Pair;
 import me.shedaniel.cloth.api.ClientUtils;
 import me.shedaniel.cloth.api.ConfigScreenBuilder;
@@ -16,8 +17,10 @@ import me.shedaniel.rei.gui.config.ItemListOrderingEntry;
 import me.shedaniel.rei.listeners.CreativePlayerInventoryScreenHooks;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.ContainerScreen;
+import net.minecraft.client.gui.Element;
 import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.ingame.CreativePlayerInventoryScreen;
+import net.minecraft.client.gui.ingame.PlayerInventoryScreen;
 import net.minecraft.client.gui.widget.RecipeBookButtonWidget;
 import net.minecraft.client.resource.language.I18n;
 import net.minecraft.item.ItemGroup;
@@ -38,13 +41,21 @@ public class ClothRegistry {
         });
         ClothClientHooks.SCREEN_INIT_POST.register((minecraftClient, screen, screenHooks) -> {
             if (screen instanceof ContainerScreen) {
-                if (screen instanceof CreativePlayerInventoryScreen) {
-                    CreativePlayerInventoryScreenHooks creativePlayerInventoryScreenHooks = (CreativePlayerInventoryScreenHooks) screen;
-                    if (creativePlayerInventoryScreenHooks.rei_getSelectedTab() != ItemGroup.INVENTORY.getIndex())
+                if (screen instanceof CreativePlayerInventoryScreen)
+                    if (((CreativePlayerInventoryScreenHooks) screen).rei_getSelectedTab() != ItemGroup.INVENTORY.getIndex())
                         return;
-                }
+                if (screen instanceof PlayerInventoryScreen && minecraftClient.interactionManager.hasCreativeInventory())
+                    return;
                 ScreenHelper.setLastContainerScreen((ContainerScreen) screen);
-                screenHooks.cloth_getInputListeners().add(ScreenHelper.getLastOverlay(true, false));
+                boolean alreadyAdded = false;
+                for(Element element : Lists.newArrayList(screenHooks.cloth_getInputListeners()))
+                    if (ContainerScreenOverlay.class.isAssignableFrom(element.getClass()))
+                        if (alreadyAdded)
+                            screenHooks.cloth_getInputListeners().remove(element);
+                        else
+                            alreadyAdded = true;
+                if (!alreadyAdded)
+                    screenHooks.cloth_getInputListeners().add(ScreenHelper.getLastOverlay(true, false));
             }
         });
         ClothClientHooks.SCREEN_RENDER_POST.register((minecraftClient, screen, i, i1, v) -> {
@@ -86,7 +97,7 @@ public class ClothRegistry {
     }
     
     public static void openConfigScreen(Screen parent) {
-        ClothConfigScreen.Builder builder = new ClothConfigScreen.Builder(parent, I18n.translate("text.rei.config.title"), null);
+        ConfigScreenBuilder builder = new ClothConfigScreen.Builder(parent, I18n.translate("text.rei.config.title"), null);
         builder.addCategory("text.rei.config.general").addOption(new BooleanListEntry("text.rei.config.cheating", RoughlyEnoughItemsCore.getConfigManager().getConfig().cheating, "text.cloth.reset_value", () -> false, bool -> RoughlyEnoughItemsCore.getConfigManager().getConfig().cheating = bool));
         ConfigScreenBuilder.CategoryBuilder appearance = builder.addCategory("text.rei.config.appearance");
         appearance.addOption(new BooleanListEntry("text.rei.config.side_search_box", RoughlyEnoughItemsCore.getConfigManager().getConfig().sideSearchField, "text.cloth.reset_value", () -> false, bool -> RoughlyEnoughItemsCore.getConfigManager().getConfig().sideSearchField = bool));
@@ -102,6 +113,7 @@ public class ClothRegistry {
         advanced.addOption(new StringListEntry("text.rei.gamemode_command", RoughlyEnoughItemsCore.getConfigManager().getConfig().gamemodeCommand, "text.cloth.reset_value", () -> "/gamemode {gamemode}", s -> RoughlyEnoughItemsCore.getConfigManager().getConfig().gamemodeCommand = s));
         advanced.addOption(new StringListEntry("text.rei.weather_command", RoughlyEnoughItemsCore.getConfigManager().getConfig().weatherCommand, "text.cloth.reset_value", () -> "/weather {weather}", s -> RoughlyEnoughItemsCore.getConfigManager().getConfig().weatherCommand = s));
         advanced.addOption(new BooleanListEntry("text.rei.config.prefer_visible_recipes", RoughlyEnoughItemsCore.getConfigManager().getConfig().preferVisibleRecipes, "text.cloth.reset_value", () -> false, bool -> RoughlyEnoughItemsCore.getConfigManager().getConfig().preferVisibleRecipes = bool));
+        advanced.addOption(new BooleanListEntry("text.rei.config.enable_legacy_speedcraft_support", RoughlyEnoughItemsCore.getConfigManager().getConfig().enableLegacySpeedCraftSupport, "text.cloth.reset_value", () -> false, bool -> RoughlyEnoughItemsCore.getConfigManager().getConfig().enableLegacySpeedCraftSupport = bool));
         builder.setOnSave(savedConfig -> {
             try {
                 RoughlyEnoughItemsCore.getConfigManager().saveConfig();

+ 2 - 1
src/main/resources/assets/roughlyenoughitems/lang/en_us.json

@@ -72,8 +72,9 @@
   "text.rei.next_category": "Next Category",
   "text.rei.previous_page": "Previous Page",
   "text.rei.next_page": "Next Page",
-  "text.rei.config.prefer_visible_recipes": "Prefer Visible Recipes",
+  "text.rei.config.prefer_visible_recipes": "Prefer Visible Recipes: ",
   "text.rei.config.title": "Roughly Enough Items Config",
+  "text.rei.config.enable_legacy_speedcraft_support": "Enable Legacy Plugin Support: ",
   "_comment": "Don't change / translate the credit down below if you are doing it :)",
   "text.rei.credit.text": "§lRoughly Enough Items\n§7Originally a fork for Almost Enough Items.\n\n§lDevelopers\n  - Originally by ZenDarva\n  - Created by Danielshe\n  - Plugin Support by TehNut\n\n§lLanguage Translation\n  English - Danielshe\n  Simplified Chinese - Danielshe\n  Traditional Chinese - hugoalh & Danielshe\n  French - Yanis48\n  German - MelanX\n  Estonian - Madis0\n  Portuguese - thiagokenis\n  LOLCAT - Danielshe\n  Upside Down - Danielshe\n\n§lLicense\n§7Roughly Enough Items is using MIT."
 }

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

@@ -13,10 +13,10 @@
     "me.shedaniel.rei.client.ScreenHelper"
   ],
   "requires": {
-    "fabric": "0.2.3"
+    "fabric": "^0.2.3"
   },
   "recommended": {
-    "pluginloader": "1.0.6"
+    "pluginloader": "^1.0.6"
   },
   "mixins": {
     "client": "roughlyenoughitems.client.json"