/* * 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 ITEM_RENDER_TYPE_GETTER = stack -> Sheets.translucentItemSheet(); private static final Function 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 tints; private final List quads; private final Supplier extents; private final ModelRenderProperties properties; private final boolean animated; private final Function renderType; private BlockModelWrapper(List tints, List quads, ModelRenderProperties properties, Function 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 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 detectRenderType(List quads) { Iterator 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 tints) implements ItemModel.Unbaked { public static final MapCodec 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 quads = resolvedModel.bakeTopGeometry(textureSlots, baker, BlockModelRotation.IDENTITY).getAll(); ModelRenderProperties properties = ModelRenderProperties.fromResolvedModel(baker, resolvedModel, textureSlots); Function renderTypeGetter = BlockModelWrapper.detectRenderType(quads); return new BlockModelWrapper(this.tints, quads, properties, renderTypeGetter); } public MapCodec type() { return MAP_CODEC; } } }