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> { 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 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 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); } } }