/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.mojang.logging.LogUtils * org.slf4j.Logger */ package net.minecraft.client.resources.model; import com.mojang.logging.LogUtils; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.renderer.PlayerSkinRenderCache; import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.block.model.SimpleModelWrapper; import net.minecraft.client.renderer.block.model.SingleVariant; import net.minecraft.client.renderer.block.model.TextureSlots; 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.item.ModelRenderProperties; import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.client.renderer.rendertype.RenderTypes; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.BlockModelRotation; import net.minecraft.client.resources.model.Material; import net.minecraft.client.resources.model.MaterialSet; import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.client.resources.model.QuadCollection; import net.minecraft.client.resources.model.ResolvedModel; import net.minecraft.client.resources.model.SpriteGetter; import net.minecraft.resources.Identifier; import net.minecraft.util.thread.ParallelMapTransform; import net.minecraft.world.level.block.state.BlockState; import org.slf4j.Logger; public class ModelBakery { public static final Material FIRE_0 = Sheets.BLOCKS_MAPPER.defaultNamespaceApply("fire_0"); public static final Material FIRE_1 = Sheets.BLOCKS_MAPPER.defaultNamespaceApply("fire_1"); public static final Material LAVA_FLOW = Sheets.BLOCKS_MAPPER.defaultNamespaceApply("lava_flow"); public static final Material WATER_FLOW = Sheets.BLOCKS_MAPPER.defaultNamespaceApply("water_flow"); public static final Material WATER_OVERLAY = Sheets.BLOCKS_MAPPER.defaultNamespaceApply("water_overlay"); public static final Material BANNER_BASE = new Material(Sheets.BANNER_SHEET, Identifier.withDefaultNamespace("entity/banner_base")); public static final Material SHIELD_BASE = new Material(Sheets.SHIELD_SHEET, Identifier.withDefaultNamespace("entity/shield_base")); public static final Material NO_PATTERN_SHIELD = new Material(Sheets.SHIELD_SHEET, Identifier.withDefaultNamespace("entity/shield_base_nopattern")); public static final int DESTROY_STAGE_COUNT = 10; public static final List DESTROY_STAGES = IntStream.range(0, 10).mapToObj(i -> Identifier.withDefaultNamespace("block/destroy_stage_" + i)).collect(Collectors.toList()); public static final List BREAKING_LOCATIONS = DESTROY_STAGES.stream().map(location -> location.withPath(path -> "textures/" + path + ".png")).collect(Collectors.toList()); public static final List DESTROY_TYPES = BREAKING_LOCATIONS.stream().map(RenderTypes::crumbling).collect(Collectors.toList()); private static final Logger LOGGER = LogUtils.getLogger(); private final EntityModelSet entityModelSet; private final MaterialSet materials; private final PlayerSkinRenderCache playerSkinRenderCache; private final Map unbakedBlockStateModels; private final Map clientInfos; private final Map resolvedModels; private final ResolvedModel missingModel; public ModelBakery(EntityModelSet entityModelSet, MaterialSet materials, PlayerSkinRenderCache playerSkinRenderCache, Map unbakedBlockStateModels, Map clientInfos, Map resolvedModels, ResolvedModel missingModel) { this.entityModelSet = entityModelSet; this.materials = materials; this.playerSkinRenderCache = playerSkinRenderCache; this.unbakedBlockStateModels = unbakedBlockStateModels; this.clientInfos = clientInfos; this.resolvedModels = resolvedModels; this.missingModel = missingModel; } public CompletableFuture bakeModels(SpriteGetter sprites, Executor taskExecutor) { MissingModels missingModels = MissingModels.bake(this.missingModel, sprites); ModelBakerImpl baker = new ModelBakerImpl(sprites); CompletableFuture> bakedBlockStateModelFuture = ParallelMapTransform.schedule(this.unbakedBlockStateModels, (blockState, model) -> { try { return model.bake((BlockState)blockState, baker); } catch (Exception e) { LOGGER.warn("Unable to bake model: '{}': {}", blockState, (Object)e); return null; } }, taskExecutor); CompletableFuture> bakedItemStackModelFuture = ParallelMapTransform.schedule(this.clientInfos, (location, clientInfo) -> { try { return clientInfo.model().bake(new ItemModel.BakingContext(baker, this.entityModelSet, this.materials, this.playerSkinRenderCache, missingModels.item, clientInfo.registrySwapper())); } catch (Exception e) { LOGGER.warn("Unable to bake item model: '{}'", location, (Object)e); return null; } }, taskExecutor); HashMap itemStackModelProperties = new HashMap(this.clientInfos.size()); this.clientInfos.forEach((id, clientInfo) -> { ClientItem.Properties properties = clientInfo.properties(); if (!properties.equals(ClientItem.Properties.DEFAULT)) { itemStackModelProperties.put(id, properties); } }); return bakedBlockStateModelFuture.thenCombine(bakedItemStackModelFuture, (bakedBlockStateModels, bakedItemStateModels) -> new BakingResult(missingModels, (Map)bakedBlockStateModels, (Map)bakedItemStateModels, itemStackModelProperties)); } public record MissingModels(BlockStateModel block, ItemModel item) { public static MissingModels bake(ResolvedModel unbaked, final SpriteGetter sprites) { ModelBaker missingModelBakery = new ModelBaker(){ @Override public ResolvedModel getModel(Identifier location) { throw new IllegalStateException("Missing model can't have dependencies, but asked for " + String.valueOf(location)); } @Override public T compute(ModelBaker.SharedOperationKey key) { return key.compute(this); } @Override public SpriteGetter sprites() { return sprites; } }; TextureSlots textureSlots = unbaked.getTopTextureSlots(); boolean hasAmbientOcclusion = unbaked.getTopAmbientOcclusion(); boolean usesBlockLight = unbaked.getTopGuiLight().lightLikeBlock(); ItemTransforms transforms = unbaked.getTopTransforms(); QuadCollection geometry = unbaked.bakeTopGeometry(textureSlots, missingModelBakery, BlockModelRotation.IDENTITY); TextureAtlasSprite particleSprite = unbaked.resolveParticleSprite(textureSlots, missingModelBakery); SingleVariant bakedBlockModel = new SingleVariant(new SimpleModelWrapper(geometry, hasAmbientOcclusion, particleSprite)); MissingItemModel bakedItemModel = new MissingItemModel(geometry.getAll(), new ModelRenderProperties(usesBlockLight, particleSprite, transforms)); return new MissingModels(bakedBlockModel, bakedItemModel); } } private class ModelBakerImpl implements ModelBaker { private final SpriteGetter sprites; private final Map, Object> operationCache = new ConcurrentHashMap, Object>(); private final Function, Object> cacheComputeFunction = k -> k.compute(this); private ModelBakerImpl(SpriteGetter textures) { this.sprites = textures; } @Override public SpriteGetter sprites() { return this.sprites; } @Override public ResolvedModel getModel(Identifier location) { ResolvedModel result = ModelBakery.this.resolvedModels.get(location); if (result == null) { LOGGER.warn("Requested a model that was not discovered previously: {}", (Object)location); return ModelBakery.this.missingModel; } return result; } @Override public T compute(ModelBaker.SharedOperationKey key) { return (T)this.operationCache.computeIfAbsent(key, this.cacheComputeFunction); } } public record BakingResult(MissingModels missingModels, Map blockStateModels, Map itemStackModels, Map itemProperties) { } }