aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main/java
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2022-11-05 01:15:41 +0800
committershedaniel <daniel@shedaniel.me>2023-05-29 21:19:00 +0800
commit8626c1a09f939913cb397520cf2c69c281cabe20 (patch)
tree97997c9c0102348b9cb9cfc6ed2302518b161a64 /runtime/src/main/java
parentbca8c6dfa773a549e8e110f88dff37689baebf30 (diff)
downloadRoughlyEnoughItems-8626c1a09f939913cb397520cf2c69c281cabe20.tar.gz
RoughlyEnoughItems-8626c1a09f939913cb397520cf2c69c281cabe20.tar.bz2
RoughlyEnoughItems-8626c1a09f939913cb397520cf2c69c281cabe20.zip
Fix #1187
Diffstat (limited to 'runtime/src/main/java')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java54
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java14
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesEntry.java113
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesScreen.java244
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/NoFilteringCategoriesEntry.java103
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java11
7 files changed, 527 insertions, 14 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java
index 41db7c7ed..8858445c7 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java
@@ -59,6 +59,7 @@ import me.shedaniel.rei.api.client.gui.config.DisplayScreenType;
import me.shedaniel.rei.api.client.gui.config.SyntaxHighlightingMode;
import me.shedaniel.rei.api.client.overlay.ScreenOverlay;
import me.shedaniel.rei.api.client.registry.entry.EntryRegistry;
+import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.util.CollectionUtils;
import me.shedaniel.rei.api.common.util.ImmutableTextComponent;
@@ -72,6 +73,7 @@ import me.shedaniel.rei.impl.common.InternalLogger;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.ChatFormatting;
+import net.minecraft.ResourceLocationException;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.events.GuiEventListener;
@@ -132,6 +134,18 @@ public class ConfigManagerImpl implements ConfigManager {
Collections.singletonList(new FilteringEntry(220, value, ((ConfigObjectImpl.Advanced.Filtering) config).filteringRules, defaultValue, saveConsumer, list -> ((ConfigObjectImpl.Advanced.Filtering) config).filteringRules = Lists.newArrayList(list)));
}
, (field) -> field.getType() == List.class, ConfigObjectImpl.UseFilteringScreen.class);
+ guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> {
+ Map<CategoryIdentifier<?>, Boolean> value = Utils.<Map<CategoryIdentifier<?>, Boolean>>getUnsafely(field, config, new HashMap<>());
+ Map<CategoryIdentifier<?>, Boolean> defaultValue = Utils.getUnsafely(field, defaults);
+ Consumer<Map<CategoryIdentifier<?>, Boolean>> saveConsumer = (newValue) -> {
+ setUnsafely(field, config, newValue);
+ };
+ return REIRuntime.getInstance().getPreviousContainerScreen() == null || Minecraft.getInstance().getConnection() == null || Minecraft.getInstance().getConnection().getRecipeManager() == null ?
+ Collections.singletonList(new NoFilteringCategoriesEntry(new TranslatableComponent(i13n), value, defaultValue, saveConsumer))
+ :
+ Collections.singletonList(new FilteringCategoriesEntry(new TranslatableComponent(i13n), value, defaultValue, saveConsumer));
+ }
+ , (field) -> field.getType() == Map.class, ConfigObjectImpl.UseFilteringCategoriesScreen.class);
InternalLogger.getInstance().info("Config loaded");
saveConfig();
}
@@ -279,6 +293,18 @@ public class ConfigManagerImpl implements ConfigManager {
}
});
+ // CategoryIdentifier
+ builder.registerSerializer(CategoryIdentifier.class, (value, marshaller) -> {
+ return marshaller.serialize(value.toString());
+ });
+ builder.registerDeserializer(String.class, CategoryIdentifier.class, (value, marshaller) -> {
+ try {
+ return CategoryIdentifier.of(value);
+ } catch (ResourceLocationException e) {
+ throw new DeserializationException(e);
+ }
+ });
+
return builder.build();
}
@@ -372,12 +398,12 @@ public class ConfigManagerImpl implements ConfigManager {
if (Minecraft.getInstance().getConnection() != null && Minecraft.getInstance().getConnection().getRecipeManager() != null) {
TextListEntry feedbackEntry = ConfigEntryBuilder.create().startTextDescription(
new TranslatableComponent("text.rei.feedback", new TranslatableComponent("text.rei.feedback.link")
- .withStyle(style -> style
- .withColor(TextColor.fromRgb(0xff1fc3ff))
- .withUnderlined(true)
- .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://forms.gle/5tdnK5WN1wng78pV8"))
+ .withStyle(style -> style
+ .withColor(TextColor.fromRgb(0xff1fc3ff))
+ .withUnderlined(true)
+ .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://forms.gle/5tdnK5WN1wng78pV8"))
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ImmutableTextComponent("https://forms.gle/5tdnK5WN1wng78pV8")))
- ))
+ ))
.withStyle(ChatFormatting.GRAY)
).build();
builder.getOrCreateCategory(new TranslatableComponent("config.roughlyenoughitems.advanced")).getEntries().add(0, feedbackEntry);
@@ -396,18 +422,18 @@ public class ConfigManagerImpl implements ConfigManager {
TextListEntry supportText = ConfigEntryBuilder.create().startTextDescription(
new TranslatableComponent("text.rei.support.me.desc",
new TranslatableComponent("text.rei.support.me.patreon")
- .withStyle(style -> style
- .withColor(TextColor.fromRgb(0xff1fc3ff))
- .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://patreon.com/shedaniel"))
+ .withStyle(style -> style
+ .withColor(TextColor.fromRgb(0xff1fc3ff))
+ .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://patreon.com/shedaniel"))
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ImmutableTextComponent("https://patreon.com/shedaniel")))
- ),
+ ),
new TranslatableComponent("text.rei.support.me.bisect")
- .withStyle(style -> style
- .withColor(TextColor.fromRgb(0xff1fc3ff))
- .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.bisecthosting.com/shedaniel"))
+ .withStyle(style -> style
+ .withColor(TextColor.fromRgb(0xff1fc3ff))
+ .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.bisecthosting.com/shedaniel"))
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ImmutableTextComponent("https://www.bisecthosting.com/shedaniel")))
- )
- )
+ )
+ )
.withStyle(ChatFormatting.GRAY)
).build();
supportText.setScreen((AbstractConfigScreen) screen);
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
index b92f89b4a..746e11b54 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
@@ -39,6 +39,7 @@ import me.shedaniel.rei.api.client.gui.config.*;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.util.CollectionUtils;
import me.shedaniel.rei.impl.client.entry.filtering.FilteringRule;
+import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesEntriesManager;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@@ -56,7 +57,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@ApiStatus.Internal
@Config(name = "roughlyenoughitems/config")
@@ -413,6 +416,12 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
return advanced.filtering.filteringRules;
}
+ @ApiStatus.Experimental
+ @Override
+ public Map<CategoryIdentifier<?>, Boolean> getFilteringQuickCraftCategories() {
+ return advanced.filtering.filteringQuickCraftCategories;
+ }
+
@Override
@ApiStatus.Experimental
public boolean shouldAsyncSearch() {
@@ -548,6 +557,10 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
+ @interface UseFilteringCategoriesScreen {}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.FIELD})
@interface UsePercentage {
double min();
@@ -708,6 +721,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
@UseFilteringScreen private List<EntryStackProvider<?>> filteredStacks = new ArrayList<>();
public boolean shouldFilterDisplays = true;
@ConfigEntry.Gui.Excluded public List<FilteringRule<?>> filteringRules = new ArrayList<>();
+ @UseFilteringCategoriesScreen public Map<CategoryIdentifier<?>, Boolean> filteringQuickCraftCategories = new HashMap<>();
}
}
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesEntry.java
new file mode 100644
index 000000000..5e1f41a32
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesEntry.java
@@ -0,0 +1,113 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.impl.client.config.entries;
+
+import com.google.common.collect.ImmutableList;
+import com.mojang.blaze3d.platform.Window;
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
+import me.shedaniel.rei.api.common.category.CategoryIdentifier;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.components.AbstractWidget;
+import net.minecraft.client.gui.components.Button;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.narration.NarratableEntry;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TranslatableComponent;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+@ApiStatus.Internal
+public class FilteringCategoriesEntry extends AbstractConfigListEntry<Map<CategoryIdentifier<?>, Boolean>> {
+ private Consumer<Map<CategoryIdentifier<?>, Boolean>> saveConsumer;
+ private Map<CategoryIdentifier<?>, Boolean> defaultValue;
+ private Map<CategoryIdentifier<?>, Boolean> configFiltered;
+ final FilteringCategoriesScreen filteringScreen = new FilteringCategoriesScreen(this);
+ boolean edited = false;
+ private final AbstractWidget buttonWidget = new Button(0, 0, 150, 20, new TranslatableComponent("config.roughlyenoughitems.filtering.excludedQuickCraftCategories.configure"), button -> {
+ filteringScreen.parent = Minecraft.getInstance().screen;
+ Minecraft.getInstance().setScreen(filteringScreen);
+ });
+ private final List<AbstractWidget> children = ImmutableList.of(buttonWidget);
+
+ public FilteringCategoriesEntry(Component fieldName, Map<CategoryIdentifier<?>, Boolean> configFiltered, Map<CategoryIdentifier<?>, Boolean> defaultValue, Consumer<Map<CategoryIdentifier<?>, Boolean>> saveConsumer) {
+ super(fieldName, false);
+ this.configFiltered = configFiltered;
+ this.defaultValue = defaultValue;
+ this.saveConsumer = saveConsumer;
+ }
+
+ @Override
+ public Map<CategoryIdentifier<?>, Boolean> getValue() {
+ return configFiltered;
+ }
+
+ @Override
+ public Optional<Map<CategoryIdentifier<?>, Boolean>> getDefaultValue() {
+ return Optional.ofNullable(defaultValue);
+ }
+
+ @Override
+ public void save() {
+ saveConsumer.accept(getValue());
+ this.edited = false;
+ }
+
+ @Override
+ public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
+ super.render(matrices, index, y, x, entryWidth, entryHeight, mouseX, mouseY, isSelected, delta);
+ Window window = Minecraft.getInstance().getWindow();
+ this.buttonWidget.y = y;
+
+ Component displayedFieldName = this.getDisplayedFieldName();
+ if (Minecraft.getInstance().font.isBidirectional()) {
+ Minecraft.getInstance().font.drawShadow(matrices, displayedFieldName.getVisualOrderText(), (float) (window.getGuiScaledWidth() - x - Minecraft.getInstance().font.width(displayedFieldName)), (float) (y + 6), 16777215);
+ this.buttonWidget.x = x + 2;
+ } else {
+ Minecraft.getInstance().font.drawShadow(matrices, displayedFieldName.getVisualOrderText(), (float) x, (float) (y + 6), this.getPreferredTextColor());
+ this.buttonWidget.x = x + entryWidth - 150;
+ }
+
+ this.buttonWidget.render(matrices, mouseX, mouseY, delta);
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return children;
+ }
+
+ @Override
+ public List<? extends NarratableEntry> narratables() {
+ return children;
+ }
+
+ @Override
+ public boolean isEdited() {
+ return super.isEdited() || edited;
+ }
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesScreen.java
new file mode 100644
index 000000000..e5e9324ad
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesScreen.java
@@ -0,0 +1,244 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.impl.client.config.entries;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget;
+import me.shedaniel.math.Rectangle;
+import me.shedaniel.rei.api.client.registry.category.CategoryRegistry;
+import net.minecraft.ChatFormatting;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.components.Button;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.narration.NarratableEntry;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.resources.sounds.SimpleSoundInstance;
+import net.minecraft.locale.Language;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.FormattedText;
+import net.minecraft.network.chat.TextComponent;
+import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.sounds.SoundEvents;
+
+import java.util.Collections;
+import java.util.List;
+
+public class FilteringCategoriesScreen extends Screen {
+ private final FilteringCategoriesEntry entry;
+ private ListWidget listWidget;
+ Screen parent;
+
+ public FilteringCategoriesScreen(FilteringCategoriesEntry entry) {
+ super(new TranslatableComponent("config.roughlyenoughitems.filtering.excludedQuickCraftCategories.configure.title"));
+ this.entry = entry;
+ }
+
+ @Override
+ public void init() {
+ super.init();
+ {
+ Component backText = new TextComponent("↩ ").append(new TranslatableComponent("gui.back"));
+ addRenderableWidget(new Button(4, 4, Minecraft.getInstance().font.width(backText) + 10, 20, backText, button -> {
+ minecraft.setScreen(parent);
+ this.parent = null;
+ }));
+ }
+ listWidget = addWidget(new ListWidget(minecraft, width, height, 30, height, BACKGROUND_LOCATION));
+ for (CategoryRegistry.CategoryConfiguration<?> configuration : CategoryRegistry.getInstance()) {
+ listWidget.addItem(new DefaultListEntry(configuration));
+ }
+ }
+
+ @Override
+ public void render(PoseStack matrices, int mouseX, int mouseY, float delta) {
+ this.listWidget.render(matrices, mouseX, mouseY, delta);
+ super.render(matrices, mouseX, mouseY, delta);
+ this.font.drawShadow(matrices, this.title.getVisualOrderText(), this.width / 2.0F - this.font.width(this.title) / 2.0F, 12.0F, -1);
+ }
+
+ private static class ListWidget extends DynamicElementListWidget<ListEntry> {
+ private boolean inFocus;
+
+ public ListWidget(Minecraft client, int width, int height, int top, int bottom, ResourceLocation backgroundLocation) {
+ super(client, width, height, top, bottom, backgroundLocation);
+ }
+
+ @Override
+ public boolean changeFocus(boolean lookForwards) {
+ if (!this.inFocus && this.getItemCount() == 0) {
+ return false;
+ } else {
+ this.inFocus = !this.inFocus;
+ if (this.inFocus && this.getSelectedItem() == null && this.getItemCount() > 0) {
+ this.moveSelection(1);
+ } else if (this.inFocus && this.getSelectedItem() != null) {
+ this.getSelectedItem();
+ }
+
+ return this.inFocus;
+ }
+ }
+
+ @Override
+ protected boolean isSelected(int index) {
+ return false;
+ }
+
+ @Override
+ public ListEntry getSelectedItem() {
+ return null;
+ }
+
+ @Override
+ protected int addItem(ListEntry item) {
+ return super.addItem(item);
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (super.mouseClicked(mouseX, mouseY, button))
+ return true;
+ ListEntry item = getItemAtPosition(mouseX, mouseY);
+ if (item != null) {
+ client.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
+ selectItem(item);
+ this.setFocused(item);
+ this.setDragging(true);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getItemWidth() {
+ return width - 40;
+ }
+
+ @Override
+ protected int getScrollbarPosition() {
+ return width - 14;
+ }
+ }
+
+ private static abstract class ListEntry extends DynamicElementListWidget.ElementEntry<ListEntry> {
+ @Override
+ public int getItemHeight() {
+ return 35;
+ }
+
+ @Override
+ public boolean changeFocus(boolean lookForwards) {
+ return false;
+ }
+ }
+
+ private class DefaultListEntry extends ListEntry {
+ private final Button toggleButton;
+ private final CategoryRegistry.CategoryConfiguration<?> configuration;
+
+ public DefaultListEntry(CategoryRegistry.CategoryConfiguration<?> configuration) {
+ this.configuration = configuration;
+ {
+ Component toggleText = new TranslatableComponent("config.roughlyenoughitems.filtering.excludedQuickCraftCategories.configure.toggle");
+ toggleButton = new Button(0, 0, Minecraft.getInstance().font.width(toggleText) + 10, 20, toggleText, button -> {
+ boolean quickCraftingEnabledByDefault = configuration.isQuickCraftingEnabledByDefault();
+ boolean enabled = entry.getValue().getOrDefault(configuration.getCategoryIdentifier(), quickCraftingEnabledByDefault);
+ if (enabled) {
+ // set to false
+ if (!quickCraftingEnabledByDefault) {
+ entry.getValue().remove(configuration.getCategoryIdentifier());
+ } else {
+ entry.getValue().put(configuration.getCategoryIdentifier(), false);
+ }
+ } else {
+ // set to true
+ if (quickCraftingEnabledByDefault) {
+ entry.getValue().remove(configuration.getCategoryIdentifier());
+ } else {
+ entry.getValue().put(configuration.getCategoryIdentifier(), true);
+ }
+ }
+
+ entry.edited = true;
+ });
+ }
+ }
+
+ @Override
+ public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) {
+ Minecraft client = Minecraft.getInstance();
+ matrices.pushPose();
+ matrices.translate(0, 0, 100);
+ configuration.getCategory().getIcon().render(matrices, new Rectangle(x + 2, y + 5, 16, 16), mouseY, mouseY, delta);
+ matrices.popPose();
+ int xPos = x + 22;
+ {
+ Component title = configuration.getCategory().getTitle();
+ int i = client.font.width(title);
+ if (i > entryWidth - 28) {
+ FormattedText titleTrimmed = FormattedText.composite(client.font.substrByWidth(title, entryWidth - 28 - client.font.width("...")), FormattedText.of("..."));
+ client.font.drawShadow(matrices, Language.getInstance().getVisualOrder(titleTrimmed), x + 2, y + 1, 16777215);
+ } else {
+ client.font.drawShadow(matrices, title.getVisualOrderText(), xPos, y + 1, 16777215);
+ }
+ }
+ {
+ Component subtitle = new TranslatableComponent("config.roughlyenoughitems.filtering.excludedQuickCraftCategories.configure." + entry.getValue().getOrDefault(configuration.getCategoryIdentifier(), configuration.isQuickCraftingEnabledByDefault()))
+ .withStyle(ChatFormatting.GRAY);
+ int i = client.font.width(subtitle);
+ if (i > entryWidth - 28) {
+ FormattedText subtitleTrimmed = FormattedText.composite(client.font.substrByWidth(subtitle, entryWidth - 28 - client.font.width("...")), FormattedText.of("..."));
+ client.font.drawShadow(matrices, Language.getInstance().getVisualOrder(subtitleTrimmed), x + 2, y + 12, 8421504);
+ } else {
+ client.font.drawShadow(matrices, subtitle.getVisualOrderText(), xPos, y + 12, 8421504);
+ }
+ }
+ {
+ Component id = new TextComponent(configuration.getCategoryIdentifier().toString())
+ .withStyle(ChatFormatting.DARK_GRAY);
+ int i = client.font.width(id);
+ if (i > entryWidth - 28) {
+ FormattedText idTrimmed = FormattedText.composite(client.font.substrByWidth(id, entryWidth - 28 - client.font.width("...")), FormattedText.of("..."));
+ client.font.drawShadow(matrices, Language.getInstance().getVisualOrder(idTrimmed), x + 2, y + 22, 8421504);
+ } else {
+ client.font.drawShadow(matrices, id.getVisualOrderText(), xPos, y + 22, 8421504);
+ }
+ }
+ toggleButton.x = x + entryWidth - 6 - toggleButton.getWidth();
+ toggleButton.y = y + 5;
+ toggleButton.render(matrices, mouseX, mouseY, delta);
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return Collections.singletonList(toggleButton);
+ }
+
+ @Override
+ public List<? extends NarratableEntry> narratables() {
+ return Collections.singletonList(toggleButton);
+ }
+ }
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/NoFilteringCategoriesEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/NoFilteringCategoriesEntry.java
new file mode 100644
index 000000000..60ce79802
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/NoFilteringCategoriesEntry.java
@@ -0,0 +1,103 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.impl.client.config.entries;
+
+import com.google.common.collect.ImmutableList;
+import com.mojang.blaze3d.platform.Window;
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
+import me.shedaniel.rei.api.common.category.CategoryIdentifier;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.components.AbstractWidget;
+import net.minecraft.client.gui.components.Button;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.narration.NarratableEntry;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TranslatableComponent;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+@ApiStatus.Internal
+public class NoFilteringCategoriesEntry extends AbstractConfigListEntry<Map<CategoryIdentifier<?>, Boolean>> {
+ private Consumer<Map<CategoryIdentifier<?>, Boolean>> saveConsumer;
+ private Map<CategoryIdentifier<?>, Boolean> defaultValue;
+ private Map<CategoryIdentifier<?>, Boolean> configFiltered;
+ private final AbstractWidget buttonWidget = new Button(0, 0, 150, 20, new TranslatableComponent("config.roughlyenoughitems.filteredEntries.loadWorldFirst"), button -> {});
+ private final List<AbstractWidget> children = ImmutableList.of(buttonWidget);
+
+ public NoFilteringCategoriesEntry(Component fieldName, Map<CategoryIdentifier<?>, Boolean> configFiltered, Map<CategoryIdentifier<?>, Boolean> defaultValue, Consumer<Map<CategoryIdentifier<?>, Boolean>> saveConsumer) {
+ super(fieldName, false);
+ this.configFiltered = configFiltered;
+ this.defaultValue = defaultValue;
+ this.saveConsumer = saveConsumer;
+ }
+
+ @Override
+ public Map<CategoryIdentifier<?>, Boolean> getValue() {
+ return configFiltered;
+ }
+
+ @Override
+ public Optional<Map<CategoryIdentifier<?>, Boolean>> getDefaultValue() {
+ return Optional.ofNullable(defaultValue);
+ }
+
+ @Override
+ public void save() {
+ saveConsumer.accept(getValue());
+ }
+
+ @Override
+ public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
+ super.render(matrices, index, y, x, entryWidth, entryHeight, mouseX, mouseY, isSelected, delta);
+ Window window = Minecraft.getInstance().getWindow();
+ this.buttonWidget.active = false;
+ this.buttonWidget.y = y;
+
+ Component displayedFieldName = this.getDisplayedFieldName();
+ if (Minecraft.getInstance().font.isBidirectional()) {
+ Minecraft.getInstance().font.drawShadow(matrices, displayedFieldName.getVisualOrderText(), (float) (window.getGuiScaledWidth() - x - Minecraft.getInstance().font.width(displayedFieldName)), (float) (y + 6), 16777215);
+ this.buttonWidget.x = x + 2;
+ } else {
+ Minecraft.getInstance().font.drawShadow(matrices, displayedFieldName.getVisualOrderText(), (float) x, (float) (y + 6), this.getPreferredTextColor());
+ this.buttonWidget.x = x + entryWidth - 150;
+ }
+
+ this.buttonWidget.render(matrices, mouseX, mouseY, delta);
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return children;
+ }
+
+ @Override
+ public List<? extends NarratableEntry> narratables() {
+ return children;
+ }
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java
index ce27e5c85..f73e158fa 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java
@@ -319,10 +319,12 @@ public class EntryWidget extends Slot implements DraggableStackProviderWidget {
try {
DisplayRegistry displayRegistry = DisplayRegistry.getInstance();
CategoryRegistry categoryRegistry = CategoryRegistry.getInstance();
+ Map<CategoryIdentifier<?>, Boolean> filteringQuickCraftCategories = ConfigObject.getInstance().getFilteringQuickCraftCategories();
for (Map.Entry<CategoryIdentifier<?>, List<Display>> entry : displayRegistry.getAll().entrySet()) {
Optional<? extends CategoryRegistry.CategoryConfiguration<?>> configuration;
if ((configuration = categoryRegistry.tryGet(entry.getKey())).isEmpty()
|| categoryRegistry.isCategoryInvisible(configuration.get().getCategory())) continue;
+ if (!filteringQuickCraftCategories.getOrDefault(entry.getKey(), configuration.get().isQuickCraftingEnabledByDefault())) continue;
for (Display display : entry.getValue()) {
if ((!ConfigObject.getInstance().shouldFilterDisplays() || displayRegistry.isDisplayVisible(display))
&& ViewsImpl.isRecipesFor(getEntries(), display)) {
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java
index ca5206299..21cc60e81 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImp