aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/me
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2020-07-08 22:49:27 +0800
committershedaniel <daniel@shedaniel.me>2020-07-08 22:49:27 +0800
commitddbedf6a7dc89176ab7797e5aaa10d6ea563f9a9 (patch)
tree3ecdb75f9c34c5cba27c15ee84d845aaa654eb2e /src/main/java/me
parent1189bcf3a46777239462da0dc45aa088697fec40 (diff)
downloadRoughlyEnoughItems-ddbedf6a7dc89176ab7797e5aaa10d6ea563f9a9.tar.gz
RoughlyEnoughItems-ddbedf6a7dc89176ab7797e5aaa10d6ea563f9a9.tar.bz2
RoughlyEnoughItems-ddbedf6a7dc89176ab7797e5aaa10d6ea563f9a9.zip
Custom Filtering Rules
Signed-off-by: shedaniel <daniel@shedaniel.me>
Diffstat (limited to 'src/main/java/me')
-rw-r--r--src/main/java/me/shedaniel/rei/api/ConfigObject.java3
-rw-r--r--src/main/java/me/shedaniel/rei/api/EntryRegistry.java3
-rw-r--r--src/main/java/me/shedaniel/rei/gui/config/entry/FilteringAddRuleScreen.java194
-rw-r--r--src/main/java/me/shedaniel/rei/gui/config/entry/FilteringEntry.java16
-rw-r--r--src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRuleOptionsScreen.java239
-rw-r--r--src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRulesScreen.java246
-rw-r--r--src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java24
-rw-r--r--src/main/java/me/shedaniel/rei/gui/config/entry/NoFilteringEntry.java4
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java19
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java11
-rw-r--r--src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java14
-rw-r--r--src/main/java/me/shedaniel/rei/impl/SearchArgument.java11
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/AbstractFilteringRule.java40
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/FilteringContext.java52
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/FilteringContextImpl.java63
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/FilteringContextType.java34
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/FilteringResult.java67
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/FilteringResultImpl.java52
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/FilteringRule.java92
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/rules/ManualFilteringRule.java92
-rw-r--r--src/main/java/me/shedaniel/rei/impl/filtering/rules/SearchFilteringRule.java172
-rw-r--r--src/main/java/me/shedaniel/rei/impl/search/Argument.java2
-rw-r--r--src/main/java/me/shedaniel/rei/impl/search/ArgumentsRegistry.java22
23 files changed, 1445 insertions, 27 deletions
diff --git a/src/main/java/me/shedaniel/rei/api/ConfigObject.java b/src/main/java/me/shedaniel/rei/api/ConfigObject.java
index a581ce649..4f4a3ff3f 100644
--- a/src/main/java/me/shedaniel/rei/api/ConfigObject.java
+++ b/src/main/java/me/shedaniel/rei/api/ConfigObject.java
@@ -26,6 +26,7 @@ package me.shedaniel.rei.api;
import me.shedaniel.clothconfig2.api.ModifierKeyCode;
import me.shedaniel.rei.gui.config.*;
import me.shedaniel.rei.impl.ConfigManagerImpl;
+import me.shedaniel.rei.impl.filtering.FilteringRule;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.jetbrains.annotations.ApiStatus;
@@ -150,6 +151,8 @@ public interface ConfigObject {
List<EntryStack> getFilteredStacks();
+ List<FilteringRule<?>> getFilteringRules();
+
@ApiStatus.Experimental
boolean shouldAsyncSearch();
diff --git a/src/main/java/me/shedaniel/rei/api/EntryRegistry.java b/src/main/java/me/shedaniel/rei/api/EntryRegistry.java
index 80f25cbf6..56c9aac19 100644
--- a/src/main/java/me/shedaniel/rei/api/EntryRegistry.java
+++ b/src/main/java/me/shedaniel/rei/api/EntryRegistry.java
@@ -25,6 +25,8 @@ package me.shedaniel.rei.api;
import me.shedaniel.rei.RoughlyEnoughItemsCore;
import me.shedaniel.rei.utils.CollectionUtils;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import org.jetbrains.annotations.ApiStatus;
@@ -33,6 +35,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+@Environment(EnvType.CLIENT)
public interface EntryRegistry {
/**
diff --git a/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringAddRuleScreen.java b/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringAddRuleScreen.java
new file mode 100644
index 000000000..cfcb02396
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringAddRuleScreen.java
@@ -0,0 +1,194 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 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.gui.config.entry;
+
+import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget;
+import me.shedaniel.rei.impl.filtering.FilteringRule;
+import me.shedaniel.rei.impl.filtering.rules.ManualFilteringRule;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.Element;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.text.LiteralText;
+import net.minecraft.text.StringRenderable;
+import net.minecraft.text.Text;
+import net.minecraft.text.TranslatableText;
+import net.minecraft.util.Identifier;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+public class FilteringAddRuleScreen extends Screen {
+ private final FilteringEntry entry;
+ private RulesList rulesList;
+ Screen parent;
+
+ public FilteringAddRuleScreen(FilteringEntry entry) {
+ super(new TranslatableText("config.roughlyenoughitems.filteringRulesScreen.new"));
+ this.entry = entry;
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ {
+ Text backText = new LiteralText("↩ ").append(new TranslatableText("gui.back"));
+ addButton(new ButtonWidget(4, 4, MinecraftClient.getInstance().textRenderer.getWidth(backText) + 10, 20, backText, button -> {
+ client.openScreen(parent);
+ this.parent = null;
+ }));
+ }
+ rulesList = addChild(new RulesList(client, width, height, 30, height, BACKGROUND_TEXTURE));
+ for (FilteringRule<?> rule : FilteringRule.REGISTRY) {
+ if (!(rule instanceof ManualFilteringRule))
+ rulesList.addItem(new DefaultRuleEntry(parent, entry, rule.createNew(), null));
+ }
+ rulesList.selectItem(rulesList.children().get(0));
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
+ this.rulesList.render(matrices, mouseX, mouseY, delta);
+ super.render(matrices, mouseX, mouseY, delta);
+ this.textRenderer.drawWithShadow(matrices, this.title, this.width / 2.0F - this.textRenderer.getWidth(this.title) / 2.0F, 12.0F, -1);
+ }
+
+ public static class RulesList extends DynamicElementListWidget<RuleEntry> {
+ private boolean inFocus;
+
+ public RulesList(MinecraftClient client, int width, int height, int top, int bottom, Identifier 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 Objects.equals(this.getSelectedItem(), this.children().get(index));
+ }
+
+ @Override
+ protected int addItem(RuleEntry item) {
+ return super.addItem(item);
+ }
+
+ @Override
+ public int getItemWidth() {
+ return width - 40;
+ }
+
+ @Override
+ protected int getScrollbarPosition() {
+ return width - 14;
+ }
+ }
+
+ public static abstract class RuleEntry extends DynamicElementListWidget.ElementEntry<RuleEntry> {
+ private final FilteringRule<?> rule;
+
+ public RuleEntry(FilteringRule<?> rule) {
+ this.rule = rule;
+ }
+
+ public FilteringRule<?> getRule() {
+ return rule;
+ }
+
+ @Override
+ public int getItemHeight() {
+ return 26;
+ }
+
+ @Override
+ public boolean changeFocus(boolean lookForwards) {
+ return false;
+ }
+ }
+
+ public static class DefaultRuleEntry extends RuleEntry {
+ private final ButtonWidget addButton;
+ private final BiFunction<FilteringEntry, Screen, Screen> screenFunction;
+
+ public DefaultRuleEntry(Screen parent, FilteringEntry entry, FilteringRule<?> rule, BiFunction<FilteringEntry, Screen, Screen> screenFunction) {
+ super(rule);
+ this.screenFunction = (screenFunction == null ? rule.createEntryScreen().orElse(null) : screenFunction);
+ addButton = new ButtonWidget(0, 0, 20, 20, Text.method_30163(" + "), button -> {
+ entry.edited = true;
+ MinecraftClient.getInstance().openScreen(this.screenFunction.apply(entry, parent));
+ entry.rules.add(0, rule);
+ });
+ addButton.active = this.screenFunction != null;
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) {
+ MinecraftClient client = MinecraftClient.getInstance();
+ {
+ Text title = getRule().getTitle();
+ int i = client.textRenderer.getWidth(title);
+ if (i > entryWidth - 28) {
+ StringRenderable titleTrimmed = StringRenderable.concat(client.textRenderer.trimToWidth(title, entryWidth - 28 - client.textRenderer.getStringWidth("...")), StringRenderable.plain("..."));
+ client.textRenderer.drawWithShadow(matrices, titleTrimmed, x + 2, y + 1, 16777215);
+ } else {
+ client.textRenderer.drawWithShadow(matrices, title, x + 2, y + 1, 16777215);
+ }
+ }
+ {
+ Text subtitle = getRule().getSubtitle();
+ int i = client.textRenderer.getWidth(subtitle);
+ if (i > entryWidth - 28) {
+ StringRenderable subtitleTrimmed = StringRenderable.concat(client.textRenderer.trimToWidth(subtitle, entryWidth - 28 - client.textRenderer.getStringWidth("...")), StringRenderable.plain("..."));
+ client.textRenderer.drawWithShadow(matrices, subtitleTrimmed, x + 2, y + 12, 8421504);
+ } else {
+ client.textRenderer.drawWithShadow(matrices, subtitle, x + 2, y + 12, 8421504);
+ }
+ }
+ addButton.x = x + entryWidth - 25;
+ addButton.y = y + 1;
+ addButton.render(matrices, mouseX, mouseY, delta);
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return Collections.singletonList(addButton);
+ }
+ }
+}
diff --git a/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringEntry.java b/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringEntry.java
index 4aecdef6f..1109e6b19 100644
--- a/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringEntry.java
+++ b/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringEntry.java
@@ -24,8 +24,10 @@
package me.shedaniel.rei.gui.config.entry;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
import me.shedaniel.rei.api.EntryStack;
+import me.shedaniel.rei.impl.filtering.FilteringRule;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
@@ -44,22 +46,27 @@ import java.util.function.Consumer;
public class FilteringEntry extends AbstractConfigListEntry<List<EntryStack>> {
private int width;
Consumer<List<EntryStack>> saveConsumer;
+ Consumer<List<FilteringRule<?>>> rulesSaveConsumer;
List<EntryStack> defaultValue;
List<EntryStack> configFiltered;
+ List<FilteringRule<?>> rules;
boolean edited = false;
- private final FilteringScreen filteringScreen = new FilteringScreen(this);
+ final FilteringScreen filteringScreen = new FilteringScreen(this);
+ final FilteringRulesScreen filteringRulesScreen = new FilteringRulesScreen(this);
private final AbstractButtonWidget buttonWidget = new ButtonWidget(0, 0, 0, 20, new TranslatableText("config.roughlyenoughitems.filteringScreen"), button -> {
- filteringScreen.parent = MinecraftClient.getInstance().currentScreen;
- MinecraftClient.getInstance().openScreen(filteringScreen);
+ filteringRulesScreen.parent = MinecraftClient.getInstance().currentScreen;
+ MinecraftClient.getInstance().openScreen(filteringRulesScreen);
});
private final List<Element> children = ImmutableList.of(buttonWidget);
- public FilteringEntry(int width, List<EntryStack> configFiltered, List<EntryStack> defaultValue, Consumer<List<EntryStack>> saveConsumer) {
+ public FilteringEntry(int width, List<EntryStack> configFiltered, List<FilteringRule<?>> rules, List<EntryStack> defaultValue, Consumer<List<EntryStack>> saveConsumer, Consumer<List<FilteringRule<?>>> rulesSaveConsumer) {
super(NarratorManager.EMPTY, false);
this.width = width;
this.configFiltered = configFiltered;
+ this.rules = Lists.newArrayList(rules);
this.defaultValue = defaultValue;
this.saveConsumer = saveConsumer;
+ this.rulesSaveConsumer = rulesSaveConsumer;
}
@Override
@@ -75,6 +82,7 @@ public class FilteringEntry extends AbstractConfigListEntry<List<EntryStack>> {
@Override
public void save() {
saveConsumer.accept(getValue());
+ rulesSaveConsumer.accept(rules);
this.edited = false;
}
diff --git a/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRuleOptionsScreen.java b/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRuleOptionsScreen.java
new file mode 100644
index 000000000..21b0e0440
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRuleOptionsScreen.java
@@ -0,0 +1,239 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 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.gui.config.entry;
+
+import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget;
+import me.shedaniel.rei.impl.filtering.FilteringRule;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.Element;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.gui.widget.TextFieldWidget;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.text.StringRenderable;
+import net.minecraft.text.Text;
+import net.minecraft.text.TranslatableText;
+import net.minecraft.util.Identifier;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+public abstract class FilteringRuleOptionsScreen<T extends FilteringRule<?>> extends Screen {
+ private final FilteringEntry entry;
+ private RulesList rulesList;
+ Screen parent;
+ public T rule;
+
+ public FilteringRuleOptionsScreen(FilteringEntry entry, T rule, Screen screen) {
+ super(new TranslatableText("config.roughlyenoughitems.filteringRulesScreen"));
+ this.entry = entry;
+ this.rule = rule;
+ this.parent = screen;
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ if (rulesList != null) save();
+ {
+ Text doneText = new TranslatableText("gui.done");
+ int width = MinecraftClient.getInstance().textRenderer.getWidth(doneText);
+ addButton(new ButtonWidget(this.width - 4 - width - 10, 4, width + 10, 20, doneText, button -> {
+ save();
+ client.openScreen(parent);
+ }));
+ }
+ rulesList = addChild(new RulesList(client, width, height, 30, height, BACKGROUND_TEXTURE));
+ addEntries(ruleEntry -> rulesList.addItem(ruleEntry));
+ }
+
+ public abstract void addEntries(Consumer<RuleEntry> entryConsumer);
+
+ public abstract void save();
+
+ public void addText(Consumer<RuleEntry> entryConsumer, StringRenderable text) {
+ for (StringRenderable s : textRenderer.wrapStringToWidthAsList(text, width - 80)) {
+ entryConsumer.accept(new TextRuleEntry(rule, s));
+ }
+ }
+
+ public void addEmpty(Consumer<RuleEntry> entryConsumer, int height) {
+ entryConsumer.accept(new EmptyRuleEntry(rule, height));
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
+ this.rulesList.render(matrices, mouseX, mouseY, delta);
+ super.render(matrices, mouseX, mouseY, delta);
+ this.textRenderer.drawWithShadow(matrices, this.title, this.width / 2.0F - this.textRenderer.getWidth(this.title) / 2.0F, 12.0F, -1);
+ }
+
+ public static class RulesList extends DynamicElementListWidget<RuleEntry> {
+ public RulesList(MinecraftClient client, int width, int height, int top, int bottom, Identifier backgroundLocation) {
+ super(client, width, height, top, bottom, backgroundLocation);
+ }
+
+ @Override
+ protected int addItem(RuleEntry item) {
+ return super.addItem(item);
+ }
+
+ @Override
+ public int getItemWidth() {
+ return width - 40;
+ }
+
+ @Override
+ protected int getScrollbarPosition() {
+ return width - 14;
+ }
+ }
+
+ public static abstract class RuleEntry extends DynamicElementListWidget.ElementEntry<RuleEntry> {
+ private final FilteringRule<?> rule;
+
+ public RuleEntry(FilteringRule<?> rule) {
+ this.rule = rule;
+ }
+
+ public FilteringRule<?> getRule() {
+ return rule;
+ }
+ }
+
+ public static class TextRuleEntry extends RuleEntry {
+ private final StringRenderable text;
+
+ public TextRuleEntry(FilteringRule<?> rule, StringRenderable text) {
+ super(rule);
+ this.text = text;
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) {
+ MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, text, x + 5, y, -1);
+ }
+
+ @Override
+ public int getItemHeight() {
+ return 12;
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return Collections.emptyList();
+ }
+ }
+
+ public static class EmptyRuleEntry extends RuleEntry {
+ private final int height;
+
+ public EmptyRuleEntry(FilteringRule<?> rule, int height) {
+ super(rule);
+ this.height = height;
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) {
+ }
+
+ @Override
+ public int getItemHeight() {
+ return height;
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return Collections.emptyList();
+ }
+ }
+
+ public static class TextFieldRuleEntry extends RuleEntry {
+ private final TextFieldWidget widget;
+
+ public TextFieldRuleEntry(int width, FilteringRule<?> rule, Consumer<TextFieldWidget> widgetConsumer) {
+ super(rule);
+ this.widget = new TextFieldWidget(MinecraftClient.getInstance().textRenderer, 0, 0, width, 18, Text.method_30163(""));
+ widgetConsumer.accept(widget);
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) {
+ widget.x = x + 2;
+ widget.y = y + 2;
+ widget.render(matrices, mouseX, mouseY, delta);
+ }
+
+ @Override
+ public int getItemHeight() {
+ return 20;
+ }
+
+ public TextFieldWidget getWidget() {
+ return widget;
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return Collections.singletonList(widget);
+ }
+ }
+
+ public static class BooleanRuleEntry extends RuleEntry {
+ private boolean b;
+ private final ButtonWidget widget;
+
+ public BooleanRuleEntry(int width, boolean b, FilteringRule<?> rule, Function<Boolean, Text> textFunction) {
+ super(rule);
+ this.b = b;
+ this.widget = new ButtonWidget(0, 0, 100, 20, textFunction.apply(b), button -> {
+ this.b = !this.b;
+ button.setMessage(textFunction.apply(this.b));
+ });
+ }
+
+ public boolean getBoolean() {
+ return b;
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) {
+ widget.x = x + 2;
+ widget.y = y;
+ widget.render(matrices, mouseX, mouseY, delta);
+ }
+
+ @Override
+ public int getItemHeight() {
+ return 20;
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return Collections.singletonList(widget);
+ }
+ }
+}
diff --git a/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRulesScreen.java b/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRulesScreen.java
new file mode 100644
index 000000000..8e5a3adae
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRulesScreen.java
@@ -0,0 +1,246 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 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.gui.config.entry;
+
+import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget;
+import me.shedaniel.rei.impl.filtering.FilteringRule;
+import me.shedaniel.rei.impl.filtering.rules.ManualFilteringRule;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.Element;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.sound.PositionedSoundInstance;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.sound.SoundEvents;
+import net.minecraft.text.LiteralText;
+import net.minecraft.text.StringRenderable;
+import net.minecraft.text.Text;
+import net.minecraft.text.TranslatableText;
+import net.minecraft.util.Identifier;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+import static me.shedaniel.rei.gui.RecipeViewingScreen.CHEST_GUI_TEXTURE;
+
+public class FilteringRulesScreen extends Screen {
+ private final FilteringEntry entry;
+ private RulesList rulesList;
+ Screen parent;
+
+ public FilteringRulesScreen(FilteringEntry entry) {
+ super(new TranslatableText("config.roughlyenoughitems.filteringRulesScreen"));
+ this.entry = entry;
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ {
+ Text backText = new LiteralText("↩ ").append(new TranslatableText("gui.back"));
+ addButton(new ButtonWidget(4, 4, MinecraftClient.getInstance().textRenderer.getWidth(backText) + 10, 20, backText, button -> {
+ client.openScreen(parent);
+ this.parent = null;
+ }));
+ }
+ {
+ Text addText = new LiteralText(" + ");
+ addButton(new ButtonWidget(width - 4 - 20, 4, 20, 20, addText, button -> {
+ FilteringAddRuleScreen screen = new FilteringAddRuleScreen(entry);
+ screen.parent = this;
+ client.openScreen(screen);
+ }));
+ }
+ rulesList = addChild(new RulesList(client, width, height, 30, height, BACKGROUND_TEXTURE));
+ for (int i = entry.rules.size() - 1; i >= 0; i--) {
+ FilteringRule<?> rule = entry.rules.get(i);
+ if (rule instanceof ManualFilteringRule)
+ rulesList.addItem(new DefaultRuleEntry(rule, entry, (entry, screen) -> {
+ entry.filteringScreen.parent = screen;
+ return entry.filteringScreen;
+ }));
+ else rulesList.addItem(new DefaultRuleEntry(rule, entry, null));
+ }
+ rulesList.selectItem(rulesList.children().get(0));
+ }
+
+ @Override
+ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
+ this.rulesList.render(matrices, mouseX, mouseY, delta);
+ super.render(matrices, mouseX, mouseY, delta);
+ this.textRenderer.drawWithShadow(matrices, this.title, this.width / 2.0F - this.textRenderer.getWidth(this.title) / 2.0F, 12.0F, -1);
+ }
+
+ public static class RulesList extends DynamicElementListWidget<RuleEntry> {
+ private boolean inFocus;
+
+ public RulesList(MinecraftClient client, int width, int height, int top, int bottom, Identifier 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 (t