diff options
| author | shedaniel <daniel@shedaniel.me> | 2023-01-22 00:08:47 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2023-01-22 00:14:02 +0800 |
| commit | 7dac5856acd5a1b4111f009d3c348a501f1bc397 (patch) | |
| tree | 9bd05e823a6d6db0605ff81264be339d0deddd62 /runtime/src/main/java/me/shedaniel | |
| parent | 3426ed6edef377ad690c44be3997a9be73df1638 (diff) | |
| download | RoughlyEnoughItems-7dac5856acd5a1b4111f009d3c348a501f1bc397.tar.gz RoughlyEnoughItems-7dac5856acd5a1b4111f009d3c348a501f1bc397.tar.bz2 RoughlyEnoughItems-7dac5856acd5a1b4111f009d3c348a501f1bc397.zip | |
Add support for c:hidden_from_recipe_viewers
Diffstat (limited to 'runtime/src/main/java/me/shedaniel')
4 files changed, 188 insertions, 2 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java index 73643b59d..f1b1110e8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java @@ -129,6 +129,7 @@ import java.util.stream.Stream; @Environment(EnvType.CLIENT) public class RoughlyEnoughItemsCoreClient { public static final Event<ClientRecipeUpdateEvent> PRE_UPDATE_RECIPES = EventFactory.createLoop(); + public static final Event<Runnable> POST_UPDATE_TAGS = EventFactory.createLoop(); public static boolean isLeftMousePressed = false; private static final ExecutorService RELOAD_PLUGINS = Executors.newSingleThreadScheduledExecutor(task -> { Thread thread = new Thread(task, "REI-ReloadPlugins"); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java index a0ed5189d..6d899d5a5 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java @@ -272,7 +272,7 @@ public class FilteringRulesScreen extends Screen { Function<Boolean, Component> function = bool -> { return Component.translatable("rule.roughlyenoughitems.filtering.search.show." + bool); }; - Map<FilteringContextType, Set<HashedEntryStackWrapper>> stacks = FilteringLogic.hidden(FilteringLogic.getRules(), false, false, EntryRegistry.getInstance().getEntryStacks().collect(Collectors.toList())); + Map<FilteringContextType, Set<HashedEntryStackWrapper>> stacks = FilteringLogic.hidden(List.of(r), false, false, EntryRegistry.getInstance().getEntryStacks().collect(Collectors.toList())); entryConsumer.accept(new SubRulesEntry(rule, () -> function.apply(true), Collections.singletonList(new SearchFilteringRuleType.EntryStacksRuleEntry(rule, diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/FilteringLogic.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/FilteringLogic.java index fe64c6975..7dd162834 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/FilteringLogic.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/FilteringLogic.java @@ -24,8 +24,11 @@ package me.shedaniel.rei.impl.common.entry.type; import com.google.common.base.Stopwatch; +import me.shedaniel.rei.api.client.config.ConfigManager; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.entry.filtering.FilteringRule; +import me.shedaniel.rei.api.client.entry.filtering.FilteringRuleType; +import me.shedaniel.rei.api.client.entry.filtering.FilteringRuleTypeRegistry; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.impl.client.config.ConfigObjectImpl; @@ -52,7 +55,18 @@ public class FilteringLogic { } public static List<FilteringRule<?>> getRules() { - return ((ConfigObjectImpl) ConfigObject.getInstance()).getFilteringRules(); + List<FilteringRule<?>> rules = ((ConfigObjectImpl) ConfigObject.getInstance()).getFilteringRules(); + boolean added = false; + for (FilteringRuleType<?> type : FilteringRuleTypeRegistry.getInstance()) { + if (type.isSingular() && rules.stream().noneMatch(filteringRule -> filteringRule.getType().equals(type))) { + rules.add(type.createNew()); + added = true; + } + } + if (added) { + ConfigManager.getInstance().saveConfig(); + } + return rules; } private static LinkedHashMap<FilteringRule<?>, Object> prepareCache(List<FilteringRule<?>> rules, boolean async, Collection<EntryStack<?>> entries) { diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/HideIngredientsFromTagsPlugin.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/HideIngredientsFromTagsPlugin.java new file mode 100644 index 000000000..8b641380f --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/HideIngredientsFromTagsPlugin.java @@ -0,0 +1,171 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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.plugin.client.runtime; + +import it.unimi.dsi.fastutil.longs.LongCollection; +import it.unimi.dsi.fastutil.longs.LongIterator; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; +import me.shedaniel.rei.RoughlyEnoughItemsCoreClient; +import me.shedaniel.rei.api.client.entry.filtering.*; +import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import me.shedaniel.rei.api.common.util.EntryIngredients; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.impl.common.InternalLogger; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.core.Registry; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import org.jetbrains.annotations.ApiStatus; + +import java.util.Collection; +import java.util.Iterator; + +/** + * A plugin to hide any ingredients from the <code>c:hidden_from_recipe_viewers</code> tag. + * This can be implemented in a few lines, but is instead implemented as a filtering rule type + * such that users may view the list of hidden ingredients separately in config. + */ +@Environment(EnvType.CLIENT) +@ApiStatus.Internal +public class HideIngredientsFromTagsPlugin implements REIClientPlugin { + private static final ResourceLocation HIDDEN_TAG = new ResourceLocation("c:hidden_from_recipe_viewers"); + + static { + FilteringRuleTypeRegistry.getInstance().register(new ResourceLocation("roughlyenoughitems", "hidden_from_recipe_viewers"), HideTagsFilteringRuleType.INSTANCE); + RoughlyEnoughItemsCoreClient.POST_UPDATE_TAGS.register(HideTagsFilteringRule.INSTANCE::markDirty); + } + + private enum HideTagsFilteringRuleType implements FilteringRuleType<HideTagsFilteringRule> { + INSTANCE; + + @Override + public CompoundTag saveTo(HideTagsFilteringRule rule, CompoundTag tag) { + return tag; + } + + @Override + public HideTagsFilteringRule readFrom(CompoundTag tag) { + return HideTagsFilteringRule.INSTANCE; + } + + @Override + public Component getTitle(HideTagsFilteringRule rule) { + return Component.translatable("rule.roughlyenoughitems.filtering.hide.tag"); + } + + @Override + public Component getSubtitle(HideTagsFilteringRule rule) { + return Component.translatable("rule.roughlyenoughitems.filtering.hide.tag.subtitle"); + } + + @Override + public HideTagsFilteringRule createNew() { + return HideTagsFilteringRule.INSTANCE; + } + + @Override + public boolean isSingular() { + return true; + } + } + + private enum HideTagsFilteringRule implements FilteringRule<HideTagsFilteringRule.Cache> { + INSTANCE; + + private Cache cache; + + private record Cache(EntryIngredient ingredient, LongSet hashes) {} + + @Override + public FilteringRuleType<? extends FilteringRule<HideTagsFilteringRule.Cache>> getType() { + return HideTagsFilteringRuleType.INSTANCE; + } + + @Override + public Cache prepareCache(boolean async) { + try { + EntryIngredient ingredient = EntryIngredient.builder() + .addAll(EntryIngredients.ofItemTag(TagKey.create(Registry.ITEM_REGISTRY, HIDDEN_TAG))) + .addAll(EntryIngredients.ofItemTag(TagKey.create(Registry.BLOCK_REGISTRY, HIDDEN_TAG))) + .addAll(EntryIngredients.ofFluidTag(TagKey.create(Registry.FLUID_REGISTRY, HIDDEN_TAG))) + .build(); + LongSet hashes = new LongOpenHashSet(); + for (EntryStack<?> stack : ingredient) { + hashes.add(EntryStacks.hashExact(stack)); + } + return this.cache = new Cache(ingredient, hashes); + } catch (Throwable e) { + InternalLogger.getInstance().warn("Failed to load hidden ingredients from tag, falling back to empty cache.", e); + return this.cache = null; + } + } + + @Override + public FilteringResult processFilteredStacks(FilteringContext context, FilteringResultFactory resultFactory, HideTagsFilteringRule.Cache cache, boolean async) { + FilteringResult result = resultFactory.create(); + if (cache != null) { + process(result, context.getShownStacks(), context.getShownExactHashes(), cache); + process(result, context.getUnsetStacks(), context.getUnsetExactHashes(), cache); + } + return result; + } + + private void process(FilteringResult result, Collection<EntryStack<?>> stacks, LongCollection hashes, HideTagsFilteringRule.Cache cache) { + Iterator<EntryStack<?>> stackIterator = stacks.iterator(); + LongIterator hashIterator = hashes.iterator(); + while (stackIterator.hasNext()) { + EntryStack<?> stack = stackIterator.next(); + long hash = hashIterator.nextLong(); + if (cache.hashes().contains(hash)) { + result.hide(stack); + } + } + } + + private void markDirty() { + InternalLogger.getInstance().debug("Marking hidden ingredients from tag cache as dirty."); + if (this.cache != null) { + this.markDirty(this.cache.ingredient(), this.cache.hashes()); + } + try { + VanillaEntryTypes.ITEM.getDefinition(); + } catch (NullPointerException ignored) { + this.cache = null; + return; + } + this.cache = this.prepareCache(false); + if (this.cache != null) { + this.markDirty(this.cache.ingredient(), this.cache.hashes()); + } + InternalLogger.getInstance().debug("Marked %d hidden ingredients from tag cache as dirty.", this.cache == null ? 0 : this.cache.hashes().size()); + } + } +} |
