Skip to content

Commit 7840a86

Browse files
committed
Block models are now loaded & baked dynamically
1 parent 523cf8a commit 7840a86

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
2+
3+
import net.minecraft.client.resources.model.ModelBakery;
4+
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
5+
import org.embeddedt.modernfix.dynresources.DynamicModelSystem;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.injection.At;
8+
import org.spongepowered.asm.mixin.injection.Redirect;
9+
10+
import java.util.Map;
11+
import java.util.concurrent.CompletableFuture;
12+
import java.util.concurrent.Executor;
13+
import java.util.function.BiFunction;
14+
15+
@Mixin(ModelBakery.class)
16+
@ClientOnlyMixin
17+
public class MixinModelBakery {
18+
@Redirect(method = "bakeModels", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/thread/ParallelMapTransform;schedule(Ljava/util/Map;Ljava/util/function/BiFunction;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"))
19+
private <K, U, V> CompletableFuture<Map<K, V>> dynamicallyBake(Map<K, U> input, BiFunction<K, U, V> baker, Executor executor) {
20+
return CompletableFuture.completedFuture(DynamicModelSystem.createDynamicBakedRegistry(input, baker));
21+
}
22+
}

src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MixinModelManager.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
22

3+
import com.google.common.collect.Maps;
34
import it.unimi.dsi.fastutil.objects.Object2IntMap;
45
import net.minecraft.client.color.block.BlockColors;
6+
import net.minecraft.client.renderer.block.model.BlockStateModel;
57
import net.minecraft.client.resources.model.BlockStateModelLoader;
68
import net.minecraft.client.resources.model.ClientItemInfoLoader;
79
import net.minecraft.client.resources.model.ModelManager;
@@ -53,4 +55,15 @@ private static ModelManager.ResolvedModels discoverModelDependencies(
5355
private static Object2IntMap<BlockState> buildModelGroups(BlockColors blockColors, BlockStateModelLoader.LoadedModels loadedModels) {
5456
return new DynamicModelSystem.BlockGroupingMap(blockColors, loadedModels);
5557
}
58+
59+
/**
60+
* @author embeddedt
61+
* @reason avoid copying inner map
62+
*/
63+
@Overwrite
64+
private static Map<BlockState, BlockStateModel> createBlockStateToModelDispatch(Map<BlockState, BlockStateModel> blockStateModels, BlockStateModel missingModel) {
65+
return Maps.asMap(DynamicModelSystem.getAllBlockStates(), state -> {
66+
return blockStateModels.getOrDefault(state, missingModel);
67+
});
68+
}
5669
}

src/main/java/org/embeddedt/modernfix/dynresources/DynamicModelSystem.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
import java.io.Reader;
3333
import java.util.List;
3434
import java.util.Map;
35+
import java.util.Optional;
3536
import java.util.Set;
37+
import java.util.function.BiFunction;
3638
import java.util.stream.Collectors;
3739

3840
public class DynamicModelSystem {
@@ -65,6 +67,10 @@ public interface SingleBlockStateEntryLoader {
6567
BlockStateModelLoader.LoadedModels loadEntry(Identifier identifier, List<Resource> blockstateResources);
6668
}
6769

70+
public static Set<BlockState> getAllBlockStates() {
71+
return ((IdMapperAccessor<BlockState>)Block.BLOCK_STATE_REGISTRY).getReferenceMap().keySet();
72+
}
73+
6874
public static BlockStateModelLoader.LoadedModels createDynamicBlockStateLoadedModels(Map<Identifier, List<Resource>> resourceMap, SingleBlockStateEntryLoader entryLoader) {
6975
LoadingCache<Identifier, BlockStateModelLoader.LoadedModels> definitionCache = CacheBuilder.newBuilder().softValues().maximumSize(1000).build(new CacheLoader<>() {
7076
@Override
@@ -77,8 +83,7 @@ public BlockStateModelLoader.LoadedModels load(Identifier key) throws Exception
7783
return entryLoader.loadEntry(file, resources);
7884
}
7985
});
80-
Set<BlockState> allStates = ((IdMapperAccessor<BlockState>)Block.BLOCK_STATE_REGISTRY).getReferenceMap().keySet();
81-
return new BlockStateModelLoader.LoadedModels(Maps.asMap(allStates, state -> {
86+
return new BlockStateModelLoader.LoadedModels(Maps.asMap(getAllBlockStates(), state -> {
8287
var identifier = state.getBlock().builtInRegistryHolder().getKey().identifier();
8388
var loadedModels = definitionCache.getUnchecked(identifier);
8489
return loadedModels.models().get(state);
@@ -148,4 +153,23 @@ public int getInt(Object key) {
148153
return -1;
149154
}
150155
}
156+
157+
public static <K, U, V> Map<K, V> createDynamicBakedRegistry(Map<K, U> input, BiFunction<K, U, V> baker) {
158+
// TODO: support persistence of overrides
159+
LoadingCache<K, Optional<V>> bakedCache = CacheBuilder.newBuilder().softValues().maximumSize(1000).build(new CacheLoader<>() {
160+
@Override
161+
public Optional<V> load(K key) throws Exception {
162+
var unbaked = input.get(key);
163+
if (unbaked != null) {
164+
if (DEBUG_DYNAMIC_MODEL_LOADING) {
165+
ModernFix.LOGGER.info("Baking {}", key);
166+
}
167+
return Optional.ofNullable(baker.apply(key, unbaked));
168+
} else {
169+
return Optional.empty();
170+
}
171+
}
172+
});
173+
return Maps.asMap(input.keySet(), k -> k != null ? bakedCache.getUnchecked(k).orElse(null) : null);
174+
}
151175
}

0 commit comments

Comments
 (0)