diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MixinModelBakery.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MixinModelBakery.java new file mode 100644 index 00000000..55903216 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MixinModelBakery.java @@ -0,0 +1,22 @@ +package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; + +import net.minecraft.client.resources.model.ModelBakery; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.dynresources.DynamicModelSystem; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.BiFunction; + +@Mixin(ModelBakery.class) +@ClientOnlyMixin +public class MixinModelBakery { + @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;")) + private CompletableFuture> dynamicallyBake(Map input, BiFunction baker, Executor executor) { + return CompletableFuture.completedFuture(DynamicModelSystem.createDynamicBakedRegistry(input, baker)); + } +} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MixinModelManager.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MixinModelManager.java index a43fc6db..eaec796a 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MixinModelManager.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MixinModelManager.java @@ -1,7 +1,9 @@ package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; +import com.google.common.collect.Maps; import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.client.resources.model.BlockStateModelLoader; import net.minecraft.client.resources.model.ClientItemInfoLoader; import net.minecraft.client.resources.model.ModelManager; @@ -53,4 +55,15 @@ public class MixinModelManager { private static Object2IntMap buildModelGroups(BlockColors blockColors, BlockStateModelLoader.LoadedModels loadedModels) { return new DynamicModelSystem.BlockGroupingMap(blockColors, loadedModels); } + + /** + * @author embeddedt + * @reason avoid copying inner map + */ + @Overwrite + private static Map createBlockStateToModelDispatch(Map blockStateModels, BlockStateModel missingModel) { + return Maps.asMap(DynamicModelSystem.getAllBlockStates(), state -> { + return blockStateModels.getOrDefault(state, missingModel); + }); + } } diff --git a/src/main/java/org/embeddedt/modernfix/dynresources/DynamicModelSystem.java b/src/main/java/org/embeddedt/modernfix/dynresources/DynamicModelSystem.java index f9275ea9..346a8df7 100644 --- a/src/main/java/org/embeddedt/modernfix/dynresources/DynamicModelSystem.java +++ b/src/main/java/org/embeddedt/modernfix/dynresources/DynamicModelSystem.java @@ -32,7 +32,9 @@ import org.embeddedt.modernfix.common.mixin.perf.dynamic_resources.ModelDiscover import java.io.Reader; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.function.BiFunction; import java.util.stream.Collectors; public class DynamicModelSystem { @@ -65,6 +67,10 @@ public class DynamicModelSystem { BlockStateModelLoader.LoadedModels loadEntry(Identifier identifier, List blockstateResources); } + public static Set getAllBlockStates() { + return ((IdMapperAccessor)Block.BLOCK_STATE_REGISTRY).getReferenceMap().keySet(); + } + public static BlockStateModelLoader.LoadedModels createDynamicBlockStateLoadedModels(Map> resourceMap, SingleBlockStateEntryLoader entryLoader) { LoadingCache definitionCache = CacheBuilder.newBuilder().softValues().maximumSize(1000).build(new CacheLoader<>() { @Override @@ -77,8 +83,7 @@ public class DynamicModelSystem { return entryLoader.loadEntry(file, resources); } }); - Set allStates = ((IdMapperAccessor)Block.BLOCK_STATE_REGISTRY).getReferenceMap().keySet(); - return new BlockStateModelLoader.LoadedModels(Maps.asMap(allStates, state -> { + return new BlockStateModelLoader.LoadedModels(Maps.asMap(getAllBlockStates(), state -> { var identifier = state.getBlock().builtInRegistryHolder().getKey().identifier(); var loadedModels = definitionCache.getUnchecked(identifier); return loadedModels.models().get(state); @@ -148,4 +153,23 @@ public class DynamicModelSystem { return -1; } } + + public static Map createDynamicBakedRegistry(Map input, BiFunction baker) { + // TODO: support persistence of overrides + LoadingCache> bakedCache = CacheBuilder.newBuilder().softValues().maximumSize(1000).build(new CacheLoader<>() { + @Override + public Optional load(K key) throws Exception { + var unbaked = input.get(key); + if (unbaked != null) { + if (DEBUG_DYNAMIC_MODEL_LOADING) { + ModernFix.LOGGER.info("Baking {}", key); + } + return Optional.ofNullable(baker.apply(key, unbaked)); + } else { + return Optional.empty(); + } + } + }); + return Maps.asMap(input.keySet(), k -> k != null ? bakedCache.getUnchecked(k).orElse(null) : null); + } }