minecraft-src/net/minecraft/client/renderer/entity/layers/CustomHeadLayer.java
2025-07-04 01:41:11 +03:00

121 lines
4.8 KiB
Java

package net.minecraft.client.renderer.entity.layers;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import java.util.Map;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.HeadedModel;
import net.minecraft.client.model.SkullModelBase;
import net.minecraft.client.model.geom.EntityModelSet;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.SkullBlockRenderer;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.WalkAnimationState;
import net.minecraft.world.entity.monster.ZombieVillager;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.item.ArmorItem;
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.component.ResolvableProfile;
import net.minecraft.world.level.block.AbstractSkullBlock;
import net.minecraft.world.level.block.SkullBlock;
@Environment(EnvType.CLIENT)
public class CustomHeadLayer<T extends LivingEntity, M extends EntityModel<T> & HeadedModel> extends RenderLayer<T, M> {
private final float scaleX;
private final float scaleY;
private final float scaleZ;
private final Map<SkullBlock.Type, SkullModelBase> skullModels;
private final ItemInHandRenderer itemInHandRenderer;
public CustomHeadLayer(RenderLayerParent<T, M> renderer, EntityModelSet modelSet, ItemInHandRenderer itemInHandRenderer) {
this(renderer, modelSet, 1.0F, 1.0F, 1.0F, itemInHandRenderer);
}
public CustomHeadLayer(
RenderLayerParent<T, M> renderer, EntityModelSet modelSet, float scaleX, float scaleY, float scaleZ, ItemInHandRenderer itemInHandRenderer
) {
super(renderer);
this.scaleX = scaleX;
this.scaleY = scaleY;
this.scaleZ = scaleZ;
this.skullModels = SkullBlockRenderer.createSkullRenderers(modelSet);
this.itemInHandRenderer = itemInHandRenderer;
}
public void render(
PoseStack poseStack,
MultiBufferSource buffer,
int packedLight,
T livingEntity,
float limbSwing,
float limbSwingAmount,
float partialTicks,
float ageInTicks,
float netHeadYaw,
float headPitch
) {
ItemStack itemStack = livingEntity.getItemBySlot(EquipmentSlot.HEAD);
if (!itemStack.isEmpty()) {
Item item = itemStack.getItem();
poseStack.pushPose();
poseStack.scale(this.scaleX, this.scaleY, this.scaleZ);
boolean bl = livingEntity instanceof Villager || livingEntity instanceof ZombieVillager;
if (livingEntity.isBaby() && !(livingEntity instanceof Villager)) {
float f = 2.0F;
float g = 1.4F;
poseStack.translate(0.0F, 0.03125F, 0.0F);
poseStack.scale(0.7F, 0.7F, 0.7F);
poseStack.translate(0.0F, 1.0F, 0.0F);
}
this.getParentModel().getHead().translateAndRotate(poseStack);
if (item instanceof BlockItem && ((BlockItem)item).getBlock() instanceof AbstractSkullBlock) {
float g = 1.1875F;
poseStack.scale(1.1875F, -1.1875F, -1.1875F);
if (bl) {
poseStack.translate(0.0F, 0.0625F, 0.0F);
}
ResolvableProfile resolvableProfile = itemStack.get(DataComponents.PROFILE);
poseStack.translate(-0.5, 0.0, -0.5);
SkullBlock.Type type = ((AbstractSkullBlock)((BlockItem)item).getBlock()).getType();
SkullModelBase skullModelBase = (SkullModelBase)this.skullModels.get(type);
RenderType renderType = SkullBlockRenderer.getRenderType(type, resolvableProfile);
WalkAnimationState walkAnimationState;
if (livingEntity.getVehicle() instanceof LivingEntity livingEntity2) {
walkAnimationState = livingEntity2.walkAnimation;
} else {
walkAnimationState = livingEntity.walkAnimation;
}
float h = walkAnimationState.position(partialTicks);
SkullBlockRenderer.renderSkull(null, 180.0F, h, poseStack, buffer, packedLight, skullModelBase, renderType);
} else if (!(item instanceof ArmorItem armorItem && armorItem.getEquipmentSlot() == EquipmentSlot.HEAD)) {
translateToHead(poseStack, bl);
this.itemInHandRenderer.renderItem(livingEntity, itemStack, ItemDisplayContext.HEAD, false, poseStack, buffer, packedLight);
}
poseStack.popPose();
}
}
public static void translateToHead(PoseStack poseStack, boolean isVillager) {
float f = 0.625F;
poseStack.translate(0.0F, -0.25F, 0.0F);
poseStack.mulPose(Axis.YP.rotationDegrees(180.0F));
poseStack.scale(0.625F, -0.625F, -0.625F);
if (isVillager) {
poseStack.translate(0.0F, 0.1875F, 0.0F);
}
}
}