Browse Source

REI Update v2.3 (#35)

* Fixes #33

* Fixes #32

* Fix #29

* Highlight Cursor

* Fix #15

* Remove Unwanted Imports

* Making it actually v2.3

* LOLCATS & Upside Down Lanuage + Credits Screen

* better credits

* Better Config

* Better Config Button Handling + Campfire text using container sub-colour

* Better Plugin Handling

* Split ItemRegisterer out from ClientHelper

* Option to disable default plugin.
Daniel She 6 năm trước cách đây
mục cha
commit
93dc019f11
43 tập tin đã thay đổi với 936 bổ sung410 xóa
  1. 1 1
      build.gradle
  2. 16 5
      src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java
  3. 35 0
      src/main/java/me/shedaniel/rei/api/IItemRegisterer.java
  4. 23 0
      src/main/java/me/shedaniel/rei/api/IPluginDisabler.java
  5. 9 3
      src/main/java/me/shedaniel/rei/api/IRecipePlugin.java
  6. 5 0
      src/main/java/me/shedaniel/rei/api/PluginFunction.java
  7. 4 53
      src/main/java/me/shedaniel/rei/client/ClientHelper.java
  8. 9 0
      src/main/java/me/shedaniel/rei/client/ConfigHelper.java
  9. 8 11
      src/main/java/me/shedaniel/rei/client/GuiHelper.java
  10. 53 0
      src/main/java/me/shedaniel/rei/client/ItemListHelper.java
  11. 1 0
      src/main/java/me/shedaniel/rei/client/REIConfig.java
  12. 15 4
      src/main/java/me/shedaniel/rei/client/RecipeHelper.java
  13. 31 27
      src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
  14. 70 0
      src/main/java/me/shedaniel/rei/gui/config/ConfigEntry.java
  15. 35 0
      src/main/java/me/shedaniel/rei/gui/config/ConfigEntryListWidget.java
  16. 207 0
      src/main/java/me/shedaniel/rei/gui/config/ConfigScreen.java
  17. 22 0
      src/main/java/me/shedaniel/rei/gui/credits/CreditsEntry.java
  18. 35 0
      src/main/java/me/shedaniel/rei/gui/credits/CreditsEntryListWidget.java
  19. 64 0
      src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java
  20. 16 26
      src/main/java/me/shedaniel/rei/gui/widget/ButtonWidget.java
  21. 0 177
      src/main/java/me/shedaniel/rei/gui/widget/ConfigWidget.java
  22. 4 5
      src/main/java/me/shedaniel/rei/gui/widget/CraftableToggleButtonWidget.java
  23. 14 21
      src/main/java/me/shedaniel/rei/gui/widget/ItemListOverlay.java
  24. 25 10
      src/main/java/me/shedaniel/rei/gui/widget/ItemSlotWidget.java
  25. 2 1
      src/main/java/me/shedaniel/rei/gui/widget/RecipeViewingWidgetScreen.java
  26. 1 0
      src/main/java/me/shedaniel/rei/gui/widget/SpeedCraftingButtonWidget.java
  27. 6 9
      src/main/java/me/shedaniel/rei/listeners/IMixinContainerScreen.java
  28. 8 15
      src/main/java/me/shedaniel/rei/mixin/MixinContainerScreen.java
  29. 1 1
      src/main/java/me/shedaniel/rei/plugin/DefaultBlastingCategory.java
  30. 2 2
      src/main/java/me/shedaniel/rei/plugin/DefaultCampfireCategory.java
  31. 65 28
      src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java
  32. 1 1
      src/main/java/me/shedaniel/rei/plugin/DefaultSmeltingCategory.java
  33. 1 1
      src/main/java/me/shedaniel/rei/plugin/DefaultSmokingCategory.java
  34. 43 0
      src/main/java/me/shedaniel/rei/plugin/PluginManager.java
  35. 3 2
      src/main/java/me/shedaniel/rei/update/UpdateChecker.java
  36. 1 1
      src/main/resources/assets/roughlyenoughitems/lang/de_de.json
  37. 42 0
      src/main/resources/assets/roughlyenoughitems/lang/en_ud.json
  38. 7 2
      src/main/resources/assets/roughlyenoughitems/lang/en_us.json
  39. 1 1
      src/main/resources/assets/roughlyenoughitems/lang/et_ee.json
  40. 42 0
      src/main/resources/assets/roughlyenoughitems/lang/lol_us.json
  41. 1 1
      src/main/resources/assets/roughlyenoughitems/lang/zh_cn.json
  42. 1 1
      src/main/resources/assets/roughlyenoughitems/lang/zh_tw.json
  43. 6 1
      version.json

+ 1 - 1
build.gradle

@@ -6,7 +6,7 @@ sourceCompatibility = 1.8
 targetCompatibility = 1.8
 
 archivesBaseName = "RoughlyEnoughItems"
-version = "2.2.0.50"
+version = "2.3.0.51"
 
 def minecraftVersion = "19w06a"
 def yarnVersion = "19w06a.5"

+ 16 - 5
src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java

@@ -1,12 +1,15 @@
 package me.shedaniel.rei;
 
 import com.google.common.collect.Maps;
+import me.shedaniel.rei.api.IItemRegisterer;
+import me.shedaniel.rei.api.IPluginDisabler;
 import me.shedaniel.rei.api.IRecipePlugin;
-import me.shedaniel.rei.client.ClientHelper;
 import me.shedaniel.rei.client.ConfigHelper;
 import me.shedaniel.rei.client.GuiHelper;
+import me.shedaniel.rei.client.ItemListHelper;
 import me.shedaniel.rei.client.RecipeHelper;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import me.shedaniel.rei.plugin.PluginManager;
 import me.shedaniel.rei.update.UpdateChecker;
 import net.fabricmc.api.ClientModInitializer;
 import net.fabricmc.api.ModInitializer;
@@ -33,7 +36,8 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer, ModInitiali
     public static final Identifier DELETE_ITEMS_PACKET = new Identifier("roughlyenoughitems", "delete_item");
     public static final Identifier CREATE_ITEMS_PACKET = new Identifier("roughlyenoughitems", "create_item");
     private static final RecipeHelper RECIPE_HELPER = new RecipeHelper();
-    private static final ClientHelper CLIENT_HELPER = new ClientHelper();
+    private static final PluginManager PLUGIN_MANAGER = new PluginManager();
+    private static final ItemListHelper ITEM_LIST_HELPER = new ItemListHelper();
     private static final Map<Identifier, IRecipePlugin> plugins = Maps.newHashMap();
     private static ConfigHelper configHelper;
     
@@ -45,13 +49,18 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer, ModInitiali
         return configHelper;
     }
     
-    public static ClientHelper getClientHelper() {
-        return CLIENT_HELPER;
+    public static IItemRegisterer getItemRegisterer() {
+        return ITEM_LIST_HELPER;
+    }
+    
+    public static IPluginDisabler getPluginDisabler() {
+        return PLUGIN_MANAGER;
     }
     
     public static IRecipePlugin registerPlugin(Identifier identifier, IRecipePlugin plugin) {
         plugins.put(identifier, plugin);
         RoughlyEnoughItemsCore.LOGGER.info("REI: Registered plugin %s from %s", identifier.toString(), plugin.getClass().getSimpleName());
+        plugin.onFirstLoad(getPluginDisabler());
         return plugin;
     }
     
@@ -66,14 +75,16 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer, ModInitiali
         return null;
     }
     
+    @SuppressWarnings("deprecation")
     @Override
     public void onInitializeClient() {
+        configHelper = new ConfigHelper();
+        
         // If pluginloader is not installed, base functionality should still remain
         if (!FabricLoader.INSTANCE.getModContainers().stream().map(modContainer -> modContainer.getInfo().getId()).anyMatch(s -> s.equalsIgnoreCase("pluginloader"))) {
             RoughlyEnoughItemsCore.LOGGER.warn("REI: Plugin Loader is not loaded! Please consider installing https://minecraft.curseforge.com/projects/pluginloader for REI plugin compatibility!");
             registerPlugin(new Identifier("roughlyenoughitems", "default_plugin"), new DefaultPlugin());
         }
-        configHelper = new ConfigHelper();
         
         ClientTickCallback.EVENT.register(GuiHelper::onTick);
         if (getConfigHelper().checkUpdates())

+ 35 - 0
src/main/java/me/shedaniel/rei/api/IItemRegisterer.java

@@ -0,0 +1,35 @@
+package me.shedaniel.rei.api;
+
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+
+import java.util.List;
+
+public interface IItemRegisterer {
+    
+    public List<ItemStack> getItemList();
+    
+    @Deprecated
+    public List<ItemStack> getModifiableItemList();
+    
+    public ItemStack[] getAllStacksFromItem(Item item);
+    
+    public void registerItemStack(Item afterItem, ItemStack stack);
+    
+    default public void registerItemStack(Item afterItem, ItemStack... stacks) {
+        for(ItemStack stack : stacks)
+            if (stack != null && !stack.isEmpty())
+                registerItemStack(afterItem, stack);
+    }
+    
+    default public void registerItemStack(ItemStack... stacks) {
+        for(ItemStack stack : stacks)
+            if (stack != null && !stack.isEmpty())
+                registerItemStack(null, stack);
+    }
+    
+    default boolean alreadyContain(ItemStack stack) {
+        return getItemList().stream().anyMatch(stack1 -> ItemStack.areEqual(stack, stack1));
+    }
+    
+}

+ 23 - 0
src/main/java/me/shedaniel/rei/api/IPluginDisabler.java

@@ -0,0 +1,23 @@
+package me.shedaniel.rei.api;
+
+import net.minecraft.util.Identifier;
+
+public interface IPluginDisabler {
+    
+    default public void disablePluginFunctions(Identifier plugin, PluginFunction... functions) {
+        for(PluginFunction function : functions)
+            disablePluginFunction(plugin, function);
+    }
+    
+    default public void enablePluginFunctions(Identifier plugin, PluginFunction... functions) {
+        for(PluginFunction function : functions)
+            enablePluginFunction(plugin, function);
+    }
+    
+    public void disablePluginFunction(Identifier plugin, PluginFunction function);
+    
+    public void enablePluginFunction(Identifier plugin, PluginFunction function);
+    
+    public boolean isFunctionEnabled(Identifier plugin, PluginFunction function);
+    
+}

+ 9 - 3
src/main/java/me/shedaniel/rei/api/IRecipePlugin.java

@@ -1,12 +1,18 @@
 package me.shedaniel.rei.api;
 
+import me.shedaniel.rei.client.RecipeHelper;
+
 public interface IRecipePlugin {
     
-    public void registerPluginCategories();
+    default public void onFirstLoad(IPluginDisabler pluginDisabler) {}
+    
+    public void registerItems(IItemRegisterer itemRegisterer);
+    
+    public void registerPluginCategories(RecipeHelper recipeHelper);
     
-    public void registerRecipes();
+    public void registerRecipeDisplays(RecipeHelper recipeHelper);
     
-    public void registerSpeedCraft();
+    public void registerSpeedCraft(RecipeHelper recipeHelper);
     
     default public int getPriority() {
         return 0;

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

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

+ 4 - 53
src/main/java/me/shedaniel/rei/client/ClientHelper.java

@@ -1,26 +1,22 @@
 package me.shedaniel.rei.client;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
 import io.netty.buffer.Unpooled;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.IRecipeCategory;
 import me.shedaniel.rei.api.IRecipeDisplay;
 import me.shedaniel.rei.gui.ContainerScreenOverlay;
-import me.shedaniel.rei.gui.widget.ConfigWidget;
+import me.shedaniel.rei.gui.config.ConfigScreen;
 import me.shedaniel.rei.gui.widget.RecipeViewingWidgetScreen;
 import net.fabricmc.api.ClientModInitializer;
 import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
 import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
 import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl;
-import net.fabricmc.loader.FabricLoader;
+import net.fabricmc.loader.api.FabricLoader;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.Mouse;
 import net.minecraft.client.gui.Screen;
 import net.minecraft.client.util.InputUtil;
-import net.minecraft.enchantment.Enchantment;
-import net.minecraft.enchantment.EnchantmentHelper;
-import net.minecraft.item.Item;
 import net.minecraft.item.ItemStack;
 import net.minecraft.item.Items;
 import net.minecraft.util.DefaultedList;
@@ -30,7 +26,6 @@ import net.minecraft.util.registry.Registry;
 
 import java.awt.*;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -40,13 +35,8 @@ public class ClientHelper implements ClientModInitializer {
     private static final Identifier USAGE_KEYBIND = new Identifier("roughlyenoughitems", "usage_keybind");
     private static final Identifier HIDE_KEYBIND = new Identifier("roughlyenoughitems", "hide_keybind");
     public static FabricKeyBinding RECIPE, USAGE, HIDE;
-    private static List<ItemStack> itemList;
     private static boolean cheating;
     
-    public ClientHelper() {
-        this.itemList = Lists.newLinkedList();
-    }
-    
     public static String getModFromItemStack(ItemStack stack) {
         if (!stack.isEmpty()) {
             Identifier location = Registry.ITEM.getId(stack.getItem());
@@ -54,7 +44,7 @@ public class ClientHelper implements ClientModInitializer {
             String modid = location.getNamespace();
             if (modid.equalsIgnoreCase("minecraft"))
                 return "Minecraft";
-            return FabricLoader.INSTANCE.getModContainers().stream().map(modContainer -> {
+            return ((net.fabricmc.loader.FabricLoader) FabricLoader.getInstance()).getModContainers().stream().map(modContainer -> {
                 return modContainer.getInfo();
             }).filter(modInfo -> modInfo.getId().equals(modid) || (modInfo.getName() != null && modInfo.getName().equals(modid))).findFirst().map(modInfo -> {
                 if (modInfo.getName() != null)
@@ -65,10 +55,6 @@ public class ClientHelper implements ClientModInitializer {
         return "";
     }
     
-    public static List<ItemStack> getItemList() {
-        return itemList;
-    }
-    
     public static Point getMouseLocation() {
         MinecraftClient client = MinecraftClient.getInstance();
         Mouse mouse = client.mouse;
@@ -127,7 +113,7 @@ public class ClientHelper implements ClientModInitializer {
     }
     
     public static void openConfigWindow(Screen parent) {
-        MinecraftClient.getInstance().openScreen(new ConfigWidget(parent));
+        MinecraftClient.getInstance().openScreen(new ConfigScreen(parent));
     }
     
     public static List<ItemStack> getInventoryItemsTypes() {
@@ -140,41 +126,6 @@ public class ClientHelper implements ClientModInitializer {
         return inventoryStacks;
     }
     
-    public void clientLoaded() {
-        Registry.ITEM.forEach(item -> {
-            if (!item.equals(Items.ENCHANTED_BOOK))
-                registerItem(item);
-        });
-        Registry.ENCHANTMENT.forEach(enchantment -> {
-            for(int i = enchantment.getMinimumLevel(); i < enchantment.getMaximumLevel(); i++) {
-                Map<Enchantment, Integer> map = new HashMap<>();
-                map.put(enchantment, i);
-                ItemStack itemStack = new ItemStack(Items.ENCHANTED_BOOK);
-                EnchantmentHelper.set(map, itemStack);
-                registerItemStack(itemStack);
-            }
-        });
-    }
-    
-    public void registerItem(Item item) {
-        registerItemStack(item.getDefaultStack());
-        DefaultedList<ItemStack> stacks = DefaultedList.create();
-        item.addStacksForDisplay(item.getItemGroup(), stacks);
-        stacks.forEach(this::registerItemStack);
-    }
-    
-    public void registerItemStack(ItemStack stack) {
-        if (!stack.getItem().equals(Items.AIR) && !alreadyContain(stack))
-            itemList.add(stack);
-    }
-    
-    private boolean alreadyContain(ItemStack stack) {
-        for(ItemStack itemStack : itemList)
-            if (ItemStack.areEqual(stack, itemStack))
-                return true;
-        return false;
-    }
-    
     @Override
     public void onInitializeClient() {
         this.cheating = false;

+ 9 - 0
src/main/java/me/shedaniel/rei/client/ConfigHelper.java

@@ -20,6 +20,7 @@ public class ConfigHelper {
         this.craftableOnly = false;
         try {
             loadConfig();
+            RoughlyEnoughItemsCore.LOGGER.info("REI: Config is loaded.");
         } catch (IOException e) {
             e.printStackTrace();
         }
@@ -119,4 +120,12 @@ public class ConfigHelper {
         config.mirrorItemPanel = mirrorItemPanel;
     }
     
+    public boolean isLoadingDefaultPlugin() {
+        return config.loadDefaultPlugin;
+    }
+    
+    public void setLoadingDefaultPlugin(boolean loadDefaultPlugin) {
+        config.loadDefaultPlugin = loadDefaultPlugin;
+    }
+    
 }

+ 8 - 11
src/main/java/me/shedaniel/rei/client/GuiHelper.java

@@ -17,7 +17,6 @@ public class GuiHelper {
     private static boolean overlayVisible = true;
     private static ContainerScreenOverlay overlay;
     private static ContainerScreen lastContainerScreen;
-    private static IMixinContainerScreen lastMixinContainerScreen;
     
     public static boolean isOverlayVisible() {
         return overlayVisible;
@@ -27,19 +26,21 @@ public class GuiHelper {
         overlayVisible = !overlayVisible;
     }
     
-    public static ContainerScreenOverlay getLastOverlay() {
+    public static ContainerScreenOverlay getLastOverlay(boolean reset) {
+        if (overlay == null || reset) {
+            overlay = new ContainerScreenOverlay();
+            overlay.onInitialized();
+        }
         return overlay;
     }
     
-    public static void setOverlay(ContainerScreenOverlay overlay) {
-        GuiHelper.overlay = overlay;
-        overlay.onInitialized();
+    public static ContainerScreenOverlay getLastOverlay() {
+        return getLastOverlay(false);
     }
     
     public static void onTick(MinecraftClient client) {
         if (client.currentScreen instanceof ContainerScreen && lastContainerScreen != client.currentScreen) {
             GuiHelper.lastContainerScreen = (ContainerScreen) client.currentScreen;
-            GuiHelper.lastMixinContainerScreen = (IMixinContainerScreen) lastContainerScreen;
         }
     }
     
@@ -52,11 +53,7 @@ public class GuiHelper {
     }
     
     public static IMixinContainerScreen getLastMixinContainerScreen() {
-        return lastMixinContainerScreen;
-    }
-    
-    public static void setLastMixinContainerScreen(IMixinContainerScreen lastMixinContainerScreen) {
-        GuiHelper.lastMixinContainerScreen = lastMixinContainerScreen;
+        return (IMixinContainerScreen) lastContainerScreen;
     }
     
 }

+ 53 - 0
src/main/java/me/shedaniel/rei/client/ItemListHelper.java

@@ -0,0 +1,53 @@
+package me.shedaniel.rei.client;
+
+import com.google.common.collect.Lists;
+import me.shedaniel.rei.api.IItemRegisterer;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+import net.minecraft.util.DefaultedList;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+public class ItemListHelper implements IItemRegisterer {
+    
+    private final List<ItemStack> itemList = Lists.newLinkedList();
+    
+    @Override
+    public List<ItemStack> getItemList() {
+        return Collections.unmodifiableList(itemList);
+    }
+    
+    @Deprecated
+    @Override
+    public List<ItemStack> getModifiableItemList() {
+        return itemList;
+    }
+    
+    @Override
+    public ItemStack[] getAllStacksFromItem(Item item) {
+        DefaultedList<ItemStack> list = DefaultedList.create();
+        list.add(item.getDefaultStack());
+        item.addStacksForDisplay(item.getItemGroup(), list);
+        TreeSet<ItemStack> stackSet = list.stream().collect(Collectors.toCollection(() -> new TreeSet<ItemStack>((p1, p2) -> ItemStack.areEqual(p1, p2) ? 0 : 1)));
+        return Lists.newArrayList(stackSet).toArray(new ItemStack[0]);
+    }
+    
+    @Override
+    public void registerItemStack(Item afterItem, ItemStack stack) {
+        if (!stack.isEmpty() && !alreadyContain(stack))
+            if (afterItem == null || afterItem.equals(Items.AIR))
+                itemList.add(stack);
+            else {
+                int last = itemList.size();
+                for(int i = 0; i < itemList.size(); i++)
+                    if (itemList.get(i).getItem().equals(afterItem))
+                        last = i + 1;
+                itemList.add(last, stack);
+            }
+    }
+    
+}

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

@@ -14,5 +14,6 @@ public class REIConfig {
     public String giveCommandPrefix = "/give";
     public boolean checkUpdates = true;
     public boolean mirrorItemPanel = false;
+    public boolean loadDefaultPlugin = true;
     
 }

+ 15 - 4
src/main/java/me/shedaniel/rei/client/RecipeHelper.java

@@ -59,7 +59,7 @@ public class RecipeHelper {
         recipeCategoryListMap.put(category.getIdentifier(), Lists.newLinkedList());
     }
     
-    public void registerRecipe(Identifier categoryIdentifier, IRecipeDisplay display) {
+    public void registerDisplay(Identifier categoryIdentifier, IRecipeDisplay display) {
         if (!recipeCategoryListMap.containsKey(categoryIdentifier))
             return;
         recipeCategoryListMap.get(categoryIdentifier).add(display);
@@ -147,6 +147,7 @@ public class RecipeHelper {
         speedCraftFunctionalMap.put(category, list);
     }
     
+    @SuppressWarnings("deprecation")
     public void recipesLoaded(RecipeManager recipeManager) {
         this.recipeManager = recipeManager;
         this.recipeCategoryListMap.clear();
@@ -162,10 +163,20 @@ public class RecipeHelper {
             return identifier == null ? "NULL" : identifier.toString();
         }).collect(Collectors.toList())));
         Collections.reverse(plugins);
+        RoughlyEnoughItemsCore.getItemRegisterer().getModifiableItemList().clear();
+        IPluginDisabler pluginDisabler = RoughlyEnoughItemsCore.getPluginDisabler();
         plugins.forEach(plugin -> {
-            plugin.registerPluginCategories();
-            plugin.registerRecipes();
-            plugin.registerSpeedCraft();
+            Identifier identifier = RoughlyEnoughItemsCore.getPluginIdentifier(plugin);
+            if (identifier == null)
+                identifier = new Identifier("null");
+            if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_ITEMS))
+                plugin.registerItems(RoughlyEnoughItemsCore.getItemRegisterer());
+            if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_CATEGORIES))
+                plugin.registerPluginCategories(this);
+            if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_RECIPE_DISPLAYS))
+                plugin.registerRecipeDisplays(this);
+            if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_SPEED_CRAFT))
+                plugin.registerSpeedCraft(this);
         });
         RoughlyEnoughItemsCore.LOGGER.info("Registered REI Categories: " + String.join(", ", categories.stream().map(category -> {
             return category.getCategoryName();

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

@@ -5,11 +5,12 @@ import com.mojang.blaze3d.platform.GlStateManager;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.client.ClientHelper;
 import me.shedaniel.rei.client.GuiHelper;
+import me.shedaniel.rei.gui.credits.CreditsScreen;
 import me.shedaniel.rei.gui.widget.*;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.ContainerScreen;
+import net.minecraft.client.gui.DrawableContainer;
 import net.minecraft.client.gui.GuiEventListener;
-import net.minecraft.client.gui.Screen;
 import net.minecraft.client.render.GuiLighting;
 import net.minecraft.client.resource.language.I18n;
 import net.minecraft.client.util.Window;
@@ -22,7 +23,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.stream.Collectors;
 
-public class ContainerScreenOverlay extends Screen {
+public class ContainerScreenOverlay extends DrawableContainer {
     
     private static final List<QueuedTooltip> QUEUED_TOOLTIPS = Lists.newArrayList();
     public static String searchTerm = "";
@@ -80,7 +81,13 @@ public class ContainerScreenOverlay extends Screen {
                 ClientHelper.openConfigWindow(GuiHelper.getLastContainerScreen());
             }
         });
-        this.widgets.add(new LabelWidget(rectangle.x + (rectangle.width / 2), rectangle.y + 10, "") {
+        widgets.add(new ButtonWidget(RoughlyEnoughItemsCore.getConfigHelper().isMirrorItemPanel() ? window.getScaledWidth() - 50 : 10, window.getScaledHeight() - 30, 40, 20, I18n.translate("text.rei.credits")) {
+            @Override
+            public void onPressed(int button, double mouseX, double mouseY) {
+                MinecraftClient.getInstance().openScreen(new CreditsScreen(GuiHelper.getLastContainerScreen()));
+            }
+        });
+        widgets.add(new LabelWidget(rectangle.x + (rectangle.width / 2), rectangle.y + 10, "") {
             @Override
             public void draw(int mouseX, int mouseY, float partialTicks) {
                 page = MathHelper.clamp(page, 0, getTotalPage());
@@ -101,7 +108,7 @@ public class ContainerScreenOverlay extends Screen {
             };
         GuiHelper.searchField.setChangedListener(s -> {
             searchTerm = s;
-            itemListOverlay.updateList(page, searchTerm);
+            itemListOverlay.updateList(getItemListArea(), page, searchTerm);
         });
         GuiHelper.searchField.setBounds(getTextFieldArea());
         this.widgets.add(GuiHelper.searchField);
@@ -111,12 +118,11 @@ public class ContainerScreenOverlay extends Screen {
                 @Override
                 public void onPressed(int button, double mouseX, double mouseY) {
                     RoughlyEnoughItemsCore.getConfigHelper().toggleCraftableOnly();
-                    itemListOverlay.updateList(page, searchTerm);
+                    itemListOverlay.updateList(getItemListArea(), page, searchTerm);
                 }
             });
         
         this.itemListOverlay.updateList(getItemListArea(), page, searchTerm);
-        this.listeners.addAll(widgets);
     }
     
     private Rectangle getTextFieldArea() {
@@ -127,7 +133,7 @@ public class ContainerScreenOverlay extends Screen {
             RecipeViewingWidgetScreen widget = (RecipeViewingWidgetScreen) MinecraftClient.getInstance().currentScreen;
             return new Rectangle(widget.getBounds().x, window.getScaledHeight() - 22, widget.getBounds().width - widthRemoved, 18);
         }
-        return new Rectangle(GuiHelper.getLastMixinContainerScreen().getContainerLeft(), window.getScaledHeight() - 22, GuiHelper.getLastMixinContainerScreen().getContainerWidth() - widthRemoved, 18);
+        return new Rectangle(GuiHelper.getLastMixinContainerScreen().rei_getContainerLeft(), window.getScaledHeight() - 22, GuiHelper.getLastMixinContainerScreen().rei_getContainerWidth() - widthRemoved, 18);
     }
     
     private Rectangle getCraftableToggleArea() {
@@ -149,13 +155,13 @@ public class ContainerScreenOverlay extends Screen {
         return rectangle;
     }
     
-    public void render(int mouseX, int mouseY, float partialTicks) {
+    public void drawOverlay(int mouseX, int mouseY, float partialTicks) {
         List<ItemStack> currentStacks = ClientHelper.getInventoryItemsTypes();
         if (getLeft() != lastLeft)
             onInitialized();
         else if (RoughlyEnoughItemsCore.getConfigHelper().craftableOnly() && (!hasSameListContent(new LinkedList<>(GuiHelper.inventoryStacks), currentStacks) || (currentStacks.size() != GuiHelper.inventoryStacks.size()))) {
             GuiHelper.inventoryStacks = ClientHelper.getInventoryItemsTypes();
-            itemListOverlay.updateList(page, searchTerm);
+            itemListOverlay.updateList(getItemListArea(), page, searchTerm);
         }
         GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
         GuiLighting.disable();
@@ -185,7 +191,6 @@ public class ContainerScreenOverlay extends Screen {
         QUEUED_TOOLTIPS.add(queuedTooltip);
     }
     
-    @Override
     public void draw(int int_1, int int_2, float float_1) {
         if (!GuiHelper.isOverlayVisible())
             return;
@@ -194,14 +199,11 @@ public class ContainerScreenOverlay extends Screen {
             widget.draw(int_1, int_2, float_1);
         });
         GuiLighting.disable();
-        itemListOverlay.draw(int_1, int_2, float_1);
-        GuiLighting.disable();
-        super.draw(int_1, int_2, float_1);
     }
     
     private Rectangle calculateBoundary() {
         if (!RoughlyEnoughItemsCore.getConfigHelper().isMirrorItemPanel()) {
-            int startX = GuiHelper.getLastMixinContainerScreen().getContainerLeft() + GuiHelper.getLastMixinContainerScreen().getContainerWidth() + 10;
+            int startX = GuiHelper.getLastMixinContainerScreen().rei_getContainerLeft() + GuiHelper.getLastMixinContainerScreen().rei_getContainerWidth() + 10;
             int width = window.getScaledWidth() - startX;
             if (MinecraftClient.getInstance().currentScreen instanceof RecipeViewingWidgetScreen) {
                 RecipeViewingWidgetScreen widget = (RecipeViewingWidgetScreen) MinecraftClient.getInstance().currentScreen;
@@ -210,12 +212,7 @@ public class ContainerScreenOverlay extends Screen {
             }
             return new Rectangle(startX, 0, width, window.getScaledHeight());
         }
-        int width = GuiHelper.getLastMixinContainerScreen().getContainerLeft() - 6;
-        if (MinecraftClient.getInstance().currentScreen instanceof RecipeViewingWidgetScreen) {
-            RecipeViewingWidgetScreen widget = (RecipeViewingWidgetScreen) MinecraftClient.getInstance().currentScreen;
-            width = widget.getBounds().x - 6;
-        }
-        return new Rectangle(4, 0, width, window.getScaledHeight());
+        return new Rectangle(4, 0, getLeft() - 6, window.getScaledHeight());
     }
     
     private int getLeft() {
@@ -223,7 +220,9 @@ public class ContainerScreenOverlay extends Screen {
             RecipeViewingWidgetScreen widget = (RecipeViewingWidgetScreen) MinecraftClient.getInstance().currentScreen;
             return widget.getBounds().x;
         }
-        return GuiHelper.getLastMixinContainerScreen().getContainerLeft();
+        if (MinecraftClient.getInstance().player.getRecipeBook().isGuiOpen())
+            return GuiHelper.getLastMixinContainerScreen().rei_getContainerLeft() - 147 - 30;
+        return GuiHelper.getLastMixinContainerScreen().rei_getContainerLeft();
     }
     
     private int getTotalPage() {
@@ -251,15 +250,15 @@ public class ContainerScreenOverlay extends Screen {
     
     @Override
     public boolean keyPressed(int int_1, int int_2, int int_3) {
+        for(GuiEventListener listener : widgets)
+            if (listener.keyPressed(int_1, int_2, int_3))
+                return true;
         if (ClientHelper.HIDE.matchesKey(int_1, int_2)) {
             GuiHelper.toggleOverlayVisible();
             return true;
         }
         if (!GuiHelper.isOverlayVisible())
             return false;
-        for(GuiEventListener listener : listeners)
-            if (listener.keyPressed(int_1, int_2, int_3))
-                return true;
         Point point = ClientHelper.getMouseLocation();
         ItemStack itemStack = null;
         for(IWidget widget : itemListOverlay.getListeners())
@@ -276,8 +275,8 @@ public class ContainerScreenOverlay extends Screen {
                 }
         }
         if (itemStack == null && MinecraftClient.getInstance().currentScreen instanceof ContainerScreen)
-            if (GuiHelper.getLastMixinContainerScreen().getHoveredSlot() != null)
-                itemStack = GuiHelper.getLastMixinContainerScreen().getHoveredSlot().getStack();
+            if (GuiHelper.getLastMixinContainerScreen().rei_getHoveredSlot() != null)
+                itemStack = GuiHelper.getLastMixinContainerScreen().rei_getHoveredSlot().getStack();
         if (itemStack != null && !itemStack.isEmpty()) {
             if (ClientHelper.RECIPE.matchesKey(int_1, int_2))
                 return ClientHelper.executeRecipeKeyBind(this, itemStack);
@@ -291,12 +290,17 @@ public class ContainerScreenOverlay extends Screen {
     public boolean charTyped(char char_1, int int_1) {
         if (!GuiHelper.isOverlayVisible())
             return false;
-        for(GuiEventListener listener : listeners)
+        for(GuiEventListener listener : getEntries())
             if (listener.charTyped(char_1, int_1))
                 return true;
         return super.charTyped(char_1, int_1);
     }
     
+    @Override
+    protected List<? extends GuiEventListener> getEntries() {
+        return widgets;
+    }
+    
     @Override
     public boolean mouseClicked(double double_1, double double_2, int int_1) {
         if (!GuiHelper.isOverlayVisible())

+ 70 - 0
src/main/java/me/shedaniel/rei/gui/config/ConfigEntry.java

@@ -0,0 +1,70 @@
+package me.shedaniel.rei.gui.config;
+
+import me.shedaniel.rei.client.ClientHelper;
+import me.shedaniel.rei.gui.widget.ButtonWidget;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.audio.PositionedSoundInstance;
+import net.minecraft.client.gui.widget.EntryListWidget;
+import net.minecraft.client.util.Window;
+import net.minecraft.sound.SoundEvents;
+import net.minecraft.text.TextComponent;
+
+import java.awt.*;
+
+public class ConfigEntry extends EntryListWidget.Entry<ConfigEntry> {
+    
+    private TextComponent nameComponent;
+    private ConfigEntryButtonProvider buttonProvider;
+    private ButtonWidget buttonWidget;
+    
+    public ConfigEntry(TextComponent nameComponent, ConfigEntryButtonProvider buttonProvider) {
+        this.nameComponent = nameComponent;
+        this.buttonProvider = buttonProvider;
+        this.buttonWidget = new ButtonWidget(0, 0, 150, 20, "") {
+            @Override
+            public boolean onMouseClick(int button, double mouseX, double mouseY) {
+                if (getBounds().contains(mouseX, mouseY) && enabled)
+                    if (buttonProvider.onPressed(button, mouseX, mouseY)) {
+                        MinecraftClient.getInstance().getSoundLoader().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
+                        return true;
+                    }
+                return false;
+            }
+            
+            @Override
+            public void onPressed(int button, double mouseX, double mouseY) {}
+        };
+    }
+    
+    @Override
+    public void draw(int entryWidth, int height, int i3, int i4, boolean isSelected, float delta) {
+        int x = getX();
+        int y = getY();
+        Window window = MinecraftClient.getInstance().window;
+        Point mouse = ClientHelper.getMouseLocation();
+        MinecraftClient.getInstance().fontRenderer.drawWithShadow(nameComponent.getFormattedText(), x + 5, y + 5, -1);
+        this.buttonWidget.text = buttonProvider.getText();
+        this.buttonWidget.getBounds().setLocation(window.getScaledWidth() - 190, y + 2);
+        buttonProvider.draw(buttonWidget, mouse, delta);
+    }
+    
+    @Override
+    public boolean mouseClicked(double double_1, double double_2, int int_1) {
+        if (buttonWidget.mouseClicked(double_1, double_2, int_1))
+            return true;
+        return false;
+    }
+    
+    interface ConfigEntryButtonProvider {
+        
+        public boolean onPressed(int button, double mouseX, double mouseY);
+        
+        public String getText();
+        
+        default public void draw(ButtonWidget button, Point mouse, float delta) {
+            button.draw(mouse.x, mouse.y, delta);
+        }
+        
+    }
+    
+}

+ 35 - 0
src/main/java/me/shedaniel/rei/gui/config/ConfigEntryListWidget.java

@@ -0,0 +1,35 @@
+package me.shedaniel.rei.gui.config;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.widget.EntryListWidget;
+
+public class ConfigEntryListWidget extends EntryListWidget<ConfigEntry> {
+    
+    public ConfigEntryListWidget(MinecraftClient client, int width, int height, int startY, int endY, int entryHeight) {
+        super(client, width, height, startY, endY, entryHeight);
+        method_1943(false); //toggleShowSelection
+    }
+    
+    public void configClearEntries() {
+        clearEntries();
+    }
+    
+    private ConfigEntry getEntry(int int_1) {
+        return this.getEntries().get(int_1);
+    }
+    
+    public void configAddEntry(ConfigEntry entry) {
+        addEntry(entry);
+    }
+    
+    @Override
+    public int getEntryWidth() {
+        return width - 80;
+    }
+    
+    @Override
+    protected int getScrollbarPosition() {
+        return width - 40;
+    }
+    
+}

+ 207 - 0
src/main/java/me/shedaniel/rei/gui/config/ConfigScreen.java

@@ -0,0 +1,207 @@
+package me.shedaniel.rei.gui.config;
+
+import me.shedaniel.rei.RoughlyEnoughItemsCore;
+import me.shedaniel.rei.client.GuiHelper;
+import me.shedaniel.rei.client.REIItemListOrdering;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.GuiEventListener;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.render.GuiLighting;
+import net.minecraft.client.resource.language.I18n;
+import net.minecraft.text.TranslatableTextComponent;
+
+import java.awt.*;
+import java.io.IOException;
+import java.util.Arrays;
+
+public class ConfigScreen extends Screen {
+    
+    private Screen parent;
+    private ConfigEntryListWidget entryListWidget;
+    
+    public ConfigScreen(Screen parent) {
+        this.parent = parent;
+    }
+    
+    @Override
+    public boolean keyPressed(int int_1, int int_2, int int_3) {
+        if (int_1 == 256 && this.doesEscapeKeyClose()) {
+            MinecraftClient.getInstance().openScreen(parent);
+            GuiHelper.getLastOverlay().onInitialized();
+            return true;
+        } else {
+            return super.keyPressed(int_1, int_2, int_3);
+        }
+    }
+    
+    @Override
+    protected void onInitialized() {
+        listeners.add(entryListWidget = new ConfigEntryListWidget(client, width, height, 32, height - 32, 24));
+        entryListWidget.configClearEntries();
+        entryListWidget.configAddEntry(new ConfigEntry(new TranslatableTextComponent("text.rei.side_searchbox"), new ConfigEntry.ConfigEntryButtonProvider() {
+            @Override
+            public boolean onPressed(int button, double mouseX, double mouseY) {
+                if (button == 0)
+                    RoughlyEnoughItemsCore.getConfigHelper().setSideSearchField(!RoughlyEnoughItemsCore.getConfigHelper().sideSearchField());
+                try {
+                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    return false;
+                }
+                return true;
+            }
+            
+            @Override
+            public String getText() {
+                return getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().sideSearchField());
+            }
+        }));
+        entryListWidget.configAddEntry(new ConfigEntry(new TranslatableTextComponent("text.rei.enable_craftable_only"), new ConfigEntry.ConfigEntryButtonProvider() {
+            @Override
+            public boolean onPressed(int button, double mouseX, double mouseY) {
+                if (button == 0)
+                    RoughlyEnoughItemsCore.getConfigHelper().setShowCraftableOnlyButton(!RoughlyEnoughItemsCore.getConfigHelper().showCraftableOnlyButton());
+                try {
+                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    return false;
+                }
+                return true;
+            }
+            
+            @Override
+            public String getText() {
+                return getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().showCraftableOnlyButton());
+            }
+        }));
+        entryListWidget.configAddEntry(new ConfigEntry(new TranslatableTextComponent("text.rei.list_ordering"), new ConfigEntry.ConfigEntryButtonProvider() {
+            @Override
+            public boolean onPressed(int button, double mouseX, double mouseY) {
+                int index = Arrays.asList(REIItemListOrdering.values()).indexOf(RoughlyEnoughItemsCore.getConfigHelper().getItemListOrdering()) + 1;
+                if (index >= REIItemListOrdering.values().length) {
+                    index = 0;
+                    RoughlyEnoughItemsCore.getConfigHelper().setAscending(!RoughlyEnoughItemsCore.getConfigHelper().isAscending());
+                }
+                RoughlyEnoughItemsCore.getConfigHelper().setItemListOrdering(REIItemListOrdering.values()[index]);
+                try {
+                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    return false;
+                }
+                return true;
+            }
+            
+            @Override
+            public String getText() {
+                return I18n.translate("text.rei.list_ordering_button", I18n.translate(RoughlyEnoughItemsCore.getConfigHelper().getItemListOrdering().getNameTranslationKey()), I18n.translate(RoughlyEnoughItemsCore.getConfigHelper().isAscending() ? "ordering.rei.ascending" : "ordering.rei.descending"));
+            }
+        }));
+        entryListWidget.configAddEntry(new ConfigEntry(new TranslatableTextComponent("text.rei.mirror_rei"), new ConfigEntry.ConfigEntryButtonProvider() {
+            @Override
+            public boolean onPressed(int button, double mouseX, double mouseY) {
+                if (button == 0)
+                    RoughlyEnoughItemsCore.getConfigHelper().setMirrorItemPanel(!RoughlyEnoughItemsCore.getConfigHelper().isMirrorItemPanel());
+                try {
+                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    return false;
+                }
+                return true;
+            }
+            
+            @Override
+            public String getText() {
+                return getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().isMirrorItemPanel());
+            }
+        }));
+        entryListWidget.configAddEntry(new ConfigEntry(new TranslatableTextComponent("text.rei.check_updates"), new ConfigEntry.ConfigEntryButtonProvider() {
+            @Override
+            public boolean onPressed(int button, double mouseX, double mouseY) {
+                if (button == 0)
+                    RoughlyEnoughItemsCore.getConfigHelper().setCheckUpdates(!RoughlyEnoughItemsCore.getConfigHelper().checkUpdates());
+                try {
+                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    return false;
+                }
+                return true;
+            }
+            
+            @Override
+            public String getText() {
+                return getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().checkUpdates());
+            }
+        }));
+        entryListWidget.configAddEntry(new ConfigEntry(new TranslatableTextComponent("text.rei.load_default_plugin"), new ConfigEntry.ConfigEntryButtonProvider() {
+            @Override
+            public boolean onPressed(int button, double mouseX, double mouseY) {
+                if (button == 0)
+                    RoughlyEnoughItemsCore.getConfigHelper().setLoadingDefaultPlugin(!RoughlyEnoughItemsCore.getConfigHelper().isLoadingDefaultPlugin());
+                try {
+                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    return false;
+                }
+                return true;
+            }
+            
+            @Override
+            public String getText() {
+                return getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().isLoadingDefaultPlugin());
+            }
+            
+            @Override
+            public void draw(me.shedaniel.rei.gui.widget.ButtonWidget button, Point mouse, float delta) {
+                button.draw(mouse.x, mouse.y, delta);
+                if (button.getBounds().contains(mouse)) {
+                    GuiLighting.disable();
+                    drawTooltip(Arrays.asList(I18n.translate("text.rei.load_default_plugin.restart_tooltip").split("\n")), mouse.x, mouse.y);
+                    GuiLighting.disable();
+                }
+            }
+        }));
+        addButton(new ButtonWidget(0, width / 2 - 100, height - 26, I18n.translate("gui.done")) {
+            @Override
+            public void onPressed(double double_1, double double_2) {
+                try {
+                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                ConfigScreen.this.client.openScreen(parent);
+                GuiHelper.getLastOverlay().onInitialized();
+            }
+        });
+        super.onInitialized();
+    }
+    
+    private String getTrueFalseText(boolean showCraftableOnlyButton) {
+        return String.format("%s%b", showCraftableOnlyButton ? "§a" : "§c", showCraftableOnlyButton);
+    }
+    
+    @Override
+    public void draw(int int_1, int int_2, float float_1) {
+        this.drawTextureBackground(0);
+        this.entryListWidget.draw(int_1, int_2, float_1);
+        this.drawStringCentered(this.fontRenderer, I18n.translate("text.rei.config"), this.width / 2, 16, 16777215);
+        super.draw(int_1, int_2, float_1);
+    }
+    
+    @Override
+    public boolean isPauseScreen() {
+        return false;
+    }
+    
+    @Override
+    public GuiEventListener getFocused() {
+        return entryListWidget;
+    }
+    
+}

+ 22 - 0
src/main/java/me/shedaniel/rei/gui/credits/CreditsEntry.java

@@ -0,0 +1,22 @@
+package me.shedaniel.rei.gui.credits;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.widget.EntryListWidget;
+import net.minecraft.text.TextComponent;
+
+public class CreditsEntry extends EntryListWidget.Entry<CreditsEntry> {
+    
+    private TextComponent textComponent;
+    
+    public CreditsEntry(TextComponent textComponent) {
+        this.textComponent = textComponent;
+    }
+    
+    @Override
+    public void draw(int entryWidth, int height, int i3, int i4, boolean isSelected, float delta) {
+        int x = getX();
+        int y = getY();
+        MinecraftClient.getInstance().fontRenderer.drawWithShadow(textComponent.getFormattedText(), x + 5, y + 5, -1);
+    }
+    
+}

+ 35 - 0
src/main/java/me/shedaniel/rei/gui/credits/CreditsEntryListWidget.java

@@ -0,0 +1,35 @@
+package me.shedaniel.rei.gui.credits;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.widget.EntryListWidget;
+
+public class CreditsEntryListWidget extends EntryListWidget<CreditsEntry> {
+    
+    public CreditsEntryListWidget(MinecraftClient client, int width, int height, int startY, int endY, int entryHeight) {
+        super(client, width, height, startY, endY, entryHeight);
+        method_1943(false); //toggleShowSelection
+    }
+    
+    public void creditsClearEntries() {
+        clearEntries();
+    }
+    
+    private CreditsEntry getEntry(int int_1) {
+        return this.getEntries().get(int_1);
+    }
+    
+    public void creditsAddEntry(CreditsEntry entry) {
+        addEntry(entry);
+    }
+    
+    @Override
+    public int getEntryWidth() {
+        return width - 80;
+    }
+    
+    @Override
+    protected int getScrollbarPosition() {
+        return width - 40;
+    }
+    
+}

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

@@ -0,0 +1,64 @@
+package me.shedaniel.rei.gui.credits;
+
+import me.shedaniel.rei.client.GuiHelper;
+import net.minecraft.client.gui.ContainerScreen;
+import net.minecraft.client.gui.GuiEventListener;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.resource.language.I18n;
+import net.minecraft.text.StringTextComponent;
+
+public class CreditsScreen extends Screen {
+    
+    private ContainerScreen parent;
+    private CreditsEntryListWidget entryListWidget;
+    
+    public CreditsScreen(ContainerScreen parent) {
+        this.parent = parent;
+    }
+    
+    @Override
+    public boolean keyPressed(int int_1, int int_2, int int_3) {
+        if (int_1 == 256 && this.doesEscapeKeyClose()) {
+            this.client.openScreen(parent);
+            GuiHelper.getLastOverlay().onInitialized();
+            return true;
+        }
+        return super.keyPressed(int_1, int_2, int_3);
+    }
+    
+    @Override
+    protected void onInitialized() {
+        listeners.add(entryListWidget = new CreditsEntryListWidget(client, width, height, 32, height - 32, 12));
+        entryListWidget.creditsClearEntries();
+        for(String line : I18n.translate("text.rei.credit.text").split("\n"))
+            entryListWidget.creditsAddEntry(new CreditsEntry(new StringTextComponent(line)));
+        entryListWidget.creditsAddEntry(new CreditsEntry(new StringTextComponent("")));
+        addButton(new ButtonWidget(0, width / 2 - 100, height - 26, I18n.translate("gui.done")) {
+            @Override
+            public void onPressed(double double_1, double double_2) {
+                CreditsScreen.this.client.openScreen(parent);
+                GuiHelper.getLastOverlay().onInitialized();
+            }
+        });
+    }
+    
+    @Override
+    public void draw(int int_1, int int_2, float float_1) {
+        this.drawTextureBackground(0);
+        this.entryListWidget.draw(int_1, int_2, float_1);
+        this.drawStringCentered(this.fontRenderer, I18n.translate("text.rei.credits"), this.width / 2, 16, 16777215);
+        super.draw(int_1, int_2, float_1);
+    }
+    
+    @Override
+    public boolean isPauseScreen() {
+        return false;
+    }
+    
+    @Override
+    public GuiEventListener getFocused() {
+        return entryListWidget;
+    }
+    
+}

+ 16 - 26
src/main/java/me/shedaniel/rei/gui/widget/ButtonWidget.java

@@ -16,32 +16,22 @@ import java.util.List;
 public abstract class ButtonWidget extends Drawable implements IWidget {
     
     protected static final Identifier WIDGET_TEX = new Identifier("textures/gui/widgets.png");
-    public int x;
-    public int y;
     public String text;
     public boolean enabled;
     public boolean visible;
-    protected int width;
-    protected int height;
     protected boolean hovered;
     private boolean pressed;
     private Rectangle bounds;
     
     public ButtonWidget(Rectangle rectangle, String text) {
-        this(rectangle.x, rectangle.y, rectangle.width, rectangle.height, text);
-    }
-    
-    public ButtonWidget(int x, int y, int width, int height, String text) {
-        this.width = 200;
-        this.height = 20;
+        this.bounds = rectangle;
         this.enabled = true;
         this.visible = true;
-        this.x = x;
-        this.y = y;
-        this.width = width;
-        this.height = height;
         this.text = text;
-        this.bounds = new Rectangle(x, this.y, this.width, this.height);
+    }
+    
+    public ButtonWidget(int x, int y, int width, int height, String text) {
+        this(new Rectangle(x, y, width, height), text);
     }
     
     public Rectangle getBounds() {
@@ -66,8 +56,8 @@ public abstract class ButtonWidget extends Drawable implements IWidget {
     
     @Override
     public void draw(int mouseX, int mouseY, float partialTicks) {
-        
         if (this.visible) {
+            int x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;
             MinecraftClient minecraftClient_1 = MinecraftClient.getInstance();
             FontRenderer fontRenderer_1 = minecraftClient_1.fontRenderer;
             minecraftClient_1.getTextureManager().bindTexture(WIDGET_TEX);
@@ -78,18 +68,18 @@ public abstract class ButtonWidget extends Drawable implements IWidget {
             GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
             GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
             //Four Corners
-            this.drawTexturedRect(this.x, this.y, 0, 46 + textureOffset * 20, 4, 4);
-            this.drawTexturedRect(this.x + this.width - 4, this.y, 196, 46 + textureOffset * 20, 4, 4);
-            this.drawTexturedRect(this.x, this.y + this.height - 4, 0, 62 + textureOffset * 20, 4, 4);
-            this.drawTexturedRect(this.x + this.width - 4, this.y + this.height - 4, 196, 62 + textureOffset * 20, 4, 4);
+            this.drawTexturedRect(x, y, 0, 46 + textureOffset * 20, 4, 4);
+            this.drawTexturedRect(x + width - 4, y, 196, 46 + textureOffset * 20, 4, 4);
+            this.drawTexturedRect(x, y + height - 4, 0, 62 + textureOffset * 20, 4, 4);
+            this.drawTexturedRect(x + width - 4, y + height - 4, 196, 62 + textureOffset * 20, 4, 4);
             
             //Sides
-            this.drawTexturedRect(this.x + 4, this.y, 4, 46 + textureOffset * 20, this.width - 8, 4);
-            this.drawTexturedRect(this.x + 4, this.y + this.height - 4, 4, 62 + textureOffset * 20, this.width - 8, 4);
+            this.drawTexturedRect(x + 4, y, 4, 46 + textureOffset * 20, width - 8, 4);
+            this.drawTexturedRect(x + 4, y + height - 4, 4, 62 + textureOffset * 20, width - 8, 4);
             
-            for(int i = this.y + 4; i < this.y + this.height - 4; i += 4) {
-                this.drawTexturedRect(this.x, i, 0, 50 + textureOffset * 20, this.width / 2, MathHelper.clamp(this.y + this.height - 4 - i, 0, 4));
-                this.drawTexturedRect(this.x + this.width / 2, i, 200 - this.width / 2, 50 + textureOffset * 20, this.width / 2, MathHelper.clamp(this.y + this.height - 4 - i, 0, 4));
+            for(int i = y + 4; i < y + height - 4; i += 4) {
+                this.drawTexturedRect(x, i, 0, 50 + textureOffset * 20, width / 2, MathHelper.clamp(y + height - 4 - i, 0, 4));
+                this.drawTexturedRect(x + width / 2, i, 200 - width / 2, 50 + textureOffset * 20, width / 2, MathHelper.clamp(y + height - 4 - i, 0, 4));
             }
             
             int colour = 14737632;
@@ -99,7 +89,7 @@ public abstract class ButtonWidget extends Drawable implements IWidget {
                 colour = 16777120;
             }
             
-            this.drawStringCentered(fontRenderer_1, this.text, this.x + this.width / 2, this.y + (this.height - 8) / 2, colour);
+            this.drawStringCentered(fontRenderer_1, this.text, x + width / 2, y + (height - 8) / 2, colour);
         }
     }
     

+ 0 - 177
src/main/java/me/shedaniel/rei/gui/widget/ConfigWidget.java

@@ -1,177 +0,0 @@
-package me.shedaniel.rei.gui.widget;
-
-import com.google.common.collect.Lists;
-import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.client.REIItemListOrdering;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.GuiEventListener;
-import net.minecraft.client.gui.Screen;
-import net.minecraft.client.render.GuiLighting;
-import net.minecraft.client.resource.language.I18n;
-import net.minecraft.client.util.Window;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-
-public class ConfigWidget extends Screen {
-    
-    private List<IWidget> widgets;
-    private Screen parent;
-    
-    public ConfigWidget(Screen parent) {
-        this.parent = parent;
-        this.widgets = Lists.newArrayList();
-    }
-    
-    @Override
-    public boolean keyPressed(int int_1, int int_2, int int_3) {
-        if (int_1 == 256 && this.doesEscapeKeyClose()) {
-            MinecraftClient.getInstance().openScreen(parent);
-            return true;
-        } else {
-            return super.keyPressed(int_1, int_2, int_3);
-        }
-    }
-    
-    @Override
-    protected void onInitialized() {
-        super.onInitialized();
-        widgets.clear();
-        Window window = MinecraftClient.getInstance().window;
-        widgets.add(new ButtonWidget(window.getScaledWidth() / 2 - 20, 30, 40, 20, "") {
-            @Override
-            public void onPressed(int button, double mouseX, double mouseY) {
-                if (button == 0)
-                    RoughlyEnoughItemsCore.getConfigHelper().setSideSearchField(!RoughlyEnoughItemsCore.getConfigHelper().sideSearchField());
-                try {
-                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-            
-            @Override
-            public void draw(int mouseX, int mouseY, float partialTicks) {
-                text = getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().sideSearchField());
-                String t = I18n.translate("text.rei.side_searchbox");
-                int width = fontRenderer.getStringWidth(t);
-                fontRenderer.drawWithShadow(t, this.x - width - 10, this.y + (this.height - 8) / 2, -1);
-                super.draw(mouseX, mouseY, partialTicks);
-            }
-        });
-        widgets.add(new ButtonWidget(window.getScaledWidth() / 2 - 20, 60, 40, 20, "") {
-            @Override
-            public void onPressed(int button, double mouseX, double mouseY) {
-                if (button == 0)
-                    RoughlyEnoughItemsCore.getConfigHelper().setShowCraftableOnlyButton(!RoughlyEnoughItemsCore.getConfigHelper().showCraftableOnlyButton());
-                try {
-                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-            
-            @Override
-            public void draw(int mouseX, int mouseY, float partialTicks) {
-                text = getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().showCraftableOnlyButton());
-                String t = I18n.translate("text.rei.enable_craftable_only");
-                int width = fontRenderer.getStringWidth(t);
-                fontRenderer.drawWithShadow(t, this.x - width - 10, this.y + (this.height - 8) / 2, -1);
-                super.draw(mouseX, mouseY, partialTicks);
-            }
-        });
-        widgets.add(new ButtonWidget(window.getScaledWidth() / 2 - 90, 90, 150, 20, "") {
-            @Override
-            public void onPressed(int button, double mouseX, double mouseY) {
-                int index = Arrays.asList(REIItemListOrdering.values()).indexOf(RoughlyEnoughItemsCore.getConfigHelper().getItemListOrdering()) + 1;
-                if (index >= REIItemListOrdering.values().length) {
-                    index = 0;
-                    RoughlyEnoughItemsCore.getConfigHelper().setAscending(!RoughlyEnoughItemsCore.getConfigHelper().isAscending());
-                }
-                RoughlyEnoughItemsCore.getConfigHelper().setItemListOrdering(REIItemListOrdering.values()[index]);
-                try {
-                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-            
-            @Override
-            public void draw(int int_1, int int_2, float float_1) {
-                GuiLighting.disable();
-                this.text = I18n.translate("text.rei.list_ordering_button", I18n.translate(RoughlyEnoughItemsCore.getConfigHelper().getItemListOrdering().getNameTranslationKey()), I18n.translate(RoughlyEnoughItemsCore.getConfigHelper().isAscending() ? "ordering.rei.ascending" : "ordering.rei.descending"));
-                String t = I18n.translate("text.rei.list_ordering") + ": ";
-                drawString(MinecraftClient.getInstance().fontRenderer, t, parent.width / 2 - 95 - MinecraftClient.getInstance().fontRenderer.getStringWidth(t), 90 + 6, -1);
-                super.draw(int_1, int_2, float_1);
-            }
-        });
-        widgets.add(new ButtonWidget(window.getScaledWidth() / 2 - 20, 120, 40, 20, "") {
-            @Override
-            public void onPressed(int button, double mouseX, double mouseY) {
-                if (button == 0)
-                    RoughlyEnoughItemsCore.getConfigHelper().setMirrorItemPanel(!RoughlyEnoughItemsCore.getConfigHelper().isMirrorItemPanel());
-                try {
-                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-            
-            @Override
-            public void draw(int mouseX, int mouseY, float partialTicks) {
-                text = getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().isMirrorItemPanel());
-                String t = I18n.translate("text.rei.mirror_rei");
-                int width = fontRenderer.getStringWidth(t);
-                fontRenderer.drawWithShadow(t, this.x - width - 10, this.y + (this.height - 8) / 2, -1);
-                super.draw(mouseX, mouseY, partialTicks);
-            }
-        });
-        widgets.add(new ButtonWidget(window.getScaledWidth() / 2 - 20, 150, 40, 20, "") {
-            @Override
-            public void onPressed(int button, double mouseX, double mouseY) {
-                if (button == 0)
-                    RoughlyEnoughItemsCore.getConfigHelper().setCheckUpdates(!RoughlyEnoughItemsCore.getConfigHelper().checkUpdates());
-                try {
-                    RoughlyEnoughItemsCore.getConfigHelper().saveConfig();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-            
-            @Override
-            public void draw(int mouseX, int mouseY, float partialTicks) {
-                text = getTrueFalseText(RoughlyEnoughItemsCore.getConfigHelper().checkUpdates());
-                String t = I18n.translate("text.rei.check_updates");
-                int width = fontRenderer.getStringWidth(t);
-                fontRenderer.drawWithShadow(t, this.x - width - 10, this.y + (this.height - 8) / 2, -1);
-                super.draw(mouseX, mouseY, partialTicks);
-            }
-        });
-    }
-    
-    private String getTrueFalseText(boolean showCraftableOnlyButton) {
-        return String.format("%s%b", showCraftableOnlyButton ? "§a" : "§c", showCraftableOnlyButton);
-    }
-    
-    @Override
-    public void draw(int int_1, int int_2, float float_1) {
-        drawBackground(0);
-        super.draw(int_1, int_2, float_1);
-        widgets.forEach(widget -> {
-            GuiLighting.disable();
-            widget.draw(int_1, int_2, float_1);
-        });
-    }
-    
-    @Override
-    public boolean isPauseScreen() {
-        return false;
-    }
-    
-    @Override
-    public List<? extends GuiEventListener> getEntries() {
-        return widgets;
-    }
-    
-}

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

@@ -21,13 +21,12 @@ public abstract class CraftableToggleButtonWidget extends ButtonWidget {
     private ItemRenderer itemRenderer;
     
     public CraftableToggleButtonWidget(Rectangle rectangle) {
-        this(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+        super(rectangle, "");
         this.itemRenderer = MinecraftClient.getInstance().getItemRenderer();
     }
     
     public CraftableToggleButtonWidget(int x, int y, int width, int height) {
-        super(x, y, width, height, "");
-        this.itemRenderer = MinecraftClient.getInstance().getItemRenderer();
+        this(new Rectangle(x, y, width, height));
     }
     
     @Override
@@ -36,13 +35,13 @@ public abstract class CraftableToggleButtonWidget extends ButtonWidget {
         
         GuiLighting.enableForItems();
         this.itemRenderer.zOffset = 0.0F;
-        this.itemRenderer.renderGuiItem(new ItemStack(Blocks.CRAFTING_TABLE), x + 2, y + 2);
+        this.itemRenderer.renderGuiItem(new ItemStack(Blocks.CRAFTING_TABLE), getBounds().x + 2, getBounds().y + 2);
         this.itemRenderer.zOffset = 0.0F;
         GuiLighting.disable();
         MinecraftClient.getInstance().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
         GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
         this.zOffset = 100f;
-        this.drawTexturedRect(x, y, (56 + (RoughlyEnoughItemsCore.getConfigHelper().craftableOnly() ? 0 : 20)), 202, 20, 20);
+        this.drawTexturedRect(getBounds().x, getBounds().y, (56 + (RoughlyEnoughItemsCore.getConfigHelper().craftableOnly() ? 0 : 20)), 202, 20, 20);
         this.zOffset = 0f;
         if (getBounds().contains(mouseX, mouseY))
             drawTooltip();

+ 14 - 21
src/main/java/me/shedaniel/rei/gui/widget/ItemListOverlay.java

@@ -20,7 +20,7 @@ import java.util.stream.Stream;
 
 public class ItemListOverlay extends Drawable implements IWidget {
     
-    private List<IWidget> widgets = new ArrayList<>();
+    private List<IWidget> widgets;
     private int width, height, page;
     private Rectangle rectangle, listArea;
     private List<ItemStack> currentDisplayed;
@@ -44,16 +44,10 @@ public class ItemListOverlay extends Drawable implements IWidget {
             GuiHelper.getLastOverlay().addTooltip(new QueuedTooltip(ClientHelper.getMouseLocation(), Arrays.asList(I18n.translate("text.rei.delete_items"))));
     }
     
-    public void updateList(int page, String searchTerm) {
-        updateList(rectangle, page, searchTerm);
-    }
-    
     public void updateList(Rectangle bounds, int page, String searchTerm) {
         this.rectangle = bounds;
-        if (ClientHelper.getItemList().isEmpty())
-            RoughlyEnoughItemsCore.getClientHelper().clientLoaded();
-        currentDisplayed = processSearchTerm(searchTerm, ClientHelper.getItemList(), GuiHelper.inventoryStacks);
-        this.widgets.clear();
+        this.widgets = Lists.newLinkedList();
+        currentDisplayed = processSearchTerm(searchTerm, RoughlyEnoughItemsCore.getItemRegisterer().getItemList(), GuiHelper.inventoryStacks);
         this.page = page;
         calculateListSize(rectangle);
         double startX = rectangle.getCenterX() - width * 9;
@@ -88,7 +82,7 @@ public class ItemListOverlay extends Drawable implements IWidget {
                     return false;
                 }
             };
-            if (this.rectangle.contains(slotWidget.getBounds()))
+            if (true || this.rectangle.contains(slotWidget.getBounds()))
                 widgets.add(slotWidget);
         }
     }
@@ -182,8 +176,8 @@ public class ItemListOverlay extends Drawable implements IWidget {
     
     private void calculateListSize(Rectangle rect) {
         int xOffset = 0, yOffset = 0;
-        this.width = 0;
-        this.height = 0;
+        width = 0;
+        height = 0;
         while (true) {
             xOffset += 18;
             if (height == 0)
@@ -200,19 +194,18 @@ public class ItemListOverlay extends Drawable implements IWidget {
     
     @Override
     public boolean mouseClicked(double double_1, double double_2, int int_1) {
-        ClientPlayerEntity player = MinecraftClient.getInstance().player;
-        if (rectangle.contains(double_1, double_2))
+        if (rectangle.contains(double_1, double_2)) {
+            ClientPlayerEntity player = MinecraftClient.getInstance().player;
             if (ClientHelper.isCheating() && !player.inventory.getCursorStack().isEmpty() && MinecraftClient.getInstance().isInSingleplayer()) {
                 ClientHelper.sendDeletePacket();
                 return true;
             }
-        if (!player.inventory.getCursorStack().isEmpty() && MinecraftClient.getInstance().isInSingleplayer())
-            return false;
-        if (onMouseClick(int_1, double_1, double_2))
-            return true;
-        for(IWidget widget : getListeners())
-            if (widget.mouseClicked(double_1, double_2, int_1))
-                return true;
+            if (!player.inventory.getCursorStack().isEmpty() && MinecraftClient.getInstance().isInSingleplayer())
+                return false;
+            for(IWidget widget : getListeners())
+                if (widget.mouseClicked(double_1, double_2, int_1))
+                    return true;
+        }
         return false;
     }
     

+ 25 - 10
src/main/java/me/shedaniel/rei/gui/widget/ItemSlotWidget.java

@@ -1,6 +1,7 @@
 package me.shedaniel.rei.gui.widget;
 
 import com.google.common.collect.Lists;
+import com.mojang.blaze3d.platform.GlStateManager;
 import me.shedaniel.rei.client.ClientHelper;
 import me.shedaniel.rei.client.GuiHelper;
 import net.minecraft.client.MinecraftClient;
@@ -23,7 +24,7 @@ public class ItemSlotWidget extends Drawable implements HighlightableWidget {
     
     private static final Identifier RECIPE_GUI = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
     private List<ItemStack> itemList = new LinkedList<>();
-    private boolean drawBackground, showToolTips, clickToMoreRecipes;
+    private boolean drawBackground, showToolTips, clickToMoreRecipes, drawHighlightedBackground;
     private int x, y;
     
     public ItemSlotWidget(int x, int y, ItemStack itemStack, boolean drawBackground, boolean showToolTips) {
@@ -37,6 +38,11 @@ public class ItemSlotWidget extends Drawable implements HighlightableWidget {
         this.x = x;
         this.y = y;
         this.clickToMoreRecipes = false;
+        this.drawHighlightedBackground = true;
+    }
+    
+    public void setDrawHighlightedBackground(boolean drawHighlightedBackground) {
+        this.drawHighlightedBackground = drawHighlightedBackground;
     }
     
     public ItemSlotWidget(int x, int y, List<ItemStack> itemList, boolean drawBackground, boolean showToolTips, boolean clickToMoreRecipes) {
@@ -60,15 +66,24 @@ public class ItemSlotWidget extends Drawable implements HighlightableWidget {
             MinecraftClient.getInstance().getTextureManager().bindTexture(RECIPE_GUI);
             drawTexturedRect(this.x - 1, this.y - 1, 0, 222, 18, 18);
         }
-        if (itemStack.isEmpty())
-            return;
-        GuiLighting.enableForItems();
-        ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
-        itemRenderer.zOffset = 200.0F;
-        itemRenderer.renderGuiItem(itemStack, x, y);
-        itemRenderer.renderGuiItemOverlay(MinecraftClient.getInstance().fontRenderer, itemStack, x, y, getItemCountOverlay(itemStack));
-        itemRenderer.zOffset = 0.0F;
-        if (isHighlighted(mouseX, mouseY) && showToolTips)
+        if (drawHighlightedBackground && isHighlighted(mouseX, mouseY)) {
+            GlStateManager.disableLighting();
+            GlStateManager.disableDepthTest();
+            GlStateManager.colorMask(true, true, true, false);
+            drawGradientRect(x, y, x + 16, y + 16, -2130706433, -2130706433);
+            GlStateManager.colorMask(true, true, true, true);
+            GlStateManager.enableLighting();
+            GlStateManager.enableDepthTest();
+        }
+        if (!itemStack.isEmpty()) {
+            GuiLighting.enableForItems();
+            ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
+            itemRenderer.zOffset = 200.0F;
+            itemRenderer.renderGuiItem(itemStack, x, y);
+            itemRenderer.renderGuiItemOverlay(MinecraftClient.getInstance().fontRenderer, itemStack, x, y, getItemCountOverlay(itemStack));
+            itemRenderer.zOffset = 0.0F;
+        }
+        if (!itemStack.isEmpty() && isHighlighted(mouseX, mouseY) && showToolTips)
             drawToolTip(itemStack);
     }
     

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

@@ -70,6 +70,7 @@ public class RecipeViewingWidgetScreen extends Screen {
     public boolean keyPressed(int int_1, int int_2, int int_3) {
         if ((int_1 == 256 || this.client.options.keyInventory.matchesKey(int_1, int_2)) && this.doesEscapeKeyClose()) {
             MinecraftClient.getInstance().openScreen(GuiHelper.getLastContainerScreen());
+            GuiHelper.getLastOverlay().onInitialized();
             return true;
         }
         for(GuiEventListener listener : listeners)
@@ -230,7 +231,7 @@ public class RecipeViewingWidgetScreen extends Screen {
         GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
         GuiLighting.disable();
         tabs.stream().filter(TabWidget::isSelected).forEach(tabWidget -> tabWidget.draw(mouseX, mouseY, partialTicks));
-        GuiHelper.getLastOverlay().render(mouseX, mouseY, partialTicks);
+        GuiHelper.getLastOverlay().drawOverlay(mouseX, mouseY, partialTicks);
     }
     
     @Override

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

@@ -25,6 +25,7 @@ public class SpeedCraftingButtonWidget extends ButtonWidget {
     @Override
     public void onPressed(int button, double mouseX, double mouseY) {
         MinecraftClient.getInstance().openScreen(GuiHelper.getLastContainerScreen());
+        GuiHelper.getLastOverlay().onInitialized();
         functional.performAutoCraft(GuiHelper.getLastContainerScreen(), displaySupplier.get());
     }
     

+ 6 - 9
src/main/java/me/shedaniel/rei/listeners/IMixinContainerScreen.java

@@ -1,23 +1,20 @@
 package me.shedaniel.rei.listeners;
 
-import me.shedaniel.rei.gui.ContainerScreenOverlay;
 import net.minecraft.container.Slot;
 import net.minecraft.item.ItemStack;
 
 public interface IMixinContainerScreen {
     
-    public int getContainerLeft();
+    public int rei_getContainerLeft();
     
-    public int getContainerTop();
+    public int rei_getContainerTop();
     
-    public int getContainerWidth();
+    public int rei_getContainerWidth();
     
-    public int getContainerHeight();
+    public int rei_getContainerHeight();
     
-    public ItemStack getDraggedStack();
+    public ItemStack rei_getDraggedStack();
     
-    public Slot getHoveredSlot();
-    
-    public void setOverlay(ContainerScreenOverlay overlay);
+    public Slot rei_getHoveredSlot();
     
 }

+ 8 - 15
src/main/java/me/shedaniel/rei/mixin/MixinContainerScreen.java

@@ -37,36 +37,29 @@ public class MixinContainerScreen extends Screen implements IMixinContainerScree
     private ItemStack field_2782;
     
     @Override
-    public int getContainerLeft() {
+    public int rei_getContainerLeft() {
         return left;
     }
     
     @Override
-    public int getContainerTop() {
+    public int rei_getContainerTop() {
         return top;
     }
     
     @Override
-    public int getContainerWidth() {
+    public int rei_getContainerWidth() {
         return containerWidth;
     }
     
     @Override
-    public int getContainerHeight() {
+    public int rei_getContainerHeight() {
         return containerHeight;
     }
     
-    @Override
-    public void setOverlay(ContainerScreenOverlay overlay) {
-        GuiHelper.setOverlay(overlay);
-    }
-    
     @Inject(method = "onInitialized()V", at = @At("RETURN"))
     protected void onInitialized(CallbackInfo info) {
         GuiHelper.setLastContainerScreen((ContainerScreen) (Object) this);
-        GuiHelper.setLastMixinContainerScreen((IMixinContainerScreen) this);
-        GuiHelper.setOverlay(new ContainerScreenOverlay());
-        this.listeners.add(GuiHelper.getLastOverlay());
+        this.listeners.add(GuiHelper.getLastOverlay(true));
     }
     
     @Inject(method = "draw(IIF)V", at = @At("RETURN"))
@@ -76,16 +69,16 @@ public class MixinContainerScreen extends Screen implements IMixinContainerScree
             if (tabGetter.getSelectedTab() != ItemGroup.INVENTORY.getId())
                 return;
         }
-        GuiHelper.getLastOverlay().render(int_1, int_2, float_1);
+        GuiHelper.getLastOverlay().drawOverlay(int_1, int_2, float_1);
     }
     
     @Override
-    public ItemStack getDraggedStack() {
+    public ItemStack rei_getDraggedStack() {
         return this.field_2782;
     }
     
     @Override
-    public Slot getHoveredSlot() {
+    public Slot rei_getHoveredSlot() {
         return focusedSlot;
     }
     

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

@@ -53,7 +53,7 @@ public class DefaultBlastingCategory implements IRecipeCategory<DefaultBlastingD
                 int height = MathHelper.ceil((System.currentTimeMillis() / 250 % 14d) / 1f);
                 drawTexturedRect(startPoint.x + 2, startPoint.y + 21 + (14 - height), 82, 77 + (14 - height), 14, height);
                 int width = MathHelper.ceil((System.currentTimeMillis() / 250 % 24d) / 1f);
-                drawTexturedRect(startPoint.x + 24, startPoint.y + 19, 82, 92, width, 17);
+                drawTexturedRect(startPoint.x + 24, startPoint.y + 18, 82, 91, width, 17);
             }
         }));
         List<List<ItemStack>> input = recipeDisplay.getInput();

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

@@ -52,10 +52,10 @@ public class DefaultCampfireCategory implements IRecipeCategory<DefaultCampfireD
                 int height = MathHelper.ceil((System.currentTimeMillis() / 250 % 14d) / 1f);
                 drawTexturedRect(startPoint.x + 2, startPoint.y + 31 + (14 - height), 82, 77 + (14 - height), 14, height);
                 int width = MathHelper.ceil((System.currentTimeMillis() / 250 % 24d) / 1f);
-                drawTexturedRect(startPoint.x + 24, startPoint.y + 19, 82, 92, width, 17);
+                drawTexturedRect(startPoint.x + 24, startPoint.y + 18, 82, 91, width, 17);
                 String text = I18n.translate("category.rei.campfire.time", MathHelper.floor(recipeDisplaySupplier.get().getCookTime() / 20d));
                 int length = MinecraftClient.getInstance().fontRenderer.getStringWidth(text);
-                MinecraftClient.getInstance().fontRenderer.draw(text, bounds.x + bounds.width - length - 5, startPoint.y + 54 - 8, -1);
+                MinecraftClient.getInstance().fontRenderer.draw(text, bounds.x + bounds.width - length - 5, startPoint.y + 54 - 8, 4210752);
             }
         }));
         widgets.add(new ItemSlotWidget(startPoint.x + 1, startPoint.y + 11, recipeDisplaySupplier.get().getInput().get(0), true, true, true));

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

@@ -2,8 +2,8 @@ package me.shedaniel.rei.plugin;
 
 import com.google.common.collect.Lists;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
-import me.shedaniel.rei.api.IRecipePlugin;
-import me.shedaniel.rei.api.SpeedCraftFunctional;
+import me.shedaniel.rei.api.*;
+import me.shedaniel.rei.client.RecipeHelper;
 import me.shedaniel.rei.listeners.IMixinRecipeBookGui;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.Screen;
@@ -12,6 +12,10 @@ import net.minecraft.client.gui.container.CraftingTableScreen;
 import net.minecraft.client.gui.container.FurnaceScreen;
 import net.minecraft.client.gui.container.SmokerScreen;
 import net.minecraft.client.gui.ingame.PlayerInventoryScreen;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.enchantment.EnchantmentHelper;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
 import net.minecraft.recipe.Recipe;
 import net.minecraft.recipe.StonecuttingRecipe;
 import net.minecraft.recipe.cooking.BlastingRecipe;
@@ -21,8 +25,11 @@ import net.minecraft.recipe.cooking.SmokingRecipe;
 import net.minecraft.recipe.crafting.ShapedRecipe;
 import net.minecraft.recipe.crafting.ShapelessRecipe;
 import net.minecraft.util.Identifier;
+import net.minecraft.util.registry.Registry;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 public class DefaultPlugin implements IRecipePlugin {
     
@@ -41,42 +48,72 @@ public class DefaultPlugin implements IRecipePlugin {
     }
     
     @Override
-    public void registerPluginCategories() {
-        RoughlyEnoughItemsCore.getRecipeHelper().registerCategory(new DefaultCraftingCategory());
-        RoughlyEnoughItemsCore.getRecipeHelper().registerCategory(new DefaultSmeltingCategory());
-        RoughlyEnoughItemsCore.getRecipeHelper().registerCategory(new DefaultSmokingCategory());
-        RoughlyEnoughItemsCore.getRecipeHelper().registerCategory(new DefaultBlastingCategory());
-        RoughlyEnoughItemsCore.getRecipeHelper().registerCategory(new DefaultCampfireCategory());
-        RoughlyEnoughItemsCore.getRecipeHelper().registerCategory(new DefaultStoneCuttingCategory());
-        RoughlyEnoughItemsCore.getRecipeHelper().registerCategory(new DefaultBrewingCategory());
+    public void onFirstLoad(IPluginDisabler pluginDisabler) {
+        if (!RoughlyEnoughItemsCore.getConfigHelper().isLoadingDefaultPlugin()) {
+            pluginDisabler.disablePluginFunction(new Identifier("roughlyenoughitems", "default_plugin"), PluginFunction.REGISTER_ITEMS);
+            pluginDisabler.disablePluginFunction(new Identifier("roughlyenoughitems", "default_plugin"), PluginFunction.REGISTER_CATEGORIES);
+            pluginDisabler.disablePluginFunction(new Identifier("roughlyenoughitems", "default_plugin"), PluginFunction.REGISTER_RECIPE_DISPLAYS);
+            pluginDisabler.disablePluginFunction(new Identifier("roughlyenoughitems", "default_plugin"), PluginFunction.REGISTER_SPEED_CRAFT);
+        }
     }
     
     @Override
-    public void registerRecipes() {
-        for(Recipe recipe : RoughlyEnoughItemsCore.getRecipeHelper().getRecipeManager().values())
+    public void registerItems(IItemRegisterer itemRegisterer) {
+        Registry.ITEM.stream().forEach(item -> {
+            itemRegisterer.registerItemStack(item.getDefaultStack());
+            try {
+                itemRegisterer.registerItemStack(itemRegisterer.getAllStacksFromItem(item));
+            } catch (Exception e) {
+            }
+        });
+        Registry.ENCHANTMENT.forEach(enchantment -> {
+            for(int i = enchantment.getMinimumLevel(); i < enchantment.getMaximumLevel(); i++) {
+                Map<Enchantment, Integer> map = new HashMap<>();
+                map.put(enchantment, i);
+                ItemStack itemStack = new ItemStack(Items.ENCHANTED_BOOK);
+                EnchantmentHelper.set(map, itemStack);
+                itemRegisterer.registerItemStack(Items.ENCHANTED_BOOK, itemStack);
+            }
+        });
+    }
+    
+    @Override
+    public void registerPluginCategories(RecipeHelper recipeHelper) {
+        recipeHelper.registerCategory(new DefaultCraftingCategory());
+        recipeHelper.registerCategory(new DefaultSmeltingCategory());
+        recipeHelper.registerCategory(new DefaultSmokingCategory());
+        recipeHelper.registerCategory(new DefaultBlastingCategory());
+        recipeHelper.registerCategory(new DefaultCampfireCategory());
+        recipeHelper.registerCategory(new DefaultStoneCuttingCategory());
+        recipeHelper.registerCategory(new DefaultBrewingCategory());
+    }
+    
+    @Override
+    public void registerRecipeDisplays(RecipeHelper recipeHelper) {
+        for(Recipe recipe : recipeHelper.getRecipeManager().values())
             if (recipe instanceof ShapelessRecipe)
-                RoughlyEnoughItemsCore.getRecipeHelper().registerRecipe(CRAFTING, new DefaultShapelessDisplay((ShapelessRecipe) recipe));
+                recipeHelper.registerDisplay(CRAFTING, new DefaultShapelessDisplay((ShapelessRecipe) recipe));
             else if (recipe instanceof ShapedRecipe)
-                RoughlyEnoughItemsCore.getRecipeHelper().registerRecipe(CRAFTING, new DefaultShapedDisplay((ShapedRecipe) recipe));
+                recipeHelper.registerDisplay(CRAFTING, new DefaultShapedDisplay((ShapedRecipe) recipe));
             else if (recipe instanceof SmeltingRecipe)
-                RoughlyEnoughItemsCore.getRecipeHelper().registerRecipe(SMELTING, new DefaultSmeltingDisplay((SmeltingRecipe) recipe));
+                recipeHelper.registerDisplay(SMELTING, new DefaultSmeltingDisplay((SmeltingRecipe) recipe));
             else if (recipe instanceof SmokingRecipe)
-                RoughlyEnoughItemsCore.getRecipeHelper().registerRecipe(SMOKING, new DefaultSmokingDisplay((SmokingRecipe) recipe));
+                recipeHelper.registerDisplay(SMOKING, new DefaultSmokingDisplay((SmokingRecipe) recipe));
             else if (recipe instanceof BlastingRecipe)
-                RoughlyEnoughItemsCore.getRecipeHelper().registerRecipe(BLASTING, new DefaultBlastingDisplay((BlastingRecipe) recipe));
+                recipeHelper.registerDisplay(BLASTING, new DefaultBlastingDisplay((BlastingRecipe) recipe));
             else if (recipe instanceof CampfireCookingRecipe)
-                RoughlyEnoughItemsCore.getRecipeHelper().registerRecipe(CAMPFIRE, new DefaultCampfireDisplay((CampfireCookingRecipe) recipe));
+                recipeHelper.registerDisplay(CAMPFIRE, new DefaultCampfireDisplay((CampfireCookingRecipe) recipe));
             else if (recipe instanceof StonecuttingRecipe)
-                RoughlyEnoughItemsCore.getRecipeHelper().registerRecipe(STONE_CUTTING, new DefaultStoneCuttingDisplay((StonecuttingRecipe) recipe));
-        BREWING_DISPLAYS.stream().forEachOrdered(display -> RoughlyEnoughItemsCore.getRecipeHelper().registerRecipe(BREWING, display));
+                recipeHelper.registerDisplay(STONE_CUTTING, new DefaultStoneCuttingDisplay((StonecuttingRecipe) recipe));
+        BREWING_DISPLAYS.stream().forEachOrdered(display -> recipeHelper.registerDisplay(BREWING, display));
     }
     
     @Override
-    public void registerSpeedCraft() {
-        RoughlyEnoughItemsCore.getRecipeHelper().registerSpeedCraftButtonArea(DefaultPlugin.CAMPFIRE, null);
-        RoughlyEnoughItemsCore.getRecipeHelper().registerSpeedCraftButtonArea(DefaultPlugin.STONE_CUTTING, null);
-        RoughlyEnoughItemsCore.getRecipeHelper().registerSpeedCraftButtonArea(DefaultPlugin.BREWING, null);
-        RoughlyEnoughItemsCore.getRecipeHelper().registerSpeedCraftFunctional(DefaultPlugin.CRAFTING, new SpeedCraftFunctional<DefaultCraftingDisplay>() {
+    public void registerSpeedCraft(RecipeHelper recipeHelper) {
+        recipeHelper.registerSpeedCraftButtonArea(DefaultPlugin.CAMPFIRE, null);
+        recipeHelper.registerSpeedCraftButtonArea(DefaultPlugin.STONE_CUTTING, null);
+        recipeHelper.registerSpeedCraftButtonArea(DefaultPlugin.BREWING, null);
+        recipeHelper.registerSpeedCraftFunctional(DefaultPlugin.CRAFTING, new SpeedCraftFunctional<DefaultCraftingDisplay>() {
             @Override
             public Class[] getFunctioningFor() {
                 return new Class[]{PlayerInventoryScreen.class, CraftingTableScreen.class};
@@ -99,7 +136,7 @@ public class DefaultPlugin implements IRecipePlugin {
                 return screen instanceof CraftingTableScreen || (screen instanceof PlayerInventoryScreen && recipe.getHeight() < 3 && recipe.getWidth() < 3);
             }
         });
-        RoughlyEnoughItemsCore.getRecipeHelper().registerSpeedCraftFunctional(DefaultPlugin.SMELTING, new SpeedCraftFunctional<DefaultSmeltingDisplay>() {
+        recipeHelper.registerSpeedCraftFunctional(DefaultPlugin.SMELTING, new SpeedCraftFunctional<DefaultSmeltingDisplay>() {
             @Override
             public Class[] getFunctioningFor() {
                 return new Class[]{FurnaceScreen.class};
@@ -120,7 +157,7 @@ public class DefaultPlugin implements IRecipePlugin {
                 return screen instanceof FurnaceScreen;
             }
         });
-        RoughlyEnoughItemsCore.getRecipeHelper().registerSpeedCraftFunctional(DefaultPlugin.SMOKING, new SpeedCraftFunctional<DefaultSmokingDisplay>() {
+        recipeHelper.registerSpeedCraftFunctional(DefaultPlugin.SMOKING, new SpeedCraftFunctional<DefaultSmokingDisplay>() {
             @Override
             public Class[] getFunctioningFor() {
                 return new Class[]{SmokerScreen.class};
@@ -141,7 +178,7 @@ public class DefaultPlugin implements IRecipePlugin {
                 return screen instanceof SmokerScreen;
             }
         });
-        RoughlyEnoughItemsCore.getRecipeHelper().registerSpeedCraftFunctional(DefaultPlugin.BLASTING, new SpeedCraftFunctional<DefaultBlastingDisplay>() {
+        recipeHelper.registerSpeedCraftFunctional(DefaultPlugin.BLASTING, new SpeedCraftFunctional<DefaultBlastingDisplay>() {
             @Override
             public Class[] getFunctioningFor() {
                 return new Class[]{BlastFurnaceScreen.class};

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

@@ -52,7 +52,7 @@ public class DefaultSmeltingCategory implements IRecipeCategory<DefaultSmeltingD
                 int height = MathHelper.ceil((System.currentTimeMillis() / 250 % 14d) / 1f);
                 drawTexturedRect(startPoint.x + 2, startPoint.y + 21 + (14 - height), 82, 77 + (14 - height), 14, height);
                 int width = MathHelper.ceil((System.currentTimeMillis() / 250 % 24d) / 1f);
-                drawTexturedRect(startPoint.x + 24, startPoint.y + 19, 82, 92, width, 17);
+                drawTexturedRect(startPoint.x + 24, startPoint.y + 18, 82, 91, width, 17);
             }
         }));
         List<List<ItemStack>> input = recipeDisplaySupplier.get().getInput();

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

@@ -52,7 +52,7 @@ public class DefaultSmokingCategory implements IRecipeCategory<DefaultSmokingDis
                 int height = MathHelper.ceil((System.currentTimeMillis() / 250 % 14d) / 1f);
                 drawTexturedRect(startPoint.x + 2, startPoint.y + 21 + (14 - height), 82, 77 + (14 - height), 14, height);
                 int width = MathHelper.ceil((System.currentTimeMillis() / 250 % 24d) / 1f);
-                drawTexturedRect(startPoint.x + 24, startPoint.y + 19, 82, 92, width, 17);
+                drawTexturedRect(startPoint.x + 24, startPoint.y + 18, 82, 91, width, 17);
             }
         }));
         List<List<ItemStack>> input = recipeDisplaySupplier.get().getInput();

+ 43 - 0
src/main/java/me/shedaniel/rei/plugin/PluginManager.java

@@ -0,0 +1,43 @@
+package me.shedaniel.rei.plugin;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import me.shedaniel.rei.api.IPluginDisabler;
+import me.shedaniel.rei.api.PluginFunction;
+import net.minecraft.util.Identifier;
+
+import java.util.List;
+import java.util.Map;
+
+public class PluginManager implements IPluginDisabler {
+    
+    private static Map<Identifier, List<PluginFunction>> pluginDisabledFunctions = Maps.newHashMap();
+    
+    @Override
+    public void disablePluginFunction(Identifier plugin, PluginFunction function) {
+        List<PluginFunction> list = Lists.newArrayList();
+        if (pluginDisabledFunctions.containsKey(plugin))
+            list = pluginDisabledFunctions.get(plugin);
+        if (!list.contains(function))
+            list.add(function);
+        pluginDisabledFunctions.put(plugin, list);
+    }
+    
+    @Override
+    public void enablePluginFunction(Identifier plugin, PluginFunction function) {
+        List<PluginFunction> list = Lists.newArrayList();
+        if (pluginDisabledFunctions.containsKey(plugin))
+            list = pluginDisabledFunctions.get(plugin);
+        if (list.contains(function))
+            list.remove(function);
+        pluginDisabledFunctions.put(plugin, list);
+        if (list.size() == 0)
+            pluginDisabledFunctions.remove(plugin);
+    }
+    
+    @Override
+    public boolean isFunctionEnabled(Identifier plugin, PluginFunction function) {
+        return !pluginDisabledFunctions.containsKey(plugin) || !pluginDisabledFunctions.get(plugin).contains(function);
+    }
+    
+}

+ 3 - 2
src/main/java/me/shedaniel/rei/update/UpdateChecker.java

@@ -16,7 +16,6 @@ import org.apache.commons.io.IOUtils;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.StringBufferInputStream;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
@@ -106,6 +105,7 @@ public class UpdateChecker implements ClientModInitializer {
         return versions;
     }
     
+    @SuppressWarnings("deprecation")
     @Override
     public void onInitializeClient() {
         if (!checkUpdates())
@@ -131,12 +131,13 @@ public class UpdateChecker implements ClientModInitializer {
             latestForGame = new Version("0.0.0");
     }
     
+    @SuppressWarnings("deprecation")
     private InputStream downloadVersionString() {
         try {
             URL versionUrl = new URL(VERSION_STRING);
             return versionUrl.openStream();
         } catch (IOException e) {
-            return new StringBufferInputStream("{}");
+            return new java.io.StringBufferInputStream("{}");
         }
     }
     

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

@@ -11,7 +11,7 @@
   "category.rei.smoking": "Räuchern",
   "category.rei.blasting": "Sprengen",
   "category.rei.campfire": "Lagerfeuer",
-  "category.rei.campfire.time": "§8%d Sekunden",
+  "category.rei.campfire.time": "%d Sekunden",
   "category.rei.stone_cutting": "Stein schneiden",
   "category.rei.brewing": "Brauen",
   "category.rei.brewing.input": "§eOriginal Trank",

+ 42 - 0
src/main/resources/assets/roughlyenoughitems/lang/en_ud.json

@@ -0,0 +1,42 @@
+{
+  "key.rei.category": "sɯǝʇI ɥƃnouƎ ʎlɥƃnoɹ",
+  "key.roughlyenoughitems.recipe_keybind": "ǝdᴉɔǝɹ ʍoɥS",
+  "key.roughlyenoughitems.hide_keybind": "IƎɹ ʍoɥS/ǝpᴉH",
+  "key.roughlyenoughitems.usage_keybind": "sǝs∩ ʍoɥS",
+  "text.rei.cheat": "Cheat",
+  "text.rei.nocheat": "§c§mʇɐǝɥƆ",
+  "category.rei.crafting": "ƃuᴉʇɟɐɹƆ",
+  "category.rei.smelting": "ƃuᴉʇlǝɯS",
+  "category.rei.smelting.fuel": "§elǝnℲ",
+  "category.rei.smoking": "ƃuᴉʞoɯS",
+  "category.rei.blasting": "ƃuᴉʇsɐlq",
+  "category.rei.campfire": "ǝɹᴉɟdɯɐƆ",
+  "category.rei.campfire.time": "spuoɔǝS %d",
+  "category.rei.stone_cutting": "ƃuᴉʇʇnƆ ǝuoʇS",
+  "category.rei.brewing": "ƃuᴉʍǝɹq",
+  "category.rei.brewing.input": "§euoᴉʇoԀ lɐuᴉƃᴉɹO",
+  "category.rei.brewing.reactant": "§eʇuǝᴉpǝɹƃuI",
+  "category.rei.brewing.result": "§euoᴉʇoԀ pǝʇlnsǝɹ",
+  "text.rei.config": "ƃᴉɟuoƆ",
+  "text.rei.side_searchbox": "xoq ɥɔɹɐǝS ǝpᴉS: ",
+  "text.rei.mirror_rei": "sʇǝƃpᴉM IƎɹ ɹoɹɹᴉW: ",
+  "text.rei.cheat_items": "˙{player_name} oʇ {item_count}x [{item_name}] uǝʌᴉפ",
+  "text.rei.failed_cheat_items": "§c˙sɯǝʇᴉ ǝʌᴉƃ oʇ pǝlᴉɐℲ",
+  "text.rei.list_ordering": "ƃuᴉɹǝpɹO ʇsᴉ˥ ɯǝʇI",
+  "text.rei.list_ordering_button": "%s [%s]",
+  "ordering.rei.ascending": "ƃuᴉpuǝɔs∀",
+  "ordering.rei.descending": "ƃuᴉpuǝɔsǝp",
+  "ordering.rei.registry": "ʎɹʇsᴉƃǝɹ",
+  "ordering.rei.name": "ǝɯɐN",
+  "ordering.rei.item_groups": "sdnoɹפ ɯǝʇI",
+  "text.speed_craft.failed_move_items": "§c¡sɯǝʇᴉ ǝʌoɯ ʇ,uɐƆ",
+  "text.speed_craft.move_items": "sɯǝʇI ǝʌoW",
+  "text.rei.enable_craftable_only": "ɹǝʇlᴉℲ ǝlqɐʇɟɐɹƆ ǝlqɐuƎ: ",
+  "text.rei.showing_craftable": "ǝlqɐʇɟɐɹƆ ƃuᴉʍoɥS",
+  "text.rei.showing_all": "ll∀ ƃuᴉʍoɥS",
+  "text.rei.delete_items": "§cɯǝʇI ǝʇǝlǝp",
+  "text.rei.check_updates": "sǝʇɐpd∩ ʞɔǝɥƆ: ",
+  "text.rei.update_outdated": "§6¡pǝʇɐpʇno sᴉ IƎɹ\n§a%s§6: ʇuǝɹɹnƆ §a%s§6: ʇsǝʇɐ˥\n§a%s§6: ʎʇᴉɹoᴉɹԀ ǝʇɐpd∩",
+  "text.rei.update_changelog_line": "%s §6-",
+  "text.rei.credits": "sʇᴉpǝɹƆ"
+}

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

@@ -11,7 +11,7 @@
   "category.rei.smoking": "Smoking",
   "category.rei.blasting": "Blasting",
   "category.rei.campfire": "Campfire",
-  "category.rei.campfire.time": "§8%d Seconds",
+  "category.rei.campfire.time": "%d Seconds",
   "category.rei.stone_cutting": "Stone Cutting",
   "category.rei.brewing": "Brewing",
   "category.rei.brewing.input": "§eOriginal Potion",
@@ -37,5 +37,10 @@
   "text.rei.delete_items": "§cDelete Item",
   "text.rei.check_updates": "Check Updates: ",
   "text.rei.update_outdated": "§6REI is outdated!\n§6Current: §a%s §6Latest: §a%s\n§6Update Priority: §a%s",
-  "text.rei.update_changelog_line": "§6- %s"
+  "text.rei.update_changelog_line": "§6- %s",
+  "text.rei.load_default_plugin": "Load Default Plugin: ",
+  "text.rei.load_default_plugin.restart_tooltip": "You probably never want to disable this.\nRestart Minecraft to apply this setting.",
+  "text.rei.credits": "Credits",
+  "_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  Hebrew - nerdoron\n  LOLCAT - Danielshe\n  Upside Down - Danielshe\n\n§lLicense\n§7Roughly Enough Items is using MIT."
 }

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

@@ -11,7 +11,7 @@
   "category.rei.smoking": "Suitsutamine",
   "category.rei.blasting": "Kõrgsulatamine",
   "category.rei.campfire": "Lõkketuli",
-  "category.rei.campfire.time": "§8%d sekundit",
+  "category.rei.campfire.time": "%d sekundit",
   "category.rei.stone_cutting": "Kivi lõikamine",
   "category.rei.brewing": "Pruulimine",
   "category.rei.brewing.input": "§eEsialgne võlujook",

+ 42 - 0
src/main/resources/assets/roughlyenoughitems/lang/lol_us.json

@@ -0,0 +1,42 @@
+{
+  "key.rei.category": "Roughly Enough Items",
+  "key.roughlyenoughitems.recipe_keybind": "Show Recipe",
+  "key.roughlyenoughitems.hide_keybind": "Hide/Show REI",
+  "key.roughlyenoughitems.usage_keybind": "Show Uses",
+  "text.rei.cheat": "HAX",
+  "text.rei.nocheat": "§c§mHAX",
+  "category.rei.crafting": "Krafting",
+  "category.rei.smelting": "Smlezting",
+  "category.rei.smelting.fuel": "§eFuelz",
+  "category.rei.smoking": "Soking",
+  "category.rei.blasting": "Blazting",
+  "category.rei.campfire": "Camfireh",
+  "category.rei.campfire.time": "%d Secondz",
+  "category.rei.stone_cutting": "Rock Kuting",
+  "category.rei.brewing": "Brwing",
+  "category.rei.brewing.input": "§eOriginal Poshun",
+  "category.rei.brewing.reactant": "§eThng",
+  "category.rei.brewing.result": "§eResuted Poshun",
+  "text.rei.config": "Konfig",
+  "text.rei.side_searchbox": "Sie Saerhc Boz: ",
+  "text.rei.mirror_rei": "Miror REI Widgetz: ",
+  "text.rei.cheat_items": "Giv [{item_name}] x{item_count} 2 {player_name}.",
+  "text.rei.failed_cheat_items": "§cFaild 2 giv itemz.",
+  "text.rei.list_ordering": "Item lis orderin",
+  "text.rei.list_ordering_button": "%s [%s]",
+  "ordering.rei.ascending": "Acendin",
+  "ordering.rei.descending": "Dscendin",
+  "ordering.rei.registry": "Registry",
+  "ordering.rei.name": "Nam",
+  "ordering.rei.item_groups": "Itmz groupz",
+  "text.speed_craft.failed_move_items": "§cKan'z m0v itemz!",
+  "text.speed_craft.move_items": "M0v Itemz",
+  "text.rei.enable_craftable_only": "Enabel craftabel fit3r: ",
+  "text.rei.showing_craftable": "Sowin Craftabel",
+  "text.rei.showing_all": "Sowin all",
+  "text.rei.delete_items": "§cDel Itm",
+  "text.rei.check_updates": "Chck Updatez: ",
+  "text.rei.update_outdated": "§6REI's 0utbat3d!\n§6Kurrant: §a%s §6Ratast: §a%s\n§6Upbate phrioriy: §a%s",
+  "text.rei.update_changelog_line": "§6- %s",
+  "text.rei.credits": "Creditz"
+}

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

@@ -11,7 +11,7 @@
   "category.rei.smoking": "烟熏",
   "category.rei.blasting": "熔炼",
   "category.rei.campfire": "营火",
-  "category.rei.campfire.time": "§8%d 秒",
+  "category.rei.campfire.time": "%d 秒",
   "category.rei.stone_cutting": "切石",
   "category.rei.brewing": "酿造",
   "category.rei.brewing.input": "§e输入药水",

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

@@ -11,7 +11,7 @@
   "category.rei.smoking": "煙燻",
   "category.rei.blasting": "熔煉",
   "category.rei.campfire": "營火",
-  "category.rei.campfire.time": "§8%d 秒",
+  "category.rei.campfire.time": "%d 秒",
   "category.rei.stone_cutting": "切石",
   "category.rei.brewing": "釀造",
   "category.rei.brewing.input": "§e輸入藥水",

+ 6 - 1
version.json

@@ -14,7 +14,7 @@
     },
     {
       "game": "19w06a",
-      "mod": "2.2.0.50"
+      "mod": "2.3.0.51"
     }
   ],
   "changelogs": {
@@ -33,6 +33,11 @@
         "version": "2.2.0.50",
         "text": "Updated to 19w06a",
         "level": "none"
+      },
+      {
+        "version": "2.3.0.51",
+        "text": "Fixed lots of bugs",
+        "level": "normal"
       }
     ]
   }