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

246 lines
11 KiB
Java

package net.minecraft.client.renderer.entity.player;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.model.HumanoidArmorModel;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.renderer.entity.layers.ArrowLayer;
import net.minecraft.client.renderer.entity.layers.BeeStingerLayer;
import net.minecraft.client.renderer.entity.layers.CapeLayer;
import net.minecraft.client.renderer.entity.layers.CustomHeadLayer;
import net.minecraft.client.renderer.entity.layers.Deadmau5EarsLayer;
import net.minecraft.client.renderer.entity.layers.ElytraLayer;
import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer;
import net.minecraft.client.renderer.entity.layers.ParrotOnShoulderLayer;
import net.minecraft.client.renderer.entity.layers.PlayerItemInHandLayer;
import net.minecraft.client.renderer.entity.layers.SpinAttackEffectLayer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.numbers.StyledFormat;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.player.PlayerModelPart;
import net.minecraft.world.item.CrossbowItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.UseAnim;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.DisplaySlot;
import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.ReadOnlyScoreInfo;
import net.minecraft.world.scores.Scoreboard;
@Environment(EnvType.CLIENT)
public class PlayerRenderer extends LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> {
public PlayerRenderer(EntityRendererProvider.Context context, boolean useSlimModel) {
super(context, new PlayerModel<>(context.bakeLayer(useSlimModel ? ModelLayers.PLAYER_SLIM : ModelLayers.PLAYER), useSlimModel), 0.5F);
this.addLayer(
new HumanoidArmorLayer<>(
this,
new HumanoidArmorModel(context.bakeLayer(useSlimModel ? ModelLayers.PLAYER_SLIM_INNER_ARMOR : ModelLayers.PLAYER_INNER_ARMOR)),
new HumanoidArmorModel(context.bakeLayer(useSlimModel ? ModelLayers.PLAYER_SLIM_OUTER_ARMOR : ModelLayers.PLAYER_OUTER_ARMOR)),
context.getModelManager()
)
);
this.addLayer(new PlayerItemInHandLayer<>(this, context.getItemInHandRenderer()));
this.addLayer(new ArrowLayer<>(context, this));
this.addLayer(new Deadmau5EarsLayer(this));
this.addLayer(new CapeLayer(this));
this.addLayer(new CustomHeadLayer<>(this, context.getModelSet(), context.getItemInHandRenderer()));
this.addLayer(new ElytraLayer<>(this, context.getModelSet()));
this.addLayer(new ParrotOnShoulderLayer<>(this, context.getModelSet()));
this.addLayer(new SpinAttackEffectLayer<>(this, context.getModelSet()));
this.addLayer(new BeeStingerLayer<>(this));
}
public void render(AbstractClientPlayer entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int packedLight) {
this.setModelProperties(entity);
super.render(entity, entityYaw, partialTicks, poseStack, buffer, packedLight);
}
public Vec3 getRenderOffset(AbstractClientPlayer entity, float partialTicks) {
return entity.isCrouching() ? new Vec3(0.0, entity.getScale() * -2.0F / 16.0, 0.0) : super.getRenderOffset(entity, partialTicks);
}
private void setModelProperties(AbstractClientPlayer clientPlayer) {
PlayerModel<AbstractClientPlayer> playerModel = this.getModel();
if (clientPlayer.isSpectator()) {
playerModel.setAllVisible(false);
playerModel.head.visible = true;
playerModel.hat.visible = true;
} else {
playerModel.setAllVisible(true);
playerModel.hat.visible = clientPlayer.isModelPartShown(PlayerModelPart.HAT);
playerModel.jacket.visible = clientPlayer.isModelPartShown(PlayerModelPart.JACKET);
playerModel.leftPants.visible = clientPlayer.isModelPartShown(PlayerModelPart.LEFT_PANTS_LEG);
playerModel.rightPants.visible = clientPlayer.isModelPartShown(PlayerModelPart.RIGHT_PANTS_LEG);
playerModel.leftSleeve.visible = clientPlayer.isModelPartShown(PlayerModelPart.LEFT_SLEEVE);
playerModel.rightSleeve.visible = clientPlayer.isModelPartShown(PlayerModelPart.RIGHT_SLEEVE);
playerModel.crouching = clientPlayer.isCrouching();
HumanoidModel.ArmPose armPose = getArmPose(clientPlayer, InteractionHand.MAIN_HAND);
HumanoidModel.ArmPose armPose2 = getArmPose(clientPlayer, InteractionHand.OFF_HAND);
if (armPose.isTwoHanded()) {
armPose2 = clientPlayer.getOffhandItem().isEmpty() ? HumanoidModel.ArmPose.EMPTY : HumanoidModel.ArmPose.ITEM;
}
if (clientPlayer.getMainArm() == HumanoidArm.RIGHT) {
playerModel.rightArmPose = armPose;
playerModel.leftArmPose = armPose2;
} else {
playerModel.rightArmPose = armPose2;
playerModel.leftArmPose = armPose;
}
}
}
private static HumanoidModel.ArmPose getArmPose(AbstractClientPlayer player, InteractionHand hand) {
ItemStack itemStack = player.getItemInHand(hand);
if (itemStack.isEmpty()) {
return HumanoidModel.ArmPose.EMPTY;
} else {
if (player.getUsedItemHand() == hand && player.getUseItemRemainingTicks() > 0) {
UseAnim useAnim = itemStack.getUseAnimation();
if (useAnim == UseAnim.BLOCK) {
return HumanoidModel.ArmPose.BLOCK;
}
if (useAnim == UseAnim.BOW) {
return HumanoidModel.ArmPose.BOW_AND_ARROW;
}
if (useAnim == UseAnim.SPEAR) {
return HumanoidModel.ArmPose.THROW_SPEAR;
}
if (useAnim == UseAnim.CROSSBOW && hand == player.getUsedItemHand()) {
return HumanoidModel.ArmPose.CROSSBOW_CHARGE;
}
if (useAnim == UseAnim.SPYGLASS) {
return HumanoidModel.ArmPose.SPYGLASS;
}
if (useAnim == UseAnim.TOOT_HORN) {
return HumanoidModel.ArmPose.TOOT_HORN;
}
if (useAnim == UseAnim.BRUSH) {
return HumanoidModel.ArmPose.BRUSH;
}
} else if (!player.swinging && itemStack.is(Items.CROSSBOW) && CrossbowItem.isCharged(itemStack)) {
return HumanoidModel.ArmPose.CROSSBOW_HOLD;
}
return HumanoidModel.ArmPose.ITEM;
}
}
/**
* Returns the location of an entity's texture.
*/
public ResourceLocation getTextureLocation(AbstractClientPlayer entity) {
return entity.getSkin().texture();
}
protected void scale(AbstractClientPlayer livingEntity, PoseStack poseStack, float partialTickTime) {
float f = 0.9375F;
poseStack.scale(0.9375F, 0.9375F, 0.9375F);
}
protected void renderNameTag(
AbstractClientPlayer entity, Component displayName, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, float partialTick
) {
double d = this.entityRenderDispatcher.distanceToSqr(entity);
poseStack.pushPose();
if (d < 100.0) {
Scoreboard scoreboard = entity.getScoreboard();
Objective objective = scoreboard.getDisplayObjective(DisplaySlot.BELOW_NAME);
if (objective != null) {
ReadOnlyScoreInfo readOnlyScoreInfo = scoreboard.getPlayerScoreInfo(entity, objective);
Component component = ReadOnlyScoreInfo.safeFormatValue(readOnlyScoreInfo, objective.numberFormatOrDefault(StyledFormat.NO_STYLE));
super.renderNameTag(
entity,
Component.empty().append(component).append(CommonComponents.SPACE).append(objective.getDisplayName()),
poseStack,
bufferSource,
packedLight,
partialTick
);
poseStack.translate(0.0F, 9.0F * 1.15F * 0.025F, 0.0F);
}
}
super.renderNameTag(entity, displayName, poseStack, bufferSource, packedLight, partialTick);
poseStack.popPose();
}
public void renderRightHand(PoseStack poseStack, MultiBufferSource buffer, int combinedLight, AbstractClientPlayer player) {
this.renderHand(poseStack, buffer, combinedLight, player, this.model.rightArm, this.model.rightSleeve);
}
public void renderLeftHand(PoseStack poseStack, MultiBufferSource buffer, int combinedLight, AbstractClientPlayer player) {
this.renderHand(poseStack, buffer, combinedLight, player, this.model.leftArm, this.model.leftSleeve);
}
private void renderHand(
PoseStack poseStack, MultiBufferSource buffer, int combinedLight, AbstractClientPlayer player, ModelPart rendererArm, ModelPart rendererArmwear
) {
PlayerModel<AbstractClientPlayer> playerModel = this.getModel();
this.setModelProperties(player);
playerModel.attackTime = 0.0F;
playerModel.crouching = false;
playerModel.swimAmount = 0.0F;
playerModel.setupAnim(player, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F);
rendererArm.xRot = 0.0F;
ResourceLocation resourceLocation = player.getSkin().texture();
rendererArm.render(poseStack, buffer.getBuffer(RenderType.entitySolid(resourceLocation)), combinedLight, OverlayTexture.NO_OVERLAY);
rendererArmwear.xRot = 0.0F;
rendererArmwear.render(poseStack, buffer.getBuffer(RenderType.entityTranslucent(resourceLocation)), combinedLight, OverlayTexture.NO_OVERLAY);
}
protected void setupRotations(AbstractClientPlayer entity, PoseStack poseStack, float bob, float yBodyRot, float partialTick, float scale) {
float f = entity.getSwimAmount(partialTick);
float g = entity.getViewXRot(partialTick);
if (entity.isFallFlying()) {
super.setupRotations(entity, poseStack, bob, yBodyRot, partialTick, scale);
float h = entity.getFallFlyingTicks() + partialTick;
float i = Mth.clamp(h * h / 100.0F, 0.0F, 1.0F);
if (!entity.isAutoSpinAttack()) {
poseStack.mulPose(Axis.XP.rotationDegrees(i * (-90.0F - g)));
}
Vec3 vec3 = entity.getViewVector(partialTick);
Vec3 vec32 = entity.getDeltaMovementLerped(partialTick);
double d = vec32.horizontalDistanceSqr();
double e = vec3.horizontalDistanceSqr();
if (d > 0.0 && e > 0.0) {
double j = (vec32.x * vec3.x + vec32.z * vec3.z) / Math.sqrt(d * e);
double k = vec32.x * vec3.z - vec32.z * vec3.x;
poseStack.mulPose(Axis.YP.rotation((float)(Math.signum(k) * Math.acos(j))));
}
} else if (f > 0.0F) {
super.setupRotations(entity, poseStack, bob, yBodyRot, partialTick, scale);
float hx = entity.isInWater() ? -90.0F - g : -90.0F;
float ix = Mth.lerp(f, 0.0F, hx);
poseStack.mulPose(Axis.XP.rotationDegrees(ix));
if (entity.isVisuallySwimming()) {
poseStack.translate(0.0F, -1.0F, 0.3F);
}
} else {
super.setupRotations(entity, poseStack, bob, yBodyRot, partialTick, scale);
}
}
}