Model loading changes

This commit is contained in:
paulevsGitch 2021-07-30 14:41:04 +03:00
parent eb90792aca
commit fdcb5ad03a
2 changed files with 67 additions and 84 deletions

View file

@ -1,5 +1,6 @@
package ru.bclib.interfaces; package ru.bclib.interfaces;
import com.google.common.collect.Maps;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;

View file

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