Skip to content

Commit 8c2c330

Browse files
committed
Build creative mode tab search tree on first use
This avoids holding search trees for many creative tabs that will likely never be searched during gameplay.
1 parent 63aeef1 commit 8c2c330

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.lazy_search_tree_registry;
2+
3+
import net.minecraft.client.searchtree.SearchRegistry;
4+
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
5+
import org.embeddedt.modernfix.searchtree.LazySearchTree;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.injection.At;
8+
import org.spongepowered.asm.mixin.injection.ModifyVariable;
9+
10+
@Mixin(SearchRegistry.class)
11+
@ClientOnlyMixin
12+
public class SearchRegistryMixin {
13+
@ModifyVariable(method = "register", at = @At("HEAD"), ordinal = 0, argsOnly = true)
14+
private <T> SearchRegistry.TreeBuilderSupplier<T> useLazyBuilder(SearchRegistry.TreeBuilderSupplier<T> supplier) {
15+
return LazySearchTree.decorate(supplier);
16+
}
17+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package org.embeddedt.modernfix.searchtree;
2+
3+
import com.google.common.base.Stopwatch;
4+
import net.minecraft.client.searchtree.RefreshableSearchTree;
5+
import net.minecraft.client.searchtree.SearchRegistry;
6+
import org.embeddedt.modernfix.ModernFix;
7+
8+
import java.util.List;
9+
import java.util.function.Function;
10+
11+
public class LazySearchTree<T> implements RefreshableSearchTree<T> {
12+
private final List<T> contents;
13+
private final Function<List<T>, RefreshableSearchTree<T>> treeBuilder;
14+
15+
private volatile RefreshableSearchTree<T> realTree;
16+
17+
public LazySearchTree(List<T> contents, Function<List<T>, RefreshableSearchTree<T>> treeBuilder) {
18+
this.contents = contents;
19+
this.treeBuilder = treeBuilder;
20+
}
21+
22+
private RefreshableSearchTree<T> getRealTree() {
23+
var t = realTree;
24+
if (t == null) {
25+
synchronized (this) {
26+
t = realTree;
27+
if (t == null) {
28+
ModernFix.LOGGER.info("Building search tree for {} items (this may take a while)...", contents.size());
29+
Stopwatch s = Stopwatch.createStarted();
30+
t = this.treeBuilder.apply(contents);
31+
t.refresh();
32+
s.stop();
33+
ModernFix.LOGGER.info("Building search tree for {} items took {}", contents.size(), s);
34+
realTree = t;
35+
}
36+
}
37+
}
38+
return t;
39+
}
40+
41+
@Override
42+
public List<T> search(String query) {
43+
if (query.isEmpty()) {
44+
return this.contents;
45+
}
46+
return getRealTree().search(query);
47+
}
48+
49+
@Override
50+
public void refresh() {
51+
var t = this.realTree;
52+
if (t != null) {
53+
t.refresh();
54+
}
55+
}
56+
57+
public static <T> SearchRegistry.TreeBuilderSupplier<T> decorate(SearchRegistry.TreeBuilderSupplier<T> originalSupplier) {
58+
return list -> new LazySearchTree<>(list, originalSupplier);
59+
}
60+
}

common/src/main/resources/modernfix.accesswidener

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ accessible field net/minecraft/client/renderer/entity/EnderDragonRenderer$Dragon
6363
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;
6464

6565
accessible class net/minecraft/world/item/crafting/Ingredient$Value
66-
accessible class net/minecraft/world/item/crafting/Ingredient$ItemValue
66+
accessible class net/minecraft/world/item/crafting/Ingredient$ItemValue
67+
accessible class net/minecraft/client/searchtree/SearchRegistry$TreeEntry

0 commit comments

Comments
 (0)