aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2023-01-22 00:08:47 +0800
committershedaniel <daniel@shedaniel.me>2023-01-22 00:14:02 +0800
commit7dac5856acd5a1b4111f009d3c348a501f1bc397 (patch)
tree9bd05e823a6d6db0605ff81264be339d0deddd62
parent3426ed6edef377ad690c44be3997a9be73df1638 (diff)
downloadRoughlyEnoughItems-7dac5856acd5a1b4111f009d3c348a501f1bc397.tar.gz
RoughlyEnoughItems-7dac5856acd5a1b4111f009d3c348a501f1bc397.tar.bz2
RoughlyEnoughItems-7dac5856acd5a1b4111f009d3c348a501f1bc397.zip
Add support for c:hidden_from_recipe_viewers
-rw-r--r--fabric/src/main/java/me/shedaniel/rei/mixin/fabric/MixinClientPacketListener.java6
-rw-r--r--fabric/src/main/resources/fabric.mod.json3
-rw-r--r--forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java2
-rw-r--r--forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinClientPacketListener.java6
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java1
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/FilteringLogic.java16
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/HideIngredientsFromTagsPlugin.java171
-rwxr-xr-xruntime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json2
9 files changed, 206 insertions, 3 deletions
diff --git a/fabric/src/main/java/me/shedaniel/rei/mixin/fabric/MixinClientPacketListener.java b/fabric/src/main/java/me/shedaniel/rei/mixin/fabric/MixinClientPacketListener.java
index 1e1eb0d3a..5f355b9fa 100644
--- a/fabric/src/main/java/me/shedaniel/rei/mixin/fabric/MixinClientPacketListener.java
+++ b/fabric/src/main/java/me/shedaniel/rei/mixin/fabric/MixinClientPacketListener.java
@@ -26,6 +26,7 @@ package me.shedaniel.rei.mixin.fabric;
import me.shedaniel.rei.RoughlyEnoughItemsCoreClient;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket;
+import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket;
import net.minecraft.world.item.crafting.RecipeManager;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -42,4 +43,9 @@ public class MixinClientPacketListener {
private void handleUpdateRecipes(ClientboundUpdateRecipesPacket clientboundUpdateRecipesPacket, CallbackInfo ci) {
RoughlyEnoughItemsCoreClient.PRE_UPDATE_RECIPES.invoker().update(recipeManager);
}
+
+ @Inject(method = "handleUpdateTags", at = @At("HEAD"))
+ private void handleUpdateTags(ClientboundUpdateTagsPacket packet, CallbackInfo ci) {
+ RoughlyEnoughItemsCoreClient.POST_UPDATE_TAGS.invoker().run();
+ }
} \ No newline at end of file
diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json
index bb8a221ae..70e6b0d83 100644
--- a/fabric/src/main/resources/fabric.mod.json
+++ b/fabric/src/main/resources/fabric.mod.json
@@ -28,7 +28,8 @@
],
"rei_client": [
"me.shedaniel.rei.plugin.client.DefaultClientPlugin",
- "me.shedaniel.rei.plugin.client.runtime.DefaultClientRuntimePlugin"
+ "me.shedaniel.rei.plugin.client.runtime.DefaultClientRuntimePlugin",
+ "me.shedaniel.rei.plugin.client.runtime.HideIngredientsFromTagsPlugin"
]
},
"accessWidener": "roughlyenoughitems.accessWidener",
diff --git a/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java b/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java
index 64dbf3d72..0ec02248c 100644
--- a/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java
+++ b/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java
@@ -35,6 +35,7 @@ import me.shedaniel.rei.api.common.plugins.REIServerPlugin;
import me.shedaniel.rei.impl.init.PluginDetector;
import me.shedaniel.rei.plugin.client.forge.DefaultClientPluginImpl;
import me.shedaniel.rei.plugin.client.runtime.DefaultClientRuntimePlugin;
+import me.shedaniel.rei.plugin.client.runtime.HideIngredientsFromTagsPlugin;
import me.shedaniel.rei.plugin.common.forge.DefaultPluginImpl;
import me.shedaniel.rei.plugin.common.runtime.DefaultRuntimePlugin;
import net.minecraftforge.api.distmarker.Dist;
@@ -178,6 +179,7 @@ public class PluginDetectorImpl implements PluginDetector {
return () -> () -> {
PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultClientPluginImpl()));
PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultClientRuntimePlugin()));
+ PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new HideIngredientsFromTagsPlugin()));
// Legacy Annotation
AnnotationUtils.<REIPlugin, REIClientPlugin>scanAnnotation(REIPlugin.class, REIClientPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
diff --git a/forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinClientPacketListener.java b/forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinClientPacketListener.java
index 5911cb28d..989b0eb63 100644
--- a/forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinClientPacketListener.java
+++ b/forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinClientPacketListener.java
@@ -26,6 +26,7 @@ package me.shedaniel.rei.mixin.forge;
import me.shedaniel.rei.RoughlyEnoughItemsCoreClient;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket;
+import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket;
import net.minecraft.world.item.crafting.RecipeManager;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -42,4 +43,9 @@ public class MixinClientPacketListener {
private void handleUpdateRecipes(ClientboundUpdateRecipesPacket clientboundUpdateRecipesPacket, CallbackInfo ci) {
RoughlyEnoughItemsCoreClient.PRE_UPDATE_RECIPES.invoker().update(recipeManager);
}
+
+ @Inject(method = "handleUpdateTags", at = @At("HEAD"))
+ private void handleUpdateTags(ClientboundUpdateTagsPacket packet, CallbackInfo ci) {
+ RoughlyEnoughItemsCoreClient.POST_UPDATE_TAGS.invoker().run();
+ }
} \ No newline at end of file
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());
+ }
+ }
+}
diff --git a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json
index b4af25079..680d7019f 100755
--- a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json
+++ b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json
@@ -368,6 +368,8 @@
"rule.roughlyenoughitems.filtering.search.show.false": "Hide",
"rule.roughlyenoughitems.filtering.basic": "Basic Plugin Filtering",
"rule.roughlyenoughitems.filtering.basic.subtitle": "Filter entries by REI plugins. This is not configurable here.",
+ "rule.roughlyenoughitems.filtering.hide.tag": "Tag Filtering",
+ "rule.roughlyenoughitems.filtering.hide.tag.subtitle": "Filter entries by 'c:hidden_from_recipe_viewers'. This is not configurable here.",
"language.roughlyenoughitems.english": "English",
"language.roughlyenoughitems.japanese": "Japanese",
"language.roughlyenoughitems.chinese_simplified": "Chinese Simplified",