diff options
13 files changed, 559 insertions, 5 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java index c994980cd..a932071db 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java @@ -28,6 +28,7 @@ import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.entry.EntryStackProvider; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.gui.config.*; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.resources.ResourceLocation; @@ -35,6 +36,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Map; @Environment(EnvType.CLIENT) public interface ConfigObject { @@ -311,6 +313,9 @@ public interface ConfigObject { boolean shouldFilterDisplays(); @ApiStatus.Experimental + Map<CategoryIdentifier<?>, Boolean> getFilteringQuickCraftCategories(); + + @ApiStatus.Experimental boolean shouldAsyncSearch(); @ApiStatus.Experimental diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/category/CategoryRegistry.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/category/CategoryRegistry.java index f209cf11b..4bdcab8ac 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/registry/category/CategoryRegistry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/category/CategoryRegistry.java @@ -270,6 +270,22 @@ public interface CategoryRegistry extends Reloadable<REIClientPlugin>, Iterable< void setPlusButtonArea(ButtonArea area); /** + * Returns whether the category is available for quick crafting by default. + * + * @return whether the category is available for quick crafting by default + */ + @ApiStatus.Experimental + boolean isQuickCraftingEnabledByDefault(); + + /** + * Sets whether the category is available for quick crafting by default. + * + * @param enabled whether the category is available for quick crafting by default + */ + @ApiStatus.Experimental + void setQuickCraftingEnabledByDefault(boolean enabled); + + /** * Returns the optional plus button area provider * * @return the optional plus button area provider diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java index 01c7f3b0c..1c83c8050 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java @@ -210,6 +210,9 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin registry.addWorkstations(BEACON_PAYMENT, EntryStacks.of(Items.BEACON)); registry.addWorkstations(WAXING, EntryStacks.of(Items.HONEYCOMB)); + registry.configure(INFO, config -> config.setQuickCraftingEnabledByDefault(false)); + registry.configure(TAG, config -> config.setQuickCraftingEnabledByDefault(false)); + Set<Item> axes = Sets.newHashSet(), hoes = Sets.newHashSet(), shovels = Sets.newHashSet(); EntryRegistry.getInstance().getEntryStacks().filter(stack -> stack.getValueType() == ItemStack.class).map(stack -> ((ItemStack) stack.getValue()).getItem()).forEach(item -> { if (item instanceof AxeItem && axes.add(item)) { diff --git a/runtime-engine/categories/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java b/runtime-engine/categories/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java index b330b368c..27746d96c 100644 --- a/runtime-engine/categories/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java +++ b/runtime-engine/categories/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java @@ -146,6 +146,7 @@ public class CategoryRegistryImpl implements CategoryRegistry { private final DisplayCategory<T> category; private final List<EntryIngredient> workstations = Collections.synchronizedList(new ArrayList<>()); private final List<CategoryExtensionProvider<T>> extensionProviders = Collections.synchronizedList(new ArrayList<>()); + private boolean quickCraftingEnabledByDefault = true; private ButtonArea plusButtonArea = ButtonArea.defaultArea(); @@ -164,6 +165,16 @@ public class CategoryRegistryImpl implements CategoryRegistry { } @Override + public boolean isQuickCraftingEnabledByDefault() { + return quickCraftingEnabledByDefault; + } + + @Override + public void setQuickCraftingEnabledByDefault(boolean enabled) { + this.quickCraftingEnabledByDefault = enabled; + } + + @Override public Optional<ButtonArea> getPlusButtonArea() { return Optional.of(bounds -> Objects.requireNonNullElseGet(this.plusButtonArea.get(bounds), () -> ButtonArea.defaultArea().get(bounds))); } diff --git a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java index c0d46569b..ed0e2eb2c 100644 --- a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java +++ b/runtime-engine/configs/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; @@ -70,6 +71,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; diff --git a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java index 178b53845..8d6f6a417 100644 --- a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java +++ b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java @@ -36,6 +36,7 @@ import me.shedaniel.rei.api.client.config.entry.EntryStackProvider; import me.shedaniel.rei.api.client.entry.filtering.FilteringRule; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.gui.config.*; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.impl.client.ClientInternals; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -52,7 +53,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @SuppressWarnings("FieldMayBeFinal") @ApiStatus.Internal @@ -368,6 +371,12 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { return advanced.filtering.shouldFilterDisplays; } + @ApiStatus.Experimental + @Override + public Map<CategoryIdentifier<?>, Boolean> getFilteringQuickCraftCategories() { + return advanced.filtering.filteringQuickCraftCategories; + } + @Override @ApiStatus.Experimental public boolean shouldAsyncSearch() { @@ -495,6 +504,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(); @@ -656,6 +669,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-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesEntry.java b/runtime-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesEntry.java new file mode 100644 index 000000000..df6048437 --- /dev/null +++ b/runtime-engine/filtering-entries/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.filteringQuickCraftCategories.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-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesScreen.java b/runtime-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringCategoriesScreen.java new file mode 100644 index 000000000..e4968c168 --- /dev/null +++ b/runtime-engine/filtering-entries/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.filteringQuickCraftCategories.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.filteringQuickCraftCategories.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.filteringQuickCraftCategories.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-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringConfigEntries.java b/runtime-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringConfigEntries.java index b51d8a5fb..0739d1894 100644 --- a/runtime-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringConfigEntries.java +++ b/runtime-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringConfigEntries.java @@ -28,22 +28,24 @@ import me.shedaniel.autoconfig.gui.registry.GuiRegistry; import me.shedaniel.autoconfig.util.Utils; import me.shedaniel.cloth.clothconfig.shadowed.blue.endless.jankson.Jankson; import me.shedaniel.cloth.clothconfig.shadowed.blue.endless.jankson.JsonNull; +import me.shedaniel.cloth.clothconfig.shadowed.blue.endless.jankson.api.DeserializationException; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.entry.EntryStackProvider; import me.shedaniel.rei.api.client.entry.filtering.FilteringRule; import me.shedaniel.rei.api.client.entry.filtering.FilteringRuleType; +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.impl.client.config.ConfigManagerInternal; +import net.minecraft.ResourceLocationException; import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.nbt.TagParser; +import net.minecraft.network.chat.TranslatableComponent; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.function.Consumer; import static me.shedaniel.autoconfig.util.Utils.setUnsafely; @@ -68,6 +70,18 @@ public class FilteringConfigEntries implements ConfigManagerInternal.SystemSetup } } , (field) -> field.getType() == List.class && field.getName().equals("filteredStacks")); + registry.registerPredicateProvider((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 && field.getName().equals("filteringQuickCraftCategories")); } @Override @@ -97,5 +111,17 @@ public class FilteringConfigEntries implements ConfigManagerInternal.SystemSetup return null; } }); + + // 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); + } + }); } } diff --git a/runtime-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/NoFilteringCategoriesEntry.java b/runtime-engine/filtering-entries/src/main/java/me/shedaniel/rei/impl/client/config/entries/NoFilteringCategoriesEntry.java new file mode 100644 index 000000000..60ce79802 --- /dev/null +++ b/runtime-engine/filtering-entries/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; + |
