diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java index 3cef3b8c..5a9deb53 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java @@ -7,7 +7,7 @@ import net.minecraft.world.item.ItemStack; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; -import org.embeddedt.modernfix.searchtree.DummySearchTree; +import org.embeddedt.modernfix.searchtree.RecipeBookSearchTree; import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry; import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFWErrorCallback; @@ -37,7 +37,7 @@ public abstract class MinecraftMixin { SearchRegistry.TreeBuilderSupplier tagSupplier = list -> provider.getSearchTree(true); this.searchRegistry.register(SearchRegistry.CREATIVE_NAMES, nameSupplier); this.searchRegistry.register(SearchRegistry.CREATIVE_TAGS, tagSupplier); - this.searchRegistry.register(SearchRegistry.RECIPE_COLLECTIONS, list -> new DummySearchTree<>()); + this.searchRegistry.register(SearchRegistry.RECIPE_COLLECTIONS, list -> new RecipeBookSearchTree(provider.getSearchTree(false), list)); ModernFixPlatformHooks.INSTANCE.registerCreativeSearchTrees(this.searchRegistry, nameSupplier, tagSupplier, this::populateSearchTree); // grab components for all key mappings in order to prevent them from being loaded off-thread later // this populates the LazyLoadedValues diff --git a/common/src/main/java/org/embeddedt/modernfix/searchtree/RecipeBookSearchTree.java b/common/src/main/java/org/embeddedt/modernfix/searchtree/RecipeBookSearchTree.java new file mode 100644 index 00000000..6048f47e --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/searchtree/RecipeBookSearchTree.java @@ -0,0 +1,55 @@ +package org.embeddedt.modernfix.searchtree; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.client.gui.screens.recipebook.RecipeCollection; +import net.minecraft.client.searchtree.SearchTree; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class RecipeBookSearchTree extends DummySearchTree { + private final SearchTree stackCollector; + private Map> collectionsByItem = null; + private final List allCollections; + + public RecipeBookSearchTree(SearchTree stackCollector, List allCollections) { + this.stackCollector = stackCollector; + this.allCollections = allCollections; + } + + private Map> populateCollectionMap() { + Map> collections = this.collectionsByItem; + if(collections == null) { + collections = new Object2ObjectOpenHashMap<>(); + Map> finalCollection = collections; + for(RecipeCollection collection : allCollections) { + collection.getRecipes().stream().map(recipe -> recipe.getResultItem(collection.registryAccess()).getItem()).distinct().forEach(item -> { + finalCollection.computeIfAbsent(item, k -> new ArrayList<>()).add(collection); + }); + } + this.collectionsByItem = collections; + } + return collections; + } + + @Override + public void refresh() { + this.collectionsByItem = null; + } + + @Override + public List search(String pSearchText) { + // Avoid constructing the recipe collection map until the first real search + if(pSearchText.trim().length() == 0) { + return this.allCollections; + } + List stacks = stackCollector.search(pSearchText); + Map> collections = this.populateCollectionMap(); + return stacks.stream().map(ItemStack::getItem).distinct().flatMap(item -> collections.getOrDefault(item, Collections.emptyList()).stream()).collect(Collectors.toList()); + } +}