Skip to content

Commit a13587e

Browse files
committed
Fix presizing of model location set & use more efficient string generation logic
1 parent 6979b56 commit a13587e

File tree

2 files changed

+68
-8
lines changed

2 files changed

+68
-8
lines changed

forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,11 @@
66
import com.google.common.graph.GraphBuilder;
77
import com.google.common.graph.MutableGraph;
88
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
9-
import net.minecraft.client.renderer.block.BlockModelShaper;
109
import net.minecraft.client.resources.model.BakedModel;
1110
import net.minecraft.client.resources.model.ModelBakery;
1211
import net.minecraft.client.resources.model.ModelResourceLocation;
1312
import net.minecraft.core.registries.BuiltInRegistries;
1413
import net.minecraft.resources.ResourceLocation;
15-
import net.minecraft.world.level.block.Block;
16-
import net.minecraft.world.level.block.state.BlockState;
1714
import net.minecraftforge.fml.ModContainer;
1815
import net.minecraftforge.fml.ModList;
1916
import net.minecraftforge.forgespi.language.IModInfo;
@@ -60,13 +57,15 @@ private enum UniverseVisibility {
6057
private final MutableGraph<String> dependencyGraph;
6158
public ModelBakeEventHelper(Map<ResourceLocation, BakedModel> modelRegistry) {
6259
this.modelRegistry = modelRegistry;
63-
this.topLevelModelLocations = new ObjectLinkedOpenHashSet<>(Block.BLOCK_STATE_REGISTRY.size() + BuiltInRegistries.ITEM.size());
64-
// Skip going through ModelLocationCache because most of the accesses will be misses
60+
int blockStateCount = 0;
61+
for (var b : BuiltInRegistries.BLOCK) {
62+
blockStateCount += b.getStateDefinition().getPossibleStates().size();
63+
}
64+
this.topLevelModelLocations = new ObjectLinkedOpenHashSet<>(blockStateCount + BuiltInRegistries.ITEM.size());
65+
var modelLocationBuilder = new ModelLocationBuilder();
6566
BuiltInRegistries.BLOCK.entrySet().forEach(entry -> {
6667
var location = entry.getKey().location();
67-
for(BlockState state : entry.getValue().getStateDefinition().getPossibleStates()) {
68-
topLevelModelLocations.add(BlockModelShaper.stateToModelLocation(location, state));
69-
}
68+
modelLocationBuilder.generateForBlock(topLevelModelLocations, entry.getValue(), location);
7069
});
7170
BuiltInRegistries.ITEM.keySet().forEach(key -> topLevelModelLocations.add(new ModelResourceLocation(key, "inventory")));
7271
this.topLevelModelLocations.addAll(modelRegistry.keySet());
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package org.embeddedt.modernfix.forge.dynresources;
2+
3+
import com.google.common.collect.Lists;
4+
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
5+
import net.minecraft.client.resources.model.ModelResourceLocation;
6+
import net.minecraft.resources.ResourceLocation;
7+
import net.minecraft.world.level.block.Block;
8+
import net.minecraft.world.level.block.state.properties.Property;
9+
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.Set;
13+
14+
public class ModelLocationBuilder {
15+
private final Object2ObjectOpenHashMap<Property<?>, PropertyData> propertyToOptionStrings = new Object2ObjectOpenHashMap<>();
16+
private final StringBuilder builder = new StringBuilder();
17+
18+
private record PropertyData(List<String> nameValuePairs, int maxPairLength) {}
19+
20+
public void generateForBlock(Set<ResourceLocation> destinationSet, Block block, ResourceLocation baseLocation) {
21+
var props = block.getStateDefinition().getProperties();
22+
List<List<String>> optionsList = new ArrayList<>();
23+
int requiredBuilderSize = Math.max(0, props.size() - 1); // commas
24+
for (var prop : props) {
25+
var data = propertyToOptionStrings.computeIfAbsent(prop, ModelLocationBuilder::computePropertyOptions);
26+
optionsList.add(data.nameValuePairs);
27+
requiredBuilderSize += data.maxPairLength;
28+
}
29+
var product = Lists.cartesianProduct(optionsList);
30+
int count = product.size();
31+
int tupleEntryCount = optionsList.size();
32+
StringBuilder stringbuilder = this.builder;
33+
stringbuilder.ensureCapacity(requiredBuilderSize);
34+
for (int i = 0; i < count; i++) {
35+
stringbuilder.setLength(0);
36+
var result = product.get(i);
37+
for (int j = 0; j < tupleEntryCount; j++) {
38+
if (j != 0) {
39+
stringbuilder.append(',');
40+
}
41+
stringbuilder.append(result.get(j));
42+
}
43+
destinationSet.add(new ModelResourceLocation(baseLocation, stringbuilder.toString()));
44+
}
45+
}
46+
47+
private static PropertyData computePropertyOptions(Property<?> prop) {
48+
List<String> valuesList = new ArrayList<>(prop.getPossibleValues().size());
49+
int maxLength = 0;
50+
for (var val : prop.getPossibleValues()) {
51+
String pair = prop.getName() + "=" + getValueName(prop, val);
52+
valuesList.add(pair);
53+
maxLength = Math.max(pair.length(), maxLength);
54+
}
55+
return new PropertyData(List.copyOf(valuesList), maxLength);
56+
}
57+
58+
private static <T extends Comparable<T>> String getValueName(Property<T> property, Comparable<?> value) {
59+
return property.getName((T)value);
60+
}
61+
}

0 commit comments

Comments
 (0)