297 lines
15 KiB
Java
297 lines
15 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.HumanoidMobRenderer;
|
|
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.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.entity.layers.WingsLayer;
|
|
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
|
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
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.EntityType;
|
|
import net.minecraft.world.entity.HumanoidArm;
|
|
import net.minecraft.world.entity.animal.Parrot;
|
|
import net.minecraft.world.entity.player.PlayerModelPart;
|
|
import net.minecraft.world.item.CrossbowItem;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.ItemUseAnimation;
|
|
import net.minecraft.world.item.Items;
|
|
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;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class PlayerRenderer extends LivingEntityRenderer<AbstractClientPlayer, PlayerRenderState, PlayerModel> {
|
|
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.getEquipmentRenderer()
|
|
)
|
|
);
|
|
this.addLayer(new PlayerItemInHandLayer<>(this, context.getItemRenderer()));
|
|
this.addLayer(new ArrowLayer<>(this, context));
|
|
this.addLayer(new Deadmau5EarsLayer(this, context.getModelSet()));
|
|
this.addLayer(new CapeLayer(this, context.getModelSet(), context.getEquipmentModels()));
|
|
this.addLayer(new CustomHeadLayer<>(this, context.getModelSet(), context.getItemRenderer()));
|
|
this.addLayer(new WingsLayer<>(this, context.getModelSet(), context.getEquipmentRenderer()));
|
|
this.addLayer(new ParrotOnShoulderLayer(this, context.getModelSet()));
|
|
this.addLayer(new SpinAttackEffectLayer(this, context.getModelSet()));
|
|
this.addLayer(new BeeStingerLayer<>(this, context));
|
|
}
|
|
|
|
protected boolean shouldRenderLayers(PlayerRenderState playerRenderState) {
|
|
return !playerRenderState.isSpectator;
|
|
}
|
|
|
|
public Vec3 getRenderOffset(PlayerRenderState playerRenderState) {
|
|
Vec3 vec3 = super.getRenderOffset(playerRenderState);
|
|
return playerRenderState.isCrouching ? vec3.add(0.0, playerRenderState.scale * -2.0F / 16.0, 0.0) : vec3;
|
|
}
|
|
|
|
public static HumanoidModel.ArmPose getArmPose(PlayerRenderState playerRenderState, HumanoidArm humanoidArm) {
|
|
HumanoidModel.ArmPose armPose = getArmPose(playerRenderState, playerRenderState.mainHandState, InteractionHand.MAIN_HAND);
|
|
HumanoidModel.ArmPose armPose2 = getArmPose(playerRenderState, playerRenderState.offhandState, InteractionHand.OFF_HAND);
|
|
if (armPose.isTwoHanded()) {
|
|
armPose2 = playerRenderState.offhandState.isEmpty ? HumanoidModel.ArmPose.EMPTY : HumanoidModel.ArmPose.ITEM;
|
|
}
|
|
|
|
return playerRenderState.mainArm == humanoidArm ? armPose : armPose2;
|
|
}
|
|
|
|
private static HumanoidModel.ArmPose getArmPose(PlayerRenderState playerRenderState, PlayerRenderState.HandState handState, InteractionHand interactionHand) {
|
|
if (handState.isEmpty) {
|
|
return HumanoidModel.ArmPose.EMPTY;
|
|
} else {
|
|
if (playerRenderState.useItemHand == interactionHand && playerRenderState.useItemRemainingTicks > 0) {
|
|
ItemUseAnimation itemUseAnimation = handState.useAnimation;
|
|
if (itemUseAnimation == ItemUseAnimation.BLOCK) {
|
|
return HumanoidModel.ArmPose.BLOCK;
|
|
}
|
|
|
|
if (itemUseAnimation == ItemUseAnimation.BOW) {
|
|
return HumanoidModel.ArmPose.BOW_AND_ARROW;
|
|
}
|
|
|
|
if (itemUseAnimation == ItemUseAnimation.SPEAR) {
|
|
return HumanoidModel.ArmPose.THROW_SPEAR;
|
|
}
|
|
|
|
if (itemUseAnimation == ItemUseAnimation.CROSSBOW) {
|
|
return HumanoidModel.ArmPose.CROSSBOW_CHARGE;
|
|
}
|
|
|
|
if (itemUseAnimation == ItemUseAnimation.SPYGLASS) {
|
|
return HumanoidModel.ArmPose.SPYGLASS;
|
|
}
|
|
|
|
if (itemUseAnimation == ItemUseAnimation.TOOT_HORN) {
|
|
return HumanoidModel.ArmPose.TOOT_HORN;
|
|
}
|
|
|
|
if (itemUseAnimation == ItemUseAnimation.BRUSH) {
|
|
return HumanoidModel.ArmPose.BRUSH;
|
|
}
|
|
} else if (!playerRenderState.swinging && handState.holdsChargedCrossbow) {
|
|
return HumanoidModel.ArmPose.CROSSBOW_HOLD;
|
|
}
|
|
|
|
return HumanoidModel.ArmPose.ITEM;
|
|
}
|
|
}
|
|
|
|
public ResourceLocation getTextureLocation(PlayerRenderState playerRenderState) {
|
|
return playerRenderState.skin.texture();
|
|
}
|
|
|
|
protected void scale(PlayerRenderState playerRenderState, PoseStack poseStack) {
|
|
float f = 0.9375F;
|
|
poseStack.scale(0.9375F, 0.9375F, 0.9375F);
|
|
}
|
|
|
|
protected void renderNameTag(PlayerRenderState playerRenderState, Component component, PoseStack poseStack, MultiBufferSource multiBufferSource, int i) {
|
|
poseStack.pushPose();
|
|
if (playerRenderState.scoreText != null) {
|
|
super.renderNameTag(playerRenderState, playerRenderState.scoreText, poseStack, multiBufferSource, i);
|
|
poseStack.translate(0.0F, 9.0F * 1.15F * 0.025F, 0.0F);
|
|
}
|
|
|
|
super.renderNameTag(playerRenderState, component, poseStack, multiBufferSource, i);
|
|
poseStack.popPose();
|
|
}
|
|
|
|
public PlayerRenderState createRenderState() {
|
|
return new PlayerRenderState();
|
|
}
|
|
|
|
public void extractRenderState(AbstractClientPlayer abstractClientPlayer, PlayerRenderState playerRenderState, float f) {
|
|
super.extractRenderState(abstractClientPlayer, playerRenderState, f);
|
|
HumanoidMobRenderer.extractHumanoidRenderState(abstractClientPlayer, playerRenderState, f);
|
|
playerRenderState.skin = abstractClientPlayer.getSkin();
|
|
playerRenderState.arrowCount = abstractClientPlayer.getArrowCount();
|
|
playerRenderState.stingerCount = abstractClientPlayer.getStingerCount();
|
|
playerRenderState.useItemRemainingTicks = abstractClientPlayer.getUseItemRemainingTicks();
|
|
playerRenderState.swinging = abstractClientPlayer.swinging;
|
|
playerRenderState.isSpectator = abstractClientPlayer.isSpectator();
|
|
playerRenderState.showHat = abstractClientPlayer.isModelPartShown(PlayerModelPart.HAT);
|
|
playerRenderState.showJacket = abstractClientPlayer.isModelPartShown(PlayerModelPart.JACKET);
|
|
playerRenderState.showLeftPants = abstractClientPlayer.isModelPartShown(PlayerModelPart.LEFT_PANTS_LEG);
|
|
playerRenderState.showRightPants = abstractClientPlayer.isModelPartShown(PlayerModelPart.RIGHT_PANTS_LEG);
|
|
playerRenderState.showLeftSleeve = abstractClientPlayer.isModelPartShown(PlayerModelPart.LEFT_SLEEVE);
|
|
playerRenderState.showRightSleeve = abstractClientPlayer.isModelPartShown(PlayerModelPart.RIGHT_SLEEVE);
|
|
playerRenderState.showCape = abstractClientPlayer.isModelPartShown(PlayerModelPart.CAPE);
|
|
extractFlightData(abstractClientPlayer, playerRenderState, f);
|
|
this.extractHandState(abstractClientPlayer, playerRenderState.mainHandState, InteractionHand.MAIN_HAND);
|
|
this.extractHandState(abstractClientPlayer, playerRenderState.offhandState, InteractionHand.OFF_HAND);
|
|
extractCapeState(abstractClientPlayer, playerRenderState, f);
|
|
if (playerRenderState.distanceToCameraSq < 100.0) {
|
|
Scoreboard scoreboard = abstractClientPlayer.getScoreboard();
|
|
Objective objective = scoreboard.getDisplayObjective(DisplaySlot.BELOW_NAME);
|
|
if (objective != null) {
|
|
ReadOnlyScoreInfo readOnlyScoreInfo = scoreboard.getPlayerScoreInfo(abstractClientPlayer, objective);
|
|
Component component = ReadOnlyScoreInfo.safeFormatValue(readOnlyScoreInfo, objective.numberFormatOrDefault(StyledFormat.NO_STYLE));
|
|
playerRenderState.scoreText = Component.empty().append(component).append(CommonComponents.SPACE).append(objective.getDisplayName());
|
|
} else {
|
|
playerRenderState.scoreText = null;
|
|
}
|
|
} else {
|
|
playerRenderState.scoreText = null;
|
|
}
|
|
|
|
playerRenderState.parrotOnLeftShoulder = getParrotOnShoulder(abstractClientPlayer, true);
|
|
playerRenderState.parrotOnRightShoulder = getParrotOnShoulder(abstractClientPlayer, false);
|
|
playerRenderState.id = abstractClientPlayer.getId();
|
|
playerRenderState.name = abstractClientPlayer.getGameProfile().getName();
|
|
}
|
|
|
|
private static void extractFlightData(AbstractClientPlayer abstractClientPlayer, PlayerRenderState playerRenderState, float f) {
|
|
playerRenderState.fallFlyingTimeInTicks = abstractClientPlayer.getFallFlyingTicks() + f;
|
|
Vec3 vec3 = abstractClientPlayer.getViewVector(f);
|
|
Vec3 vec32 = abstractClientPlayer.getDeltaMovementLerped(f);
|
|
double d = vec32.horizontalDistanceSqr();
|
|
double e = vec3.horizontalDistanceSqr();
|
|
if (d > 0.0 && e > 0.0) {
|
|
playerRenderState.shouldApplyFlyingYRot = true;
|
|
double g = (vec32.x * vec3.x + vec32.z * vec3.z) / Math.sqrt(d * e);
|
|
double h = vec32.x * vec3.z - vec32.z * vec3.x;
|
|
playerRenderState.flyingYRot = (float)(Math.signum(h) * Math.acos(g));
|
|
} else {
|
|
playerRenderState.shouldApplyFlyingYRot = false;
|
|
playerRenderState.flyingYRot = 0.0F;
|
|
}
|
|
}
|
|
|
|
private void extractHandState(AbstractClientPlayer abstractClientPlayer, PlayerRenderState.HandState handState, InteractionHand interactionHand) {
|
|
ItemStack itemStack = abstractClientPlayer.getItemInHand(interactionHand);
|
|
handState.isEmpty = itemStack.isEmpty();
|
|
handState.useAnimation = !itemStack.isEmpty() ? itemStack.getUseAnimation() : null;
|
|
handState.holdsChargedCrossbow = itemStack.is(Items.CROSSBOW) && CrossbowItem.isCharged(itemStack);
|
|
}
|
|
|
|
private static void extractCapeState(AbstractClientPlayer abstractClientPlayer, PlayerRenderState playerRenderState, float f) {
|
|
double d = Mth.lerp((double)f, abstractClientPlayer.xCloakO, abstractClientPlayer.xCloak)
|
|
- Mth.lerp((double)f, abstractClientPlayer.xo, abstractClientPlayer.getX());
|
|
double e = Mth.lerp((double)f, abstractClientPlayer.yCloakO, abstractClientPlayer.yCloak)
|
|
- Mth.lerp((double)f, abstractClientPlayer.yo, abstractClientPlayer.getY());
|
|
double g = Mth.lerp((double)f, abstractClientPlayer.zCloakO, abstractClientPlayer.zCloak)
|
|
- Mth.lerp((double)f, abstractClientPlayer.zo, abstractClientPlayer.getZ());
|
|
float h = Mth.rotLerp(f, abstractClientPlayer.yBodyRotO, abstractClientPlayer.yBodyRot);
|
|
double i = Mth.sin(h * (float) (Math.PI / 180.0));
|
|
double j = -Mth.cos(h * (float) (Math.PI / 180.0));
|
|
playerRenderState.capeFlap = (float)e * 10.0F;
|
|
playerRenderState.capeFlap = Mth.clamp(playerRenderState.capeFlap, -6.0F, 32.0F);
|
|
playerRenderState.capeLean = (float)(d * i + g * j) * 100.0F;
|
|
playerRenderState.capeLean = playerRenderState.capeLean * (1.0F - playerRenderState.fallFlyingScale());
|
|
playerRenderState.capeLean = Mth.clamp(playerRenderState.capeLean, 0.0F, 150.0F);
|
|
playerRenderState.capeLean2 = (float)(d * j - g * i) * 100.0F;
|
|
playerRenderState.capeLean2 = Mth.clamp(playerRenderState.capeLean2, -20.0F, 20.0F);
|
|
float k = Mth.lerp(f, abstractClientPlayer.oBob, abstractClientPlayer.bob);
|
|
float l = Mth.lerp(f, abstractClientPlayer.walkDistO, abstractClientPlayer.walkDist);
|
|
playerRenderState.capeFlap = playerRenderState.capeFlap + Mth.sin(l * 6.0F) * 32.0F * k;
|
|
}
|
|
|
|
@Nullable
|
|
private static Parrot.Variant getParrotOnShoulder(AbstractClientPlayer abstractClientPlayer, boolean bl) {
|
|
CompoundTag compoundTag = bl ? abstractClientPlayer.getShoulderEntityLeft() : abstractClientPlayer.getShoulderEntityRight();
|
|
return EntityType.byString(compoundTag.getString("id")).filter(entityType -> entityType == EntityType.PARROT).isPresent()
|
|
? Parrot.Variant.byId(compoundTag.getInt("Variant"))
|
|
: null;
|
|
}
|
|
|
|
public void renderRightHand(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, ResourceLocation resourceLocation, boolean bl) {
|
|
this.renderHand(poseStack, multiBufferSource, i, resourceLocation, this.model.rightArm, bl);
|
|
}
|
|
|
|
public void renderLeftHand(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, ResourceLocation resourceLocation, boolean bl) {
|
|
this.renderHand(poseStack, multiBufferSource, i, resourceLocation, this.model.leftArm, bl);
|
|
}
|
|
|
|
private void renderHand(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, ResourceLocation resourceLocation, ModelPart modelPart, boolean bl) {
|
|
PlayerModel playerModel = this.getModel();
|
|
modelPart.resetPose();
|
|
modelPart.visible = true;
|
|
playerModel.leftSleeve.visible = bl;
|
|
playerModel.rightSleeve.visible = bl;
|
|
playerModel.leftArm.zRot = -0.1F;
|
|
playerModel.rightArm.zRot = 0.1F;
|
|
modelPart.render(poseStack, multiBufferSource.getBuffer(RenderType.entityTranslucent(resourceLocation)), i, OverlayTexture.NO_OVERLAY);
|
|
}
|
|
|
|
protected void setupRotations(PlayerRenderState playerRenderState, PoseStack poseStack, float f, float g) {
|
|
float h = playerRenderState.swimAmount;
|
|
float i = playerRenderState.xRot;
|
|
if (playerRenderState.isFallFlying) {
|
|
super.setupRotations(playerRenderState, poseStack, f, g);
|
|
float j = playerRenderState.fallFlyingScale();
|
|
if (!playerRenderState.isAutoSpinAttack) {
|
|
poseStack.mulPose(Axis.XP.rotationDegrees(j * (-90.0F - i)));
|
|
}
|
|
|
|
if (playerRenderState.shouldApplyFlyingYRot) {
|
|
poseStack.mulPose(Axis.YP.rotation(playerRenderState.flyingYRot));
|
|
}
|
|
} else if (h > 0.0F) {
|
|
super.setupRotations(playerRenderState, poseStack, f, g);
|
|
float jx = playerRenderState.isInWater ? -90.0F - i : -90.0F;
|
|
float k = Mth.lerp(h, 0.0F, jx);
|
|
poseStack.mulPose(Axis.XP.rotationDegrees(k));
|
|
if (playerRenderState.isVisuallySwimming) {
|
|
poseStack.translate(0.0F, -1.0F, 0.3F);
|
|
}
|
|
} else {
|
|
super.setupRotations(playerRenderState, poseStack, f, g);
|
|
}
|
|
}
|
|
}
|