diff --git a/src/main/java/ru/bclib/interfaces/BlockModelProvider.java b/src/main/java/ru/bclib/interfaces/BlockModelProvider.java index 26ba723c..5b4a6a86 100644 --- a/src/main/java/ru/bclib/interfaces/BlockModelProvider.java +++ b/src/main/java/ru/bclib/interfaces/BlockModelProvider.java @@ -1,5 +1,6 @@ package ru.bclib.interfaces; +import com.google.common.collect.Maps; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.renderer.block.model.BlockModel; diff --git a/src/main/java/ru/bclib/mixin/client/ModelBakeryMixin.java b/src/main/java/ru/bclib/mixin/client/ModelBakeryMixin.java index 065c2b0c..16326ea7 100644 --- a/src/main/java/ru/bclib/mixin/client/ModelBakeryMixin.java +++ b/src/main/java/ru/bclib/mixin/client/ModelBakeryMixin.java @@ -1,121 +1,103 @@ package ru.bclib.mixin.client; +import com.google.common.collect.Maps; +import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.renderer.block.BlockModelShaper; import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.client.renderer.block.model.multipart.MultiPart; import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.item.Items; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import ru.bclib.BCLib; import ru.bclib.interfaces.BlockModelProvider; import ru.bclib.interfaces.ItemModelProvider; -import java.util.List; import java.util.Map; -import java.util.Optional; @Mixin(ModelBakery.class) public abstract class ModelBakeryMixin { @Final @Shadow - private ResourceManager resourceManager; + private Map unbakedCache; @Final @Shadow - private Map unbakedCache; + private Map topLevelModels; - @Shadow - protected abstract void cacheAndQueueDependencies(ResourceLocation resourceLocation, UnbakedModel unbakedModel); + //private Map cache = Maps.newHashMap(); + //private Map topLevel = Maps.newHashMap(); - @Inject(method = "loadModel", at = @At("HEAD"), cancellable = true) - private void bclib_loadModels(ResourceLocation resourceLocation, CallbackInfo info) { - if (resourceLocation instanceof ModelResourceLocation) { - String modId = resourceLocation.getNamespace(); - String path = resourceLocation.getPath(); - ResourceLocation clearLoc = new ResourceLocation(modId, path); - ModelResourceLocation modelId = (ModelResourceLocation) resourceLocation; - if ("inventory".equals(modelId.getVariant())) { - ResourceLocation itemLoc = new ResourceLocation(modId, "item/" + path); - ResourceLocation itemModelLoc = new ResourceLocation(modId, "models/" + itemLoc.getPath() + ".json"); - if (!resourceManager.hasResource(itemModelLoc)) { - Item item = Registry.ITEM.get(clearLoc); - ItemModelProvider modelProvider = null; - if (item instanceof ItemModelProvider) { - modelProvider = (ItemModelProvider) item; - } - else if (item instanceof BlockItem) { - Block block = Registry.BLOCK.get(clearLoc); - if (block instanceof ItemModelProvider) { - modelProvider = (ItemModelProvider) block; - } - } - if (modelProvider != null) { - BlockModel model = modelProvider.getItemModel(clearLoc); - if (model != null) { - model.name = itemLoc.toString(); - cacheAndQueueDependencies(modelId, model); - unbakedCache.put(itemLoc, model); - } - else { - BCLib.LOGGER.warning("Error loading model: {}", itemLoc); - } - info.cancel(); + @Inject( + method = "*", + at = @At( + value = "INVOKE_STRING", + target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", + args = "ldc=static_definitions", + shift = Shift.BEFORE + ) + ) + private void bclib_initCustomModels(ResourceManager resourceManager, BlockColors blockColors, ProfilerFiller profiler, int mipmap, CallbackInfo info) { + Map cache = Maps.newHashMap(); + Map topLevel = Maps.newHashMap(); + + Registry.BLOCK.forEach(block -> { + if (block instanceof BlockModelProvider) { + ResourceLocation blockID = Registry.BLOCK.getKey(block); + ResourceLocation storageID = new ResourceLocation(blockID.getNamespace(), "blockstates/" + blockID.getPath() + ".json"); + BlockModelProvider provider = (BlockModelProvider) block; + + if (!resourceManager.hasResource(storageID)) { + BlockState defaultState = block.defaultBlockState(); + ResourceLocation defaultStateID = BlockModelShaper.stateToModelLocation(blockID, defaultState); + + UnbakedModel defaultModel = provider.getModelVariant(defaultStateID, defaultState, cache); + cache.put(blockID, defaultModel); + topLevel.put(blockID, defaultModel); + + block.getStateDefinition().getPossibleStates().forEach(blockState -> { + ResourceLocation stateID = BlockModelShaper.stateToModelLocation(blockID, blockState); + BlockModel model = provider.getBlockModel(stateID, blockState); + cache.put(stateID, model != null ? model : defaultModel); + }); + } + + if (Registry.ITEM.get(blockID) != Items.AIR) { + storageID = new ResourceLocation(blockID.getNamespace(), "models/item/" + blockID.getPath() + ".json"); + if (!resourceManager.hasResource(storageID)) { + ResourceLocation itemID = new ModelResourceLocation(blockID.getNamespace(), blockID.getPath(), "inventory"); + BlockModel model = provider.getItemModel(itemID); + cache.put(itemID, model); + topLevel.put(itemID, model); } } } - else { - ResourceLocation stateLoc = new ResourceLocation(modId, "blockstates/" + path + ".json"); - if (!resourceManager.hasResource(stateLoc)) { - Block block = Registry.BLOCK.get(clearLoc); - if (block instanceof BlockModelProvider) { - List possibleStates = block.getStateDefinition().getPossibleStates(); - Optional possibleState = possibleStates.stream() - .filter(state -> modelId.equals( - BlockModelShaper.stateToModelLocation( - clearLoc, - state - ))) - .findFirst(); - if (possibleState.isPresent()) { - UnbakedModel modelVariant = ((BlockModelProvider) block).getModelVariant( - modelId, - possibleState.get(), - unbakedCache - ); - if (modelVariant != null) { - if (modelVariant instanceof MultiPart) { - possibleStates.forEach(state -> { - ResourceLocation stateId = BlockModelShaper.stateToModelLocation( - clearLoc, - state - ); - cacheAndQueueDependencies(stateId, modelVariant); - }); - } - else { - cacheAndQueueDependencies(modelId, modelVariant); - } - } - else { - BCLib.LOGGER.warning("Error loading variant: {}", modelId); - } - info.cancel(); - } - } + }); + + Registry.ITEM.forEach(item -> { + if (item instanceof ItemModelProvider) { + ResourceLocation registryID = Registry.ITEM.getKey(item); + ResourceLocation storageID = new ResourceLocation(registryID.getNamespace(), "models/item/" + registryID.getPath() + ".json"); + if (!resourceManager.hasResource(storageID)) { + ResourceLocation itemID = new ModelResourceLocation(registryID.getNamespace(), registryID.getPath(), "inventory"); + ItemModelProvider provider = (ItemModelProvider) item; + BlockModel model = provider.getItemModel(registryID); + cache.put(itemID, model); + topLevel.put(itemID, model); } } - } + }); + + topLevelModels.putAll(topLevel); + unbakedCache.putAll(cache); } }