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; public LivingEntityEmissiveLayer( RenderLayerParent renderer, ResourceLocation texture, LivingEntityEmissiveLayer.AlphaFunction alphaFunction, LivingEntityEmissiveLayer.DrawSelector drawSelector, Function bufferProvider ) { super(renderer); this.texture = texture; this.alphaFunction = alphaFunction; this.drawSelector = drawSelector; this.bufferProvider = bufferProvider; } public void render(PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, S renderState, float yRot, float xRot) { if (!renderState.isInvisible) { if (this.onlyDrawSelectedParts(renderState)) { VertexConsumer vertexConsumer = bufferSource.getBuffer((RenderType)this.bufferProvider.apply(this.texture)); float f = this.alphaFunction.apply(renderState, renderState.ageInTicks); int i = ARGB.color(Mth.floor(f * 255.0F), 255, 255, 255); this.getParentModel().renderToBuffer(poseStack, vertexConsumer, packedLight, LivingEntityRenderer.getOverlayCoords(renderState, 0.0F), i); 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); } }