package net.minecraft.client.renderer.entity.layers; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import java.util.List; import java.util.Optional; import java.util.function.Function; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.Util; import net.minecraft.client.model.Model; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.EquipmentAssetManager; import net.minecraft.client.resources.model.EquipmentClientInfo; import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ARGB; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.DyedItemColor; import net.minecraft.world.item.equipment.EquipmentAsset; import net.minecraft.world.item.equipment.trim.ArmorTrim; import org.jetbrains.annotations.Nullable; @Environment(EnvType.CLIENT) public class EquipmentLayerRenderer { private static final int NO_LAYER_COLOR = 0; private final EquipmentAssetManager equipmentAssets; private final Function layerTextureLookup; private final Function trimSpriteLookup; public EquipmentLayerRenderer(EquipmentAssetManager equipmentAssets, TextureAtlas atlas) { this.equipmentAssets = equipmentAssets; this.layerTextureLookup = Util.memoize( (Function)(layerTextureKey -> layerTextureKey.layer.getTextureLocation(layerTextureKey.layerType)) ); this.trimSpriteLookup = Util.memoize( (Function)(trimSpriteKey -> atlas.getSprite(trimSpriteKey.spriteId())) ); } public void renderLayers( EquipmentClientInfo.LayerType layerType, ResourceKey equipmentAsset, Model armorModel, ItemStack item, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight ) { this.renderLayers(layerType, equipmentAsset, armorModel, item, poseStack, bufferSource, packedLight, null); } public void renderLayers( EquipmentClientInfo.LayerType layerType, ResourceKey equipmentAsset, Model armorModel, ItemStack item, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, @Nullable ResourceLocation playerTexture ) { List list = this.equipmentAssets.get(equipmentAsset).getLayers(layerType); if (!list.isEmpty()) { int i = DyedItemColor.getOrDefault(item, 0); boolean bl = item.hasFoil(); for (EquipmentClientInfo.Layer layer : list) { int j = getColorForLayer(layer, i); if (j != 0) { ResourceLocation resourceLocation = layer.usePlayerTexture() && playerTexture != null ? playerTexture : (ResourceLocation)this.layerTextureLookup.apply(new EquipmentLayerRenderer.LayerTextureKey(layerType, layer)); VertexConsumer vertexConsumer = ItemRenderer.getArmorFoilBuffer(bufferSource, RenderType.armorCutoutNoCull(resourceLocation), bl); armorModel.renderToBuffer(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, j); bl = false; } } ArmorTrim armorTrim = item.get(DataComponents.TRIM); if (armorTrim != null) { TextureAtlasSprite textureAtlasSprite = (TextureAtlasSprite)this.trimSpriteLookup .apply(new EquipmentLayerRenderer.TrimSpriteKey(armorTrim, layerType, equipmentAsset)); VertexConsumer vertexConsumer2 = textureAtlasSprite.wrap(bufferSource.getBuffer(Sheets.armorTrimsSheet(armorTrim.pattern().value().decal()))); armorModel.renderToBuffer(poseStack, vertexConsumer2, packedLight, OverlayTexture.NO_OVERLAY); } } } private static int getColorForLayer(EquipmentClientInfo.Layer layer, int color) { Optional optional = layer.dyeable(); if (optional.isPresent()) { int i = (Integer)((EquipmentClientInfo.Dyeable)optional.get()).colorWhenUndyed().map(ARGB::opaque).orElse(0); return color != 0 ? color : i; } else { return -1; } } @Environment(EnvType.CLIENT) record LayerTextureKey(EquipmentClientInfo.LayerType layerType, EquipmentClientInfo.Layer layer) { } @Environment(EnvType.CLIENT) record TrimSpriteKey(ArmorTrim trim, EquipmentClientInfo.LayerType layerType, ResourceKey equipmentAssetId) { public ResourceLocation spriteId() { return this.trim.layerAssetId(this.layerType.trimAssetPrefix(), this.equipmentAssetId); } } }