2025-11-24 22:52:51 +03:00

176 lines
9.5 KiB
Java

/*
* 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<Identifier> DESTROY_STAGES = IntStream.range(0, 10).mapToObj(i -> Identifier.withDefaultNamespace("block/destroy_stage_" + i)).collect(Collectors.toList());
public static final List<Identifier> BREAKING_LOCATIONS = DESTROY_STAGES.stream().map(location -> location.withPath(path -> "textures/" + path + ".png")).collect(Collectors.toList());
public static final List<RenderType> 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<BlockState, BlockStateModel.UnbakedRoot> unbakedBlockStateModels;
private final Map<Identifier, ClientItem> clientInfos;
private final Map<Identifier, ResolvedModel> resolvedModels;
private final ResolvedModel missingModel;
public ModelBakery(EntityModelSet entityModelSet, MaterialSet materials, PlayerSkinRenderCache playerSkinRenderCache, Map<BlockState, BlockStateModel.UnbakedRoot> unbakedBlockStateModels, Map<Identifier, ClientItem> clientInfos, Map<Identifier, ResolvedModel> 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<BakingResult> bakeModels(SpriteGetter sprites, Executor taskExecutor) {
MissingModels missingModels = MissingModels.bake(this.missingModel, sprites);
ModelBakerImpl baker = new ModelBakerImpl(sprites);
CompletableFuture<Map<BlockState, BlockStateModel>> 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<Map<Identifier, ItemModel>> 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<BlockState, BlockStateModel>)bakedBlockStateModels, (Map<Identifier, ItemModel>)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> T compute(ModelBaker.SharedOperationKey<T> 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<ModelBaker.SharedOperationKey<Object>, Object> operationCache = new ConcurrentHashMap<ModelBaker.SharedOperationKey<Object>, Object>();
private final Function<ModelBaker.SharedOperationKey<Object>, 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> T compute(ModelBaker.SharedOperationKey<T> key) {
return (T)this.operationCache.computeIfAbsent(key, this.cacheComputeFunction);
}
}
public record BakingResult(MissingModels missingModels, Map<BlockState, BlockStateModel> blockStateModels, Map<Identifier, ItemModel> itemStackModels, Map<Identifier, ClientItem.Properties> itemProperties) {
}
}