diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/lazy_search_tree_registry/SearchRegistryMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/lazy_search_tree_registry/SearchRegistryMixin.java new file mode 100644 index 00000000..b9ab980f --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/lazy_search_tree_registry/SearchRegistryMixin.java @@ -0,0 +1,17 @@ +package org.embeddedt.modernfix.common.mixin.perf.lazy_search_tree_registry; + +import net.minecraft.client.searchtree.SearchRegistry; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.searchtree.LazySearchTree; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(SearchRegistry.class) +@ClientOnlyMixin +public class SearchRegistryMixin { + @ModifyVariable(method = "register", at = @At("HEAD"), ordinal = 0, argsOnly = true) + private SearchRegistry.TreeBuilderSupplier useLazyBuilder(SearchRegistry.TreeBuilderSupplier supplier) { + return LazySearchTree.decorate(supplier); + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/searchtree/LazySearchTree.java b/common/src/main/java/org/embeddedt/modernfix/searchtree/LazySearchTree.java new file mode 100644 index 00000000..af54daa8 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/searchtree/LazySearchTree.java @@ -0,0 +1,60 @@ +package org.embeddedt.modernfix.searchtree; + +import com.google.common.base.Stopwatch; +import net.minecraft.client.searchtree.RefreshableSearchTree; +import net.minecraft.client.searchtree.SearchRegistry; +import org.embeddedt.modernfix.ModernFix; + +import java.util.List; +import java.util.function.Function; + +public class LazySearchTree implements RefreshableSearchTree { + private final List contents; + private final Function, RefreshableSearchTree> treeBuilder; + + private volatile RefreshableSearchTree realTree; + + public LazySearchTree(List contents, Function, RefreshableSearchTree> treeBuilder) { + this.contents = contents; + this.treeBuilder = treeBuilder; + } + + private RefreshableSearchTree getRealTree() { + var t = realTree; + if (t == null) { + synchronized (this) { + t = realTree; + if (t == null) { + ModernFix.LOGGER.info("Building search tree for {} items (this may take a while)...", contents.size()); + Stopwatch s = Stopwatch.createStarted(); + t = this.treeBuilder.apply(contents); + t.refresh(); + s.stop(); + ModernFix.LOGGER.info("Building search tree for {} items took {}", contents.size(), s); + realTree = t; + } + } + } + return t; + } + + @Override + public List search(String query) { + if (query.isEmpty()) { + return this.contents; + } + return getRealTree().search(query); + } + + @Override + public void refresh() { + var t = this.realTree; + if (t != null) { + t.refresh(); + } + } + + public static SearchRegistry.TreeBuilderSupplier decorate(SearchRegistry.TreeBuilderSupplier originalSupplier) { + return list -> new LazySearchTree<>(list, originalSupplier); + } +} diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 7405d408..d68848ee 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -32,12 +32,22 @@ accessible field net/minecraft/client/renderer/texture/Stitcher$Holder width I accessible field net/minecraft/client/renderer/texture/Stitcher$Holder height I accessible field net/minecraft/network/syncher/EntityDataAccessor id I mutable field net/minecraft/network/syncher/EntityDataAccessor id I +accessible class net/minecraft/client/resources/model/ModelBakery$BlockStateDefinitionException +accessible field net/minecraft/network/syncher/SynchedEntityData itemsById Lit/unimi/dsi/fastutil/ints/Int2ObjectMap; +accessible field net/minecraft/network/syncher/SynchedEntityData ENTITY_ID_POOL Lit/unimi/dsi/fastutil/objects/Object2IntMap; +accessible field net/minecraft/network/syncher/SynchedEntityData lock Ljava/util/concurrent/locks/ReadWriteLock; +accessible method net/minecraft/Util makeExecutor (Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; accessible field net/minecraft/server/level/ChunkMap updatingChunkMap Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap; accessible field net/minecraft/server/level/ChunkMap visibleChunkMap Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap; accessible field net/minecraft/server/level/ChunkMap pendingUnloads Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap; accessible method net/minecraft/resources/ResourceKey (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/resources/ResourceLocation;)V accessible field net/minecraft/client/renderer/block/model/BlockModel GSON Lcom/google/gson/Gson; accessible class net/minecraft/server/level/ChunkMap$DistanceManager +accessible class net/minecraft/client/resources/model/ModelBakery$BakedCacheKey +accessible field net/minecraft/client/resources/model/ModelBakery bakedCache Ljava/util/Map; +accessible field net/minecraft/client/resources/model/ModelBakery ITEM_MODEL_GENERATOR Lnet/minecraft/client/renderer/block/model/ItemModelGenerator; +accessible method net/minecraft/client/resources/model/ModelBakery loadTopLevel (Lnet/minecraft/client/resources/model/ModelResourceLocation;)V +accessible field net/minecraft/client/resources/model/ModelBakery topLevelModels Ljava/util/Map; accessible class net/minecraft/client/resources/model/ModelBakery$ModelBakerImpl accessible class net/minecraft/client/resources/model/ModelManager$ReloadState accessible method net/minecraft/client/resources/model/BlockStateModelLoader loadBlockStateDefinitionStack (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/world/level/block/state/StateDefinition;Ljava/util/List;)Lnet/minecraft/client/resources/model/BlockStateModelLoader$LoadedModels; @@ -48,10 +58,11 @@ accessible field net/minecraft/server/MinecraftServer resources Lnet/minecraft/s accessible class net/minecraft/server/MinecraftServer$ReloadableResources accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map; +accessible field net/minecraft/client/renderer/block/model/multipart/MultiPart definition Lnet/minecraft/world/level/block/state/StateDefinition; +accessible field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOverride model Lnet/minecraft/client/resources/model/BakedModel; +mutable field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOverride model Lnet/minecraft/client/resources/model/BakedModel; +accessible field net/minecraft/client/renderer/entity/EnderDragonRenderer$DragonModel entity Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon; accessible method net/minecraft/world/level/block/state/StateDefinition appendPropertyCodec (Lcom/mojang/serialization/MapCodec;Ljava/util/function/Supplier;Ljava/lang/String;Lnet/minecraft/world/level/block/state/properties/Property;)Lcom/mojang/serialization/MapCodec; -accessible class net/minecraft/client/multiplayer/SessionSearchTrees$Key -accessible class net/minecraft/client/resources/model/ModelDiscovery$ModelWrapper -accessible method net/minecraft/client/resources/model/ModelDiscovery$ModelWrapper (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/UnbakedModel;Z)V -accessible field net/minecraft/client/resources/model/ModelDiscovery$ModelWrapper parent Lnet/minecraft/client/resources/model/ModelDiscovery$ModelWrapper; -accessible method net/minecraft/client/resources/model/BlockStateDefinitions definitionLocationToBlockStateMapper ()Ljava/util/function/Function; \ No newline at end of file +accessible class net/minecraft/world/item/crafting/Ingredient$Value +accessible class net/minecraft/world/item/crafting/Ingredient$ItemValue \ No newline at end of file