package net.minecraft.client.resources.model; import com.mojang.logging.LogUtils; import com.mojang.math.Transformation; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.IntStream; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.block.model.UnbakedBlockStateModel; import net.minecraft.client.renderer.item.ClientItem; import net.minecraft.client.renderer.item.ItemModel; import net.minecraft.client.renderer.item.MissingItemModel; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.ModelBakery.TextureGetter.1; import net.minecraft.resources.ResourceLocation; import org.slf4j.Logger; @Environment(EnvType.CLIENT) public class ModelBakery { public static final Material FIRE_0 = new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.withDefaultNamespace("block/fire_0")); public static final Material FIRE_1 = new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.withDefaultNamespace("block/fire_1")); public static final Material LAVA_FLOW = new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.withDefaultNamespace("block/lava_flow")); public static final Material WATER_FLOW = new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.withDefaultNamespace("block/water_flow")); public static final Material WATER_OVERLAY = new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.withDefaultNamespace("block/water_overlay")); public static final Material BANNER_BASE = new Material(Sheets.BANNER_SHEET, ResourceLocation.withDefaultNamespace("entity/banner_base")); public static final Material SHIELD_BASE = new Material(Sheets.SHIELD_SHEET, ResourceLocation.withDefaultNamespace("entity/shield_base")); public static final Material NO_PATTERN_SHIELD = new Material(Sheets.SHIELD_SHEET, ResourceLocation.withDefaultNamespace("entity/shield_base_nopattern")); public static final int DESTROY_STAGE_COUNT = 10; public static final List DESTROY_STAGES = (List)IntStream.range(0, 10) .mapToObj(i -> ResourceLocation.withDefaultNamespace("block/destroy_stage_" + i)) .collect(Collectors.toList()); public static final List BREAKING_LOCATIONS = (List)DESTROY_STAGES.stream() .map(resourceLocation -> resourceLocation.withPath((UnaryOperator)(string -> "textures/" + string + ".png"))) .collect(Collectors.toList()); public static final List DESTROY_TYPES = (List)BREAKING_LOCATIONS.stream().map(RenderType::crumbling).collect(Collectors.toList()); static final Logger LOGGER = LogUtils.getLogger(); private final EntityModelSet entityModelSet; final Map bakedCache = new HashMap(); private final Map unbakedBlockStateModels; private final Map clientInfos; final Map unbakedPlainModels; final UnbakedModel missingModel; public ModelBakery( EntityModelSet entityModelSet, Map unbakedBlockStateModels, Map unbakedItemStackModels, Map unbakedPlainModels, UnbakedModel missingModel ) { this.entityModelSet = entityModelSet; this.unbakedBlockStateModels = unbakedBlockStateModels; this.clientInfos = unbakedItemStackModels; this.unbakedPlainModels = unbakedPlainModels; this.missingModel = missingModel; } public ModelBakery.BakingResult bakeModels(ModelBakery.TextureGetter textureGetter) { BakedModel bakedModel = UnbakedModel.bakeWithTopModelValues( this.missingModel, new ModelBakery.ModelBakerImpl(textureGetter, () -> "missing"), BlockModelRotation.X0_Y0 ); Map map = new HashMap(this.unbakedBlockStateModels.size()); this.unbakedBlockStateModels.forEach((modelResourceLocation, unbakedBlockStateModel) -> { try { BakedModel bakedModelx = unbakedBlockStateModel.bake(new ModelBakery.ModelBakerImpl(textureGetter, modelResourceLocation::toString)); map.put(modelResourceLocation, bakedModelx); } catch (Exception var6x) { LOGGER.warn("Unable to bake model: '{}': {}", modelResourceLocation, var6x); } }); ItemModel itemModel = new MissingItemModel(bakedModel); Map map2 = new HashMap(this.clientInfos.size()); Map map3 = new HashMap(this.clientInfos.size()); this.clientInfos.forEach((resourceLocation, clientItem) -> { ModelDebugName modelDebugName = () -> resourceLocation + "#inventory"; ModelBakery.ModelBakerImpl modelBakerImpl = new ModelBakery.ModelBakerImpl(textureGetter, modelDebugName); ItemModel.BakingContext bakingContext = new ItemModel.BakingContext(modelBakerImpl, this.entityModelSet, itemModel); try { ItemModel itemModel2 = clientItem.model().bake(bakingContext); map2.put(resourceLocation, itemModel2); if (!clientItem.properties().equals(ClientItem.Properties.DEFAULT)) { map3.put(resourceLocation, clientItem.properties()); } } catch (Exception var11) { LOGGER.warn("Unable to bake item model: '{}'", resourceLocation, var11); } }); return new ModelBakery.BakingResult(bakedModel, map, itemModel, map2, map3); } @Environment(EnvType.CLIENT) record BakedCacheKey(ResourceLocation id, Transformation transformation, boolean isUvLocked) { } @Environment(EnvType.CLIENT) public record BakingResult( BakedModel missingModel, Map blockStateModels, ItemModel missingItemModel, Map itemStackModels, Map itemProperties ) { } @Environment(EnvType.CLIENT) class ModelBakerImpl implements ModelBaker { private final ModelDebugName rootName; private final SpriteGetter modelTextureGetter; ModelBakerImpl(final ModelBakery.TextureGetter textureGetter, final ModelDebugName rootName) { this.modelTextureGetter = textureGetter.bind(rootName); this.rootName = rootName; } @Override public SpriteGetter sprites() { return this.modelTextureGetter; } private UnbakedModel getModel(ResourceLocation name) { UnbakedModel unbakedModel = (UnbakedModel)ModelBakery.this.unbakedPlainModels.get(name); if (unbakedModel == null) { ModelBakery.LOGGER.warn("Requested a model that was not discovered previously: {}", name); return ModelBakery.this.missingModel; } else { return unbakedModel; } } @Override public BakedModel bake(ResourceLocation location, ModelState transform) { ModelBakery.BakedCacheKey bakedCacheKey = new ModelBakery.BakedCacheKey(location, transform.getRotation(), transform.isUvLocked()); BakedModel bakedModel = (BakedModel)ModelBakery.this.bakedCache.get(bakedCacheKey); if (bakedModel != null) { return bakedModel; } else { UnbakedModel unbakedModel = this.getModel(location); BakedModel bakedModel2 = UnbakedModel.bakeWithTopModelValues(unbakedModel, this, transform); ModelBakery.this.bakedCache.put(bakedCacheKey, bakedModel2); return bakedModel2; } } @Override public ModelDebugName rootName() { return this.rootName; } } @Environment(EnvType.CLIENT) public interface TextureGetter { TextureAtlasSprite get(ModelDebugName name, Material material); TextureAtlasSprite reportMissingReference(ModelDebugName name, String reference); default SpriteGetter bind(ModelDebugName name) { return new 1(this, name); } } }