Преглед на файлове

fix favorites saving

Signed-off-by: shedaniel <daniel@shedaniel.me>
shedaniel преди 5 години
родител
ревизия
e968e926d6

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

@@ -13,10 +13,6 @@ import me.shedaniel.rei.impl.ConfigManagerImpl;
 import me.shedaniel.rei.impl.ConfigObjectImpl;
 import org.jetbrains.annotations.ApiStatus;
 
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
 import java.util.List;
 
 public interface ConfigObject {
@@ -124,28 +120,6 @@ public interface ConfigObject {
     
     List<EntryStack> getFavorites();
     
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.FIELD})
-    @interface AddInFrontKeyCode {}
-    
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.FIELD})
-    @interface DontApplyFieldName {}
-    
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.FIELD})
-    @interface UseEnumSelectorInstead {}
-    
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.FIELD})
-    @interface UseSpecialRecipeTypeScreen {}
-    
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.FIELD})
-    @interface UsePercentage {
-        double min();
-        
-        double max();
-    }
+    List<EntryStack> getFilteredStacks();
     
 }

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

@@ -50,7 +50,7 @@ public interface EntryStack {
     }
     
     static EntryStack create(ItemConvertible item) {
-        return new ItemEntryStack(new ItemStack(item));
+        return create(new ItemStack(item));
     }
     
     @ApiStatus.Internal
@@ -185,6 +185,7 @@ public interface EntryStack {
         public static final Supplier<Boolean> FALSE = () -> false;
         public static final Settings<Supplier<Boolean>> RENDER = new Settings<>(TRUE);
         public static final Settings<Supplier<Boolean>> CHECK_TAGS = new Settings<>(FALSE);
+        public static final Settings<Supplier<Boolean>> CHECK_AMOUNT = new Settings<>(FALSE);
         public static final Settings<Supplier<Boolean>> TOOLTIP_ENABLED = new Settings<>(TRUE);
         public static final Settings<Supplier<Boolean>> TOOLTIP_APPEND_MOD = new Settings<>(TRUE);
         public static final Settings<Supplier<Boolean>> RENDER_COUNTS = new Settings<>(TRUE);

+ 79 - 0
src/main/java/me/shedaniel/rei/gui/config/entry/RecipeScreenTypeEntry.java

@@ -0,0 +1,79 @@
+package me.shedaniel.rei.gui.config.entry;
+
+import com.google.common.collect.ImmutableList;
+import me.shedaniel.clothconfig2.gui.entries.TooltipListEntry;
+import me.shedaniel.rei.gui.PreRecipeViewingScreen;
+import me.shedaniel.rei.gui.config.RecipeScreenType;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.Element;
+import net.minecraft.client.gui.widget.AbstractButtonWidget;
+import net.minecraft.client.gui.widget.AbstractPressableButtonWidget;
+import net.minecraft.client.resource.language.I18n;
+import net.minecraft.client.util.Window;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+public class RecipeScreenTypeEntry extends TooltipListEntry<RecipeScreenType> {
+    private int width;
+    private RecipeScreenType type;
+    private RecipeScreenType defaultValue;
+    private Consumer<RecipeScreenType> save;
+    private AbstractButtonWidget buttonWidget = new AbstractPressableButtonWidget(0, 0, 0, 20, "") {
+        @Override
+        public void onPress() {
+            MinecraftClient.getInstance().openScreen(new PreRecipeViewingScreen(getScreen(), type, false, original -> {
+                MinecraftClient.getInstance().openScreen(getScreen());
+                type = original ? RecipeScreenType.ORIGINAL : RecipeScreenType.VILLAGER;
+                getScreen().setEdited(true, isRequiresRestart());
+            }));
+        }
+        
+        @Override
+        public void render(int mouseX, int mouseY, float delta) {
+            setMessage(I18n.translate("config.roughlyenoughitems.recipeScreenType.config", type.toString()));
+            super.render(mouseX, mouseY, delta);
+        }
+    };
+    private List<Element> children = ImmutableList.of(buttonWidget);
+    
+    public RecipeScreenTypeEntry(int width, String fieldName, RecipeScreenType type, RecipeScreenType defaultValue, Consumer<RecipeScreenType> save) {
+        super(fieldName, null);
+        this.width = width;
+        this.type = type;
+        this.defaultValue = defaultValue;
+        this.save = save;
+    }
+    
+    @Override
+    public RecipeScreenType getValue() {
+        return type;
+    }
+    
+    @Override
+    public Optional<RecipeScreenType> getDefaultValue() {
+        return Optional.ofNullable(defaultValue);
+    }
+    
+    @Override
+    public void save() {
+        save.accept(type);
+    }
+    
+    @Override
+    public List<? extends Element> children() {
+        return children;
+    }
+    
+    @Override
+    public void render(int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
+        super.render(index, y, x, entryWidth, entryHeight, mouseX, mouseY, isSelected, delta);
+        Window window = MinecraftClient.getInstance().getWindow();
+        this.buttonWidget.active = this.isEditable();
+        this.buttonWidget.y = y;
+        this.buttonWidget.x = x + entryWidth / 2 - width / 2;
+        this.buttonWidget.setWidth(width);
+        this.buttonWidget.render(mouseX, mouseY, delta);
+    }
+}

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

@@ -233,7 +233,7 @@ public class EntryWidget extends WidgetWithBounds {
             if (interactableFavorites && ConfigObject.getInstance().isFavoritesEnabled() && containsMouse(PointHelper.fromMouse()) && !getCurrentEntry().isEmpty()) {
                 ModifierKeyCode keyCode = ConfigObject.getInstance().getFavoriteKeyCode();
                 EntryStack entry = getCurrentEntry().copy();
-                entry.setAmount(1000);
+                entry.setAmount(127);
                 if (keyCode.matchesKey(int_1, int_2)) {
                     if (reverseFavoritesAction())
                         ConfigManager.getInstance().getFavorites().remove(entry);

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

@@ -63,7 +63,8 @@ public abstract class AbstractEntryStack extends DrawableHelper implements Entry
             return false;
         EntryStack stack = (EntryStack) obj;
         boolean checkTags = get(Settings.CHECK_TAGS).get() || stack.get(Settings.CHECK_TAGS).get();
-        return equals(stack, !checkTags, true);
+        boolean checkAmount = get(Settings.CHECK_AMOUNT).get() || stack.get(Settings.CHECK_AMOUNT).get();
+        return equals(stack, !checkTags, !checkAmount);
     }
     
     @Override

+ 12 - 78
src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java

@@ -32,8 +32,8 @@ import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeHelper;
 import me.shedaniel.rei.gui.ConfigReloadingScreen;
 import me.shedaniel.rei.gui.ContainerScreenOverlay;
-import me.shedaniel.rei.gui.PreRecipeViewingScreen;
 import me.shedaniel.rei.gui.config.RecipeScreenType;
+import me.shedaniel.rei.gui.config.entry.RecipeScreenTypeEntry;
 import me.shedaniel.rei.gui.credits.CreditsScreen;
 import net.fabricmc.loader.api.FabricLoader;
 import net.minecraft.client.MinecraftClient;
@@ -59,7 +59,6 @@ import static me.sargunvohra.mcmods.autoconfig1u.util.Utils.setUnsafely;
 public class ConfigManagerImpl implements ConfigManager {
     
     private boolean craftableOnly;
-    //    private List<EntryStack> favorites = new ArrayList<>();
     private final Gson gson = new GsonBuilder().create();
     
     public ConfigManagerImpl() {
@@ -82,22 +81,7 @@ public class ConfigManagerImpl implements ConfigManager {
         }).build()));
         GuiRegistry guiRegistry = AutoConfig.getGuiRegistry(ConfigObjectImpl.class);
         //noinspection rawtypes
-        guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> Collections.singletonList(ConfigEntryBuilder.create().startEnumSelector(i13n, (Class) field.getType(), getUnsafely(field, config, null)).setDefaultValue(() -> getUnsafely(field, defaults)).setSaveConsumer(newValue -> setUnsafely(field, config, newValue)).build()), field -> field.getType().isEnum(), ConfigObject.UseEnumSelectorInstead.class);
-        //        guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> {
-        //            @SuppressWarnings("rawtypes") List<AbstractConfigListEntry> entries = new ArrayList<>();
-        //            for (FabricKeyBinding binding : ClientHelper.getInstance().getREIKeyBindings()) {
-        //                entries.add(ConfigEntryBuilder.create().fillKeybindingField(I18n.translate(binding.getId()) + ":", binding).build());
-        //            }
-        //            KeyCodeEntry entry = ConfigEntryBuilder.create().startKeyCodeField(i13n, getUnsafely(field, config, InputUtil.UNKNOWN_KEYCODE)).setDefaultValue(() -> getUnsafely(field, defaults)).setSaveConsumer(newValue -> setUnsafely(field, config, newValue)).build();
-        //            entry.setAllowMouse(false);
-        //            entries.add(entry);
-        //            return entries;
-        //        }, field -> field.getType() == InputUtil.KeyCode.class, ConfigObject.AddInFrontKeyCode.class);
-        //        guiRegistry.registerPredicateProvider((i13n, field, config, defaults, guiProvider) -> {
-        //            KeyCodeEntry entry = ConfigEntryBuilder.create().startKeyCodeField(i13n, getUnsafely(field, config, InputUtil.UNKNOWN_KEYCODE)).setDefaultValue(() -> getUnsafely(field, defaults)).setSaveConsumer(newValue -> setUnsafely(field, config, newValue)).build();
-        //            entry.setAllowMouse(false);
-        //            return Collections.singletonList(entry);
-        //        }, field -> field.getType() == InputUtil.KeyCode.class);
+        guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> Collections.singletonList(ConfigEntryBuilder.create().startEnumSelector(i13n, (Class) field.getType(), getUnsafely(field, config, null)).setDefaultValue(() -> getUnsafely(field, defaults)).setSaveConsumer(newValue -> setUnsafely(field, config, newValue)).build()), field -> field.getType().isEnum(), ConfigObjectImpl.UseEnumSelectorInstead.class);
         guiRegistry.registerPredicateProvider((i13n, field, config, defaults, guiProvider) -> {
             if (field.isAnnotationPresent(ConfigEntry.Gui.Excluded.class))
                 return Collections.emptyList();
@@ -106,67 +90,15 @@ public class ConfigManagerImpl implements ConfigManager {
             return Collections.singletonList(entry);
         }, field -> field.getType() == ModifierKeyCode.class);
         guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> {
-            ConfigObject.UsePercentage bounds = field.getAnnotation(ConfigObject.UsePercentage.class);
+            ConfigObjectImpl.UsePercentage bounds = field.getAnnotation(ConfigObjectImpl.UsePercentage.class);
             return Collections.singletonList(ConfigEntryBuilder.create().startIntSlider(i13n, MathHelper.ceil(Utils.getUnsafely(field, config, 0.0) * 100), MathHelper.ceil(bounds.min() * 100), MathHelper.ceil(bounds.max() * 100)).setDefaultValue(() -> MathHelper.ceil((double) Utils.getUnsafely(field, defaults) * 100)).setSaveConsumer((newValue) -> {
                 Utils.setUnsafely(field, config, newValue / 100d);
             }).setTextGetter(integer -> String.format("Size: %d%%", integer)).build());
-        }, (field) -> field.getType() == Double.TYPE || field.getType() == Double.class, ConfigObject.UsePercentage.class);
+        }, (field) -> field.getType() == Double.TYPE || field.getType() == Double.class, ConfigObjectImpl.UsePercentage.class);
         
-        guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> {
-            int width = 220;
-            //noinspection deprecation
-            return Collections.singletonList(new TooltipListEntry<RecipeScreenType>(i13n, null) {
-                private RecipeScreenType type = getUnsafely(field, config, RecipeScreenType.UNSET);
-                private final AbstractButtonWidget buttonWidget = new AbstractPressableButtonWidget(0, 0, 0, 20, "") {
-                    @Override
-                    public void onPress() {
-                        MinecraftClient.getInstance().openScreen(new PreRecipeViewingScreen(getScreen(), type, false, original -> {
-                            MinecraftClient.getInstance().openScreen(getScreen());
-                            type = original ? RecipeScreenType.ORIGINAL : RecipeScreenType.VILLAGER;
-                            getScreen().setEdited(true, isRequiresRestart());
-                        }));
-                    }
-                    
-                    @Override
-                    public void render(int mouseX, int mouseY, float delta) {
-                        setMessage(I18n.translate("config.roughlyenoughitems.recipeScreenType.config", type.toString()));
-                        super.render(mouseX, mouseY, delta);
-                    }
-                };
-                private final List<Element> children = ImmutableList.of(buttonWidget);
-                
-                @Override
-                public RecipeScreenType getValue() {
-                    return type;
-                }
-                
-                @Override
-                public Optional<RecipeScreenType> getDefaultValue() {
-                    return Optional.ofNullable(getUnsafely(field, defaults));
-                }
-                
-                @Override
-                public void save() {
-                    Utils.setUnsafely(field, config, type);
-                }
-                
-                @Override
-                public List<? extends Element> children() {
-                    return children;
-                }
-                
-                @Override
-                public void render(int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
-                    super.render(index, y, x, entryWidth, entryHeight, mouseX, mouseY, isSelected, delta);
-                    Window window = MinecraftClient.getInstance().getWindow();
-                    this.buttonWidget.active = this.isEditable();
-                    this.buttonWidget.y = y;
-                    this.buttonWidget.x = x + entryWidth / 2 - width / 2;
-                    this.buttonWidget.setWidth(width);
-                    this.buttonWidget.render(mouseX, mouseY, delta);
-                }
-            });
-        }, (field) -> field.getType() == RecipeScreenType.class, ConfigObject.UseSpecialRecipeTypeScreen.class);
+        guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) ->
+                        Collections.singletonList(new RecipeScreenTypeEntry(220, i13n, getUnsafely(field, config, RecipeScreenType.UNSET), getUnsafely(field, defaults), type -> setUnsafely(field, config, type)))
+                , (field) -> field.getType() == RecipeScreenType.class, ConfigObjectImpl.UseSpecialRecipeTypeScreen.class);
         saveConfig();
         RoughlyEnoughItemsCore.LOGGER.info("[REI] Config is loaded.");
     }
@@ -178,8 +110,10 @@ public class ConfigManagerImpl implements ConfigManager {
     
     @Override
     public void saveConfig() {
-        if (getFavorites() != null)
-            getFavorites().removeIf(EntryStack::isEmpty);
+        if (getConfig().getFavorites() != null)
+            getConfig().getFavorites().removeIf(EntryStack::isEmpty);
+        if (getConfig().getFilteredStacks() != null)
+            getConfig().getFilteredStacks().removeIf(EntryStack::isEmpty);
         ((me.sargunvohra.mcmods.autoconfig1u.ConfigManager<ConfigObjectImpl>) AutoConfig.getConfigHolder(ConfigObjectImpl.class)).save();
     }
     
@@ -203,7 +137,7 @@ public class ConfigManagerImpl implements ConfigManager {
         try {
             ConfigScreenProvider<ConfigObjectImpl> provider = (ConfigScreenProvider<ConfigObjectImpl>) AutoConfig.getConfigScreen(ConfigObjectImpl.class, parent);
             provider.setI13nFunction(manager -> "config.roughlyenoughitems");
-            provider.setOptionFunction((baseI13n, field) -> field.isAnnotationPresent(ConfigObject.DontApplyFieldName.class) ? baseI13n : String.format("%s.%s", baseI13n, field.getName()));
+            provider.setOptionFunction((baseI13n, field) -> field.isAnnotationPresent(ConfigObjectImpl.DontApplyFieldName.class) ? baseI13n : String.format("%s.%s", baseI13n, field.getName()));
             provider.setCategoryFunction((baseI13n, categoryName) -> String.format("%s.%s", baseI13n, categoryName));
             provider.setBuildFunction(builder -> {
                 if (FabricLoader.getInstance().isModLoaded("modmenu")) {

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

@@ -20,6 +20,10 @@ import me.shedaniel.rei.gui.config.SearchFieldLocation;
 import net.minecraft.client.util.InputUtil;
 import org.jetbrains.annotations.ApiStatus;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -27,12 +31,36 @@ import java.util.List;
 @Config(name = "roughlyenoughitems/config")
 public class ConfigObjectImpl implements ConfigObject, ConfigData {
     
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    @interface DontApplyFieldName {}
+    
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    @interface UseEnumSelectorInstead {}
+    
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    @interface UseSpecialRecipeTypeScreen {}
+    
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    @interface UseFilteringScreen {}
+    
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    @interface UsePercentage {
+        double min();
+        
+        double max();
+    }
+    
     @ConfigEntry.Category("!general") @ConfigEntry.Gui.TransitiveObject @DontApplyFieldName public General general = new General();
     @ConfigEntry.Category("appearance") @ConfigEntry.Gui.TransitiveObject @DontApplyFieldName private Appearance appearance = new Appearance();
     @ConfigEntry.Category("modules") @ConfigEntry.Gui.TransitiveObject @DontApplyFieldName private Modules modules = new Modules();
     @ConfigEntry.Category("technical") @ConfigEntry.Gui.TransitiveObject @DontApplyFieldName private Technical technical = new Technical();
     @ConfigEntry.Category("performance") @ConfigEntry.Gui.TransitiveObject @DontApplyFieldName private Performance performance = new Performance();
-    //    @ConfigEntry.Category("filtering") @ConfigEntry.Gui.TransitiveObject @DontApplyFieldName private Filtering filtering = new Filtering();
+    @ConfigEntry.Category("filtering") @ConfigEntry.Gui.TransitiveObject @DontApplyFieldName private Filtering filtering = new Filtering();
     
     @Override
     public boolean isOverlayVisible() {
@@ -280,6 +308,11 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
         return general.favorites;
     }
     
+    @Override
+    public List<EntryStack> getFilteredStacks() {
+        return filtering.filteredStacks;
+    }
+    
     public static class General {
         @ConfigEntry.Gui.Excluded public List<EntryStack> favorites = new ArrayList<>();
         @Comment("Declares whether cheating mode is on.") private boolean cheating = false;
@@ -343,6 +376,6 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
     }
     
     public static class Filtering {
-        private List<EntryStack> filteredStacks = new ArrayList<>();
+        @UseFilteringScreen private List<EntryStack> filteredStacks = new ArrayList<>();
     }
 }

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

@@ -7,6 +7,7 @@ package me.shedaniel.rei.impl;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Queues;
+import me.shedaniel.rei.api.ConfigObject;
 import me.shedaniel.rei.api.EntryRegistry;
 import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.RecipeHelper;
@@ -26,8 +27,10 @@ public class EntryRegistryImpl implements EntryRegistry {
     private final CopyOnWriteArrayList<EntryStack> entries = Lists.newCopyOnWriteArrayList();
     private final Queue<Pair<EntryStack, Collection<? extends EntryStack>>> queueRegisterEntryStackAfter = Queues.newConcurrentLinkedQueue();
     private List<EntryStack> reloadList;
+    private boolean doingDistinct = false;
     
     public void distinct() {
+        doingDistinct = true;
         TreeSet<EntryStack> set = new TreeSet<>((i, j) -> i.equalsAll(j) ? 0 : 1);
         set.addAll(reloadList);
         entries.clear();
@@ -40,14 +43,25 @@ public class EntryRegistryImpl implements EntryRegistry {
                 break;
             registerEntriesAfter(pair.getLeft(), pair.getRight());
         }
+        set.clear();
+        set.addAll(entries);
+        set.removeIf(EntryStack::isEmpty);
+        entries.clear();
+        entries.addAll(set);
+        set.clear();
+        for (EntryStack stack : ConfigObject.getInstance().getFilteredStacks()) {
+            entries.remove(stack);
+        }
+        doingDistinct = false;
     }
     
     @Override
     public List<EntryStack> getStacksList() {
-        return RecipeHelper.getInstance().arePluginsLoading() ? reloadList : entries;
+        return RecipeHelper.getInstance().arePluginsLoading() && !doingDistinct ? reloadList : entries;
     }
     
     public void reset() {
+        doingDistinct = false;
         reloadList = Lists.newArrayList();
         queueRegisterEntryStackAfter.clear();
         entries.clear();
@@ -94,8 +108,9 @@ public class EntryRegistryImpl implements EntryRegistry {
     public void queueRegisterEntryAfter(EntryStack afterEntry, Collection<? extends EntryStack> stacks) {
         if (RecipeHelper.getInstance().arePluginsLoading()) {
             queueRegisterEntryStackAfter.add(new Pair<>(afterEntry, stacks));
-        } else
+        } else {
             registerEntriesAfter(afterEntry, stacks);
+        }
     }
     
     @Override

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

@@ -324,9 +324,9 @@ public class RecipeHelperImpl implements RecipeHelper {
         ((DisplayHelperImpl) DisplayHelper.getInstance()).resetCache();
         ScreenHelper.getOptionalOverlay().ifPresent(overlay -> overlay.shouldReInit = true);
         
-        arePluginsLoading = false;
         // Remove duplicate entries
         ((EntryRegistryImpl) EntryRegistry.getInstance()).distinct();
+        arePluginsLoading = false;
         
         // Clear Cache Again!
         ((DisplayHelperImpl) DisplayHelper.getInstance()).resetCache();

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

@@ -40,14 +40,7 @@ public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
     
     public DefaultCookingDisplay(AbstractCookingRecipe recipe) {
         this.recipe = recipe;
-        this.input = recipe.getPreviewInputs().stream().map(i -> {
-            List<EntryStack> entries = new ArrayList<>();
-            for (ItemStack stack : i.getMatchingStacksClient()) {
-                entries.add(EntryStack.create(stack));
-            }
-            return entries;
-        }).collect(Collectors.toList());
-        this.input.add(fuel);
+        this.input = CollectionUtils.map(recipe.getPreviewInputs(), i -> CollectionUtils.map(i.getMatchingStacksClient(), EntryStack::create));
         this.output = Collections.singletonList(EntryStack.create(recipe.getOutput()));
         this.xp = recipe.getExperience();
         this.cookTime = recipe.getCookTime();
@@ -81,6 +74,10 @@ public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
         return cookTime;
     }
     
+    public static List<EntryStack> getFuel() {
+        return fuel;
+    }
+    
     @ApiStatus.Internal
     public Optional<AbstractCookingRecipe> getOptionalRecipe() {
         return Optional.ofNullable(recipe);
@@ -98,7 +95,7 @@ public abstract class DefaultCookingDisplay implements TransferRecipeDisplay {
     
     @Override
     public List<List<EntryStack>> getOrganisedInputEntries(ContainerInfo<Container> containerInfo, Container container) {
-        return CollectionUtils.map(recipe.getPreviewInputs(), i -> CollectionUtils.map(i.getMatchingStacksClient(), EntryStack::create));
+        return input;
     }
     
 }

+ 8 - 2
src/main/java/me/shedaniel/rei/plugin/fuel/DefaultFuelCategory.java

@@ -23,12 +23,16 @@ import net.minecraft.util.Identifier;
 import net.minecraft.util.math.MathHelper;
 import org.jetbrains.annotations.Nullable;
 
+import java.text.DecimalFormat;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.function.Supplier;
 
 public class DefaultFuelCategory implements RecipeCategory<DefaultFuelDisplay> {
+    
+    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##");
+    
     @Override
     public Identifier getIdentifier() {
         return DefaultPlugin.FUEL;
@@ -52,6 +56,7 @@ public class DefaultFuelCategory implements RecipeCategory<DefaultFuelDisplay> {
     @Override
     public List<Widget> setupDisplay(Supplier<DefaultFuelDisplay> recipeDisplaySupplier, Rectangle bounds) {
         Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 17);
+        String burnItems = DECIMAL_FORMAT.format(recipeDisplaySupplier.get().getFuelTime() / 200d);
         List<Widget> widgets = new LinkedList<>(Collections.singletonList(new RecipeBaseWidget(bounds) {
             @Override
             public void render(int mouseX, int mouseY, float delta) {
@@ -60,7 +65,7 @@ public class DefaultFuelCategory implements RecipeCategory<DefaultFuelDisplay> {
                 blit(bounds.x + 5, startPoint.y, 0, 73, 18, 34);
                 int height = MathHelper.ceil(System.currentTimeMillis() / 250d % 14d);
                 blit(bounds.x + 7, startPoint.y + 12 + (3 - height), 82, 77 + (14 - height), 14, height);
-                minecraft.textRenderer.draw(I18n.translate("category.rei.fuel.time", recipeDisplaySupplier.get().getFuelTime()), bounds.x + 26, bounds.getMaxY() - 15, ScreenHelper.isDarkModeEnabled() ? 0xFFBBBBBB : 0xFF404040);
+                minecraft.textRenderer.draw(I18n.translate("category.rei.fuel.time.items", burnItems), bounds.x + 26, bounds.getMaxY() - 15, ScreenHelper.isDarkModeEnabled() ? 0xFFBBBBBB : 0xFF404040);
             }
         }));
         widgets.add(EntryWidget.create(bounds.x + 6, startPoint.y + 18).entries(recipeDisplaySupplier.get().getInputEntries().get(0)));
@@ -70,6 +75,7 @@ public class DefaultFuelCategory implements RecipeCategory<DefaultFuelDisplay> {
     @Override
     public RecipeEntry getSimpleRenderer(DefaultFuelDisplay recipe) {
         EntryWidget widget = EntryWidget.create(0, 0).entries(recipe.getInputEntries().get(0)).noBackground().noHighlight();
+        String burnItems = DECIMAL_FORMAT.format(recipe.getFuelTime() / 200d);
         return new RecipeEntry() {
             @Override
             public int getHeight() {
@@ -89,7 +95,7 @@ public class DefaultFuelCategory implements RecipeCategory<DefaultFuelDisplay> {
                 widget.setZ(getZ() + 50);
                 widget.getBounds().setLocation(bounds.x + 4, bounds.y + 2);
                 widget.render(mouseX, mouseY, delta);
-                MinecraftClient.getInstance().textRenderer.drawWithShadow(I18n.translate("category.rei.fuel.time_short", recipe.getFuelTime()), bounds.x + 25, bounds.y + 8, -1);
+                MinecraftClient.getInstance().textRenderer.drawWithShadow(I18n.translate("category.rei.fuel.time_short.items", burnItems), bounds.x + 25, bounds.y + 8, -1);
             }
         };
     }

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

@@ -12,7 +12,9 @@
   "category.rei.smelting.fuel": "Fuel",
   "category.rei.fuel": "Fuel",
   "category.rei.fuel.time": "Burn Time: %d ticks",
+  "category.rei.fuel.time.items": "Burn Time: %s item(s)",
   "category.rei.fuel.time_short": "%d ticks",
+  "category.rei.fuel.time_short.items": "%s item(s)",
   "category.rei.cooking.xp": "%f XP",
   "category.rei.cooking.time&xp": "%s XP in %s sec",
   "category.rei.smoking": "Smoking",