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.function.Function; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ARGB; import net.minecraft.util.Mth; @Environment(EnvType.CLIENT) public class LivingEntityEmissiveLayer> extends RenderLayer { private final ResourceLocation texture; private final LivingEntityEmissiveLayer.AlphaFunction alphaFunction; private final LivingEntityEmissiveLayer.DrawSelector drawSelector; private final Function bufferProvider; private final boolean alwaysVisible; public LivingEntityEmissiveLayer( RenderLayerParent renderer, ResourceLocation texture, LivingEntityEmissiveLayer.AlphaFunction alphaFunction, LivingEntityEmissiveLayer.DrawSelector drawSelector, Function bufferProvider, boolean alwaysVisible ) { super(renderer); this.texture = texture; this.alphaFunction = alphaFunction; this.drawSelector = drawSelector; this.bufferProvider = bufferProvider; this.alwaysVisible = alwaysVisible; } public void render(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, S livingEntityRenderState, float f, float g) { if (!livingEntityRenderState.isInvisible || this.alwaysVisible) { if (this.onlyDrawSelectedParts(livingEntityRenderState)) { VertexConsumer vertexConsumer = multiBufferSource.getBuffer((RenderType)this.bufferProvider.apply(this.texture)); float h = this.alphaFunction.apply(livingEntityRenderState, livingEntityRenderState.ageInTicks); int j = ARGB.color(Mth.floor(h * 255.0F), 255, 255, 255); this.getParentModel().renderToBuffer(poseStack, vertexConsumer, i, LivingEntityRenderer.getOverlayCoords(livingEntityRenderState, 0.0F), j); this.resetDrawForAllParts(); } } } private boolean onlyDrawSelectedParts(S renderState) { List list = this.drawSelector.getPartsToDraw(this.getParentModel(), renderState); if (list.isEmpty()) { return false; } else { this.getParentModel().allParts().forEach(modelPart -> modelPart.skipDraw = true); list.forEach(modelPart -> modelPart.skipDraw = false); return true; } } private void resetDrawForAllParts() { this.getParentModel().allParts().forEach(modelPart -> modelPart.skipDraw = false); } @Environment(EnvType.CLIENT) public interface AlphaFunction { float apply(S livingEntityRenderState, float f); } @Environment(EnvType.CLIENT) public interface DrawSelector> { List getPartsToDraw(M entityModel, S livingEntityRenderState); } }