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

174 lines
8.0 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.google.common.base.Suppliers
* com.mojang.datafixers.kinds.App
* com.mojang.datafixers.kinds.Applicative
* com.mojang.serialization.MapCodec
* com.mojang.serialization.codecs.RecordCodecBuilder
* org.joml.Vector3f
* org.jspecify.annotations.Nullable
*/
package net.minecraft.client.renderer.item;
import com.google.common.base.Suppliers;
import com.mojang.datafixers.kinds.App;
import com.mojang.datafixers.kinds.Applicative;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import net.minecraft.client.color.item.ItemTintSource;
import net.minecraft.client.color.item.ItemTintSources;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.FaceBakery;
import net.minecraft.client.renderer.block.model.TextureSlots;
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
import net.minecraft.client.renderer.item.ItemModel;
import net.minecraft.client.renderer.item.ItemModelResolver;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.renderer.item.ModelRenderProperties;
import net.minecraft.client.renderer.rendertype.RenderType;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.resources.model.BlockModelRotation;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.client.resources.model.ResolvableModel;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.resources.Identifier;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.ItemOwner;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.joml.Vector3f;
import org.jspecify.annotations.Nullable;
public class BlockModelWrapper
implements ItemModel {
private static final Function<ItemStack, RenderType> ITEM_RENDER_TYPE_GETTER = stack -> Sheets.translucentItemSheet();
private static final Function<ItemStack, RenderType> BLOCK_RENDER_TYPE_GETTER = stack -> {
BlockItem blockItem;
ChunkSectionLayer blockLayer;
Item patt0$temp = stack.getItem();
if (patt0$temp instanceof BlockItem && (blockLayer = ItemBlockRenderTypes.getChunkRenderType((blockItem = (BlockItem)patt0$temp).getBlock().defaultBlockState())) == ChunkSectionLayer.TRANSLUCENT) {
return Sheets.translucentBlockItemSheet();
}
return Sheets.cutoutBlockSheet();
};
private final List<ItemTintSource> tints;
private final List<BakedQuad> quads;
private final Supplier<Vector3f[]> extents;
private final ModelRenderProperties properties;
private final boolean animated;
private final Function<ItemStack, RenderType> renderType;
private BlockModelWrapper(List<ItemTintSource> tints, List<BakedQuad> quads, ModelRenderProperties properties, Function<ItemStack, RenderType> renderType) {
this.tints = tints;
this.quads = quads;
this.properties = properties;
this.renderType = renderType;
this.extents = Suppliers.memoize(() -> BlockModelWrapper.computeExtents(this.quads));
boolean animated = false;
for (BakedQuad quad : quads) {
if (!quad.sprite().contents().isAnimated()) continue;
animated = true;
break;
}
this.animated = animated;
}
public static Vector3f[] computeExtents(List<BakedQuad> quads) {
HashSet result = new HashSet();
for (BakedQuad quad : quads) {
FaceBakery.extractPositions(quad.vertices(), result::add);
}
return (Vector3f[])result.toArray(Vector3f[]::new);
}
@Override
public void update(ItemStackRenderState output, ItemStack item, ItemModelResolver resolver, ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable ItemOwner owner, int seed) {
output.appendModelIdentityElement(this);
ItemStackRenderState.LayerRenderState layer = output.newLayer();
if (item.hasFoil()) {
ItemStackRenderState.FoilType foilType = BlockModelWrapper.hasSpecialAnimatedTexture(item) ? ItemStackRenderState.FoilType.SPECIAL : ItemStackRenderState.FoilType.STANDARD;
layer.setFoilType(foilType);
output.setAnimated();
output.appendModelIdentityElement((Object)foilType);
}
int activeTints = this.tints.size();
int[] tintLayers = layer.prepareTintLayers(activeTints);
for (int i = 0; i < activeTints; ++i) {
int tint;
tintLayers[i] = tint = this.tints.get(i).calculate(item, level, owner == null ? null : owner.asLivingEntity());
output.appendModelIdentityElement(tint);
}
layer.setExtents(this.extents);
layer.setRenderType(this.renderType.apply(item));
this.properties.applyToLayer(layer, displayContext);
layer.prepareQuadList().addAll(this.quads);
if (this.animated) {
output.setAnimated();
}
}
private static Function<ItemStack, RenderType> detectRenderType(List<BakedQuad> quads) {
Iterator<BakedQuad> quadIterator = quads.iterator();
if (!quadIterator.hasNext()) {
return ITEM_RENDER_TYPE_GETTER;
}
Identifier expectedAtlas = quadIterator.next().sprite().atlasLocation();
while (quadIterator.hasNext()) {
BakedQuad quad = quadIterator.next();
Identifier quadAtlas = quad.sprite().atlasLocation();
if (quadAtlas.equals(expectedAtlas)) continue;
throw new IllegalStateException("Multiple atlases used in model, expected " + String.valueOf(expectedAtlas) + ", but also got " + String.valueOf(quadAtlas));
}
if (expectedAtlas.equals(TextureAtlas.LOCATION_ITEMS)) {
return ITEM_RENDER_TYPE_GETTER;
}
if (expectedAtlas.equals(TextureAtlas.LOCATION_BLOCKS)) {
return BLOCK_RENDER_TYPE_GETTER;
}
throw new IllegalArgumentException("Atlas " + String.valueOf(expectedAtlas) + " can't be usef for item models");
}
private static boolean hasSpecialAnimatedTexture(ItemStack itemStack) {
return itemStack.is(ItemTags.COMPASSES) || itemStack.is(Items.CLOCK);
}
public record Unbaked(Identifier model, List<ItemTintSource> tints) implements ItemModel.Unbaked
{
public static final MapCodec<Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(i -> i.group((App)Identifier.CODEC.fieldOf("model").forGetter(Unbaked::model), (App)ItemTintSources.CODEC.listOf().optionalFieldOf("tints", List.of()).forGetter(Unbaked::tints)).apply((Applicative)i, Unbaked::new));
@Override
public void resolveDependencies(ResolvableModel.Resolver resolver) {
resolver.markDependency(this.model);
}
@Override
public ItemModel bake(ItemModel.BakingContext context) {
ModelBaker baker = context.blockModelBaker();
ResolvedModel resolvedModel = baker.getModel(this.model);
TextureSlots textureSlots = resolvedModel.getTopTextureSlots();
List<BakedQuad> quads = resolvedModel.bakeTopGeometry(textureSlots, baker, BlockModelRotation.IDENTITY).getAll();
ModelRenderProperties properties = ModelRenderProperties.fromResolvedModel(baker, resolvedModel, textureSlots);
Function<ItemStack, RenderType> renderTypeGetter = BlockModelWrapper.detectRenderType(quads);
return new BlockModelWrapper(this.tints, quads, properties, renderTypeGetter);
}
public MapCodec<Unbaked> type() {
return MAP_CODEC;
}
}
}