AvatarRenderer.java

net.minecraft.client.renderer.entity.player.AvatarRenderer

信息

  • 全限定名:net.minecraft.client.renderer.entity.player.AvatarRenderer
  • 类型:public class
  • 包:net.minecraft.client.renderer.entity.player
  • 源码路径:src/main/java/net/minecraft/client/renderer/entity/player/AvatarRenderer.java
  • 起始行号:L51
  • 继承:LivingEntityRenderer<AvatarlikeEntity,AvatarRenderState,PlayerModel>
  • 职责:

    TODO

字段/常量

内部类/嵌套类型

构造器

public AvatarRenderer(EntityRendererProvider.Context context, boolean slimSteve) @ L53

  • 构造器名:AvatarRenderer
  • 源码定位:L53
  • 修饰符:public

参数:

  • context: EntityRendererProvider.Context
  • slimSteve: boolean

说明:

TODO

方法

下面的方法块按源码顺序生成。

protected boolean shouldRenderLayers(AvatarRenderState state) @ L75

  • 方法名:shouldRenderLayers
  • 源码定位:L75
  • 返回类型:boolean
  • 修饰符:protected

参数:

  • state: AvatarRenderState

说明:

TODO

public Vec3 getRenderOffset(AvatarRenderState state) @ L79

  • 方法名:getRenderOffset
  • 源码定位:L79
  • 返回类型:Vec3
  • 修饰符:public

参数:

  • state: AvatarRenderState

说明:

TODO

private static HumanoidModel.ArmPose getArmPose(Avatar avatar, HumanoidArm arm) @ L84

  • 方法名:getArmPose
  • 源码定位:L84
  • 返回类型:HumanoidModel.ArmPose
  • 修饰符:private static

参数:

  • avatar: Avatar
  • arm: HumanoidArm

说明:

TODO

private static HumanoidModel.ArmPose getArmPose(Avatar avatar, ItemStack itemInHand, InteractionHand hand) @ L96

  • 方法名:getArmPose
  • 源码定位:L96
  • 返回类型:HumanoidModel.ArmPose
  • 修饰符:private static

参数:

  • avatar: Avatar
  • itemInHand: ItemStack
  • hand: InteractionHand

说明:

TODO

public Identifier getTextureLocation(AvatarRenderState state) @ L146

  • 方法名:getTextureLocation
  • 源码定位:L146
  • 返回类型:Identifier
  • 修饰符:public

参数:

  • state: AvatarRenderState

说明:

TODO

protected void scale(AvatarRenderState state, PoseStack poseStack) @ L150

  • 方法名:scale
  • 源码定位:L150
  • 返回类型:void
  • 修饰符:protected

参数:

  • state: AvatarRenderState
  • poseStack: PoseStack

说明:

TODO

protected void submitNameDisplay(AvatarRenderState state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera) @ L155

  • 方法名:submitNameDisplay
  • 源码定位:L155
  • 返回类型:void
  • 修饰符:protected

参数:

  • state: AvatarRenderState
  • poseStack: PoseStack
  • submitNodeCollector: SubmitNodeCollector
  • camera: CameraRenderState

说明:

TODO

public AvatarRenderState createRenderState() @ L162

  • 方法名:createRenderState
  • 源码定位:L162
  • 返回类型:AvatarRenderState
  • 修饰符:public

参数:

说明:

TODO

public void extractRenderState(AvatarlikeEntity entity, AvatarRenderState state, float partialTicks) @ L166

  • 方法名:extractRenderState
  • 源码定位:L166
  • 返回类型:void
  • 修饰符:public

参数:

  • entity: AvatarlikeEntity
  • state: AvatarRenderState
  • partialTicks: float

说明:

TODO

protected boolean shouldShowName(AvatarlikeEntity entity, double distanceToCameraSq) @ L197

  • 方法名:shouldShowName
  • 源码定位:L197
  • 返回类型:boolean
  • 修饰符:protected

参数:

  • entity: AvatarlikeEntity
  • distanceToCameraSq: double

说明:

TODO

private void extractFlightData(AvatarlikeEntity entity, AvatarRenderState state, float partialTicks) @ L202

  • 方法名:extractFlightData
  • 源码定位:L202
  • 返回类型:void
  • 修饰符:private

参数:

  • entity: AvatarlikeEntity
  • state: AvatarRenderState
  • partialTicks: float

说明:

TODO

private void extractCapeState(AvatarlikeEntity entity, AvatarRenderState state, float partialTicks) @ L217

  • 方法名:extractCapeState
  • 源码定位:L217
  • 返回类型:void
  • 修饰符:private

参数:

  • entity: AvatarlikeEntity
  • state: AvatarRenderState
  • partialTicks: float

说明:

TODO

public void renderRightHand(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, Identifier skinTexture, boolean hasSleeve) @ L237

  • 方法名:renderRightHand
  • 源码定位:L237
  • 返回类型:void
  • 修饰符:public

参数:

  • poseStack: PoseStack
  • submitNodeCollector: SubmitNodeCollector
  • lightCoords: int
  • skinTexture: Identifier
  • hasSleeve: boolean

说明:

TODO

public void renderLeftHand(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, Identifier skinTexture, boolean hasSleeve) @ L241

  • 方法名:renderLeftHand
  • 源码定位:L241
  • 返回类型:void
  • 修饰符:public

参数:

  • poseStack: PoseStack
  • submitNodeCollector: SubmitNodeCollector
  • lightCoords: int
  • skinTexture: Identifier
  • hasSleeve: boolean

说明:

TODO

private void renderHand(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, Identifier skinTexture, ModelPart arm, boolean hasSleeve) @ L245

  • 方法名:renderHand
  • 源码定位:L245
  • 返回类型:void
  • 修饰符:private

参数:

  • poseStack: PoseStack
  • submitNodeCollector: SubmitNodeCollector
  • lightCoords: int
  • skinTexture: Identifier
  • arm: ModelPart
  • hasSleeve: boolean

说明:

TODO

protected void setupRotations(AvatarRenderState state, PoseStack poseStack, float bodyRot, float entityScale) @ L258

  • 方法名:setupRotations
  • 源码定位:L258
  • 返回类型:void
  • 修饰符:protected

参数:

  • state: AvatarRenderState
  • poseStack: PoseStack
  • bodyRot: float
  • entityScale: float

说明:

TODO

public boolean isEntityUpsideDown(AvatarlikeEntity mob) @ L284

  • 方法名:isEntityUpsideDown
  • 源码定位:L284
  • 返回类型:boolean
  • 修饰符:public

参数:

  • mob: AvatarlikeEntity

说明:

TODO

public static boolean isPlayerUpsideDown(Player player) @ L292

  • 方法名:isPlayerUpsideDown
  • 源码定位:L292
  • 返回类型:boolean
  • 修饰符:public static

参数:

  • player: Player

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class AvatarRenderer<AvatarlikeEntity extends Avatar & ClientAvatarEntity>
    extends LivingEntityRenderer<AvatarlikeEntity, AvatarRenderState, PlayerModel> {
    public AvatarRenderer(EntityRendererProvider.Context context, boolean slimSteve) {
        super(context, new PlayerModel(context.bakeLayer(slimSteve ? ModelLayers.PLAYER_SLIM : ModelLayers.PLAYER), slimSteve), 0.5F);
        this.addLayer(
            new HumanoidArmorLayer<>(
                this,
                ArmorModelSet.bake(
                    slimSteve ? ModelLayers.PLAYER_SLIM_ARMOR : ModelLayers.PLAYER_ARMOR, context.getModelSet(), part -> new PlayerModel(part, slimSteve)
                ),
                context.getEquipmentRenderer()
            )
        );
        this.addLayer(new PlayerItemInHandLayer<>(this));
        this.addLayer(new ArrowLayer<>(this, context));
        this.addLayer(new Deadmau5EarsLayer(this, context.getModelSet()));
        this.addLayer(new CapeLayer(this, context.getModelSet(), context.getEquipmentAssets()));
        this.addLayer(new CustomHeadLayer<>(this, context.getModelSet(), context.getPlayerSkinRenderCache()));
        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(AvatarRenderState state) {
        return !state.isSpectator;
    }
 
    public Vec3 getRenderOffset(AvatarRenderState state) {
        Vec3 offset = super.getRenderOffset(state);
        return state.isCrouching ? offset.add(0.0, state.scale * -2.0F / 16.0, 0.0) : offset;
    }
 
    private static HumanoidModel.ArmPose getArmPose(Avatar avatar, HumanoidArm arm) {
        ItemStack mainHandItem = avatar.getItemInHand(InteractionHand.MAIN_HAND);
        ItemStack offHandItem = avatar.getItemInHand(InteractionHand.OFF_HAND);
        HumanoidModel.ArmPose mainHandPose = getArmPose(avatar, mainHandItem, InteractionHand.MAIN_HAND);
        HumanoidModel.ArmPose offHandPose = getArmPose(avatar, offHandItem, InteractionHand.OFF_HAND);
        if (mainHandPose.isTwoHanded()) {
            offHandPose = offHandItem.isEmpty() ? HumanoidModel.ArmPose.EMPTY : HumanoidModel.ArmPose.ITEM;
        }
 
        return avatar.getMainArm() == arm ? mainHandPose : offHandPose;
    }
 
    private static HumanoidModel.ArmPose getArmPose(Avatar avatar, ItemStack itemInHand, InteractionHand hand) {
        if (itemInHand.isEmpty()) {
            return HumanoidModel.ArmPose.EMPTY;
        } else if (!avatar.swinging && itemInHand.is(Items.CROSSBOW) && CrossbowItem.isCharged(itemInHand)) {
            return HumanoidModel.ArmPose.CROSSBOW_HOLD;
        } else {
            if (avatar.getUsedItemHand() == hand && avatar.getUseItemRemainingTicks() > 0) {
                ItemUseAnimation anim = itemInHand.getUseAnimation();
                if (anim == ItemUseAnimation.BLOCK) {
                    return HumanoidModel.ArmPose.BLOCK;
                }
 
                if (anim == ItemUseAnimation.BOW) {
                    return HumanoidModel.ArmPose.BOW_AND_ARROW;
                }
 
                if (anim == ItemUseAnimation.TRIDENT) {
                    return HumanoidModel.ArmPose.THROW_TRIDENT;
                }
 
                if (anim == ItemUseAnimation.CROSSBOW) {
                    return HumanoidModel.ArmPose.CROSSBOW_CHARGE;
                }
 
                if (anim == ItemUseAnimation.SPYGLASS) {
                    return HumanoidModel.ArmPose.SPYGLASS;
                }
 
                if (anim == ItemUseAnimation.TOOT_HORN) {
                    return HumanoidModel.ArmPose.TOOT_HORN;
                }
 
                if (anim == ItemUseAnimation.BRUSH) {
                    return HumanoidModel.ArmPose.BRUSH;
                }
 
                if (anim == ItemUseAnimation.SPEAR) {
                    return HumanoidModel.ArmPose.SPEAR;
                }
            }
 
            SwingAnimation attack = itemInHand.get(DataComponents.SWING_ANIMATION);
            if (attack != null && attack.type() == SwingAnimationType.STAB && avatar.swinging) {
                return HumanoidModel.ArmPose.SPEAR;
            } else {
                return itemInHand.is(ItemTags.SPEARS) ? HumanoidModel.ArmPose.SPEAR : HumanoidModel.ArmPose.ITEM;
            }
        }
    }
 
    public Identifier getTextureLocation(AvatarRenderState state) {
        return state.skin.body().texturePath();
    }
 
    protected void scale(AvatarRenderState state, PoseStack poseStack) {
        float s = 0.9375F;
        poseStack.scale(0.9375F, 0.9375F, 0.9375F);
    }
 
    protected void submitNameDisplay(AvatarRenderState state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera) {
        poseStack.pushPose();
        int offset = state.showExtraEars ? -10 : 0;
        this.submitNameDisplay(state, poseStack, submitNodeCollector, camera, offset);
        poseStack.popPose();
    }
 
    public AvatarRenderState createRenderState() {
        return new AvatarRenderState();
    }
 
    public void extractRenderState(AvatarlikeEntity entity, AvatarRenderState state, float partialTicks) {
        super.extractRenderState(entity, state, partialTicks);
        HumanoidMobRenderer.extractHumanoidRenderState(entity, state, partialTicks, this.itemModelResolver);
        state.leftArmPose = getArmPose(entity, HumanoidArm.LEFT);
        state.rightArmPose = getArmPose(entity, HumanoidArm.RIGHT);
        state.skin = entity.getSkin();
        state.arrowCount = entity.getArrowCount();
        state.stingerCount = entity.getStingerCount();
        state.isSpectator = entity.isSpectator();
        state.showHat = entity.isModelPartShown(PlayerModelPart.HAT);
        state.showJacket = entity.isModelPartShown(PlayerModelPart.JACKET);
        state.showLeftPants = entity.isModelPartShown(PlayerModelPart.LEFT_PANTS_LEG);
        state.showRightPants = entity.isModelPartShown(PlayerModelPart.RIGHT_PANTS_LEG);
        state.showLeftSleeve = entity.isModelPartShown(PlayerModelPart.LEFT_SLEEVE);
        state.showRightSleeve = entity.isModelPartShown(PlayerModelPart.RIGHT_SLEEVE);
        state.showCape = entity.isModelPartShown(PlayerModelPart.CAPE);
        this.extractFlightData(entity, state, partialTicks);
        this.extractCapeState(entity, state, partialTicks);
        state.parrotOnLeftShoulder = entity.getParrotVariantOnShoulder(true);
        state.parrotOnRightShoulder = entity.getParrotVariantOnShoulder(false);
        state.id = entity.getId();
        state.showExtraEars = entity.showExtraEars();
        state.heldOnHead.clear();
        if (state.isUsingItem) {
            ItemStack useItem = entity.getItemInHand(state.useItemHand);
            if (useItem.is(Items.SPYGLASS)) {
                this.itemModelResolver.updateForLiving(state.heldOnHead, useItem, ItemDisplayContext.HEAD, entity);
            }
        }
    }
 
    protected boolean shouldShowName(AvatarlikeEntity entity, double distanceToCameraSq) {
        return super.shouldShowName(entity, distanceToCameraSq)
            && (entity.shouldShowName() || entity.hasCustomName() && entity == this.entityRenderDispatcher.crosshairPickEntity);
    }
 
    private void extractFlightData(AvatarlikeEntity entity, AvatarRenderState state, float partialTicks) {
        state.fallFlyingTimeInTicks = entity.getFallFlyingTicks() + partialTicks;
        Vec3 lookAngle = entity.getViewVector(partialTicks);
        Vec3 movement = entity.avatarState().deltaMovementOnPreviousTick().lerp(entity.getDeltaMovement(), partialTicks);
        if (movement.horizontalDistanceSqr() > 1.0E-5F && lookAngle.horizontalDistanceSqr() > 1.0E-5F) {
            state.shouldApplyFlyingYRot = true;
            double dot = movement.horizontal().normalize().dot(lookAngle.horizontal().normalize());
            double sign = movement.x * lookAngle.z - movement.z * lookAngle.x;
            state.flyingYRot = (float)(Math.signum(sign) * Math.acos(Math.min(1.0, Math.abs(dot))));
        } else {
            state.shouldApplyFlyingYRot = false;
            state.flyingYRot = 0.0F;
        }
    }
 
    private void extractCapeState(AvatarlikeEntity entity, AvatarRenderState state, float partialTicks) {
        ClientAvatarState clientState = entity.avatarState();
        double deltaX = clientState.getInterpolatedCloakX(partialTicks) - Mth.lerp((double)partialTicks, entity.xo, entity.getX());
        double deltaY = clientState.getInterpolatedCloakY(partialTicks) - Mth.lerp((double)partialTicks, entity.yo, entity.getY());
        double deltaZ = clientState.getInterpolatedCloakZ(partialTicks) - Mth.lerp((double)partialTicks, entity.zo, entity.getZ());
        float yBodyRot = Mth.rotLerp(partialTicks, entity.yBodyRotO, entity.yBodyRot);
        double forwardX = Mth.sin(yBodyRot * (float) (Math.PI / 180.0));
        double forwardZ = -Mth.cos(yBodyRot * (float) (Math.PI / 180.0));
        state.capeFlap = (float)deltaY * 10.0F;
        state.capeFlap = Mth.clamp(state.capeFlap, -6.0F, 32.0F);
        state.capeLean = (float)(deltaX * forwardX + deltaZ * forwardZ) * 100.0F;
        state.capeLean = state.capeLean * (1.0F - state.fallFlyingScale());
        state.capeLean = Mth.clamp(state.capeLean, 0.0F, 150.0F);
        state.capeLean2 = (float)(deltaX * forwardZ - deltaZ * forwardX) * 100.0F;
        state.capeLean2 = Mth.clamp(state.capeLean2, -20.0F, 20.0F);
        float pow = clientState.getInterpolatedBob(partialTicks);
        float walkDistance = clientState.getInterpolatedWalkDistance(partialTicks);
        state.capeFlap = state.capeFlap + Mth.sin(walkDistance * 6.0F) * 32.0F * pow;
    }
 
    public void renderRightHand(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, Identifier skinTexture, boolean hasSleeve) {
        this.renderHand(poseStack, submitNodeCollector, lightCoords, skinTexture, this.model.rightArm, hasSleeve);
    }
 
    public void renderLeftHand(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, Identifier skinTexture, boolean hasSleeve) {
        this.renderHand(poseStack, submitNodeCollector, lightCoords, skinTexture, this.model.leftArm, hasSleeve);
    }
 
    private void renderHand(
        PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, Identifier skinTexture, ModelPart arm, boolean hasSleeve
    ) {
        PlayerModel model = this.getModel();
        arm.resetPose();
        arm.visible = true;
        model.leftSleeve.visible = hasSleeve;
        model.rightSleeve.visible = hasSleeve;
        model.leftArm.zRot = -0.1F;
        model.rightArm.zRot = 0.1F;
        submitNodeCollector.submitModelPart(arm, poseStack, RenderTypes.entityTranslucent(skinTexture), lightCoords, OverlayTexture.NO_OVERLAY, null);
    }
 
    protected void setupRotations(AvatarRenderState state, PoseStack poseStack, float bodyRot, float entityScale) {
        float swimAmount = state.swimAmount;
        float xRot = state.xRot;
        if (state.isFallFlying) {
            super.setupRotations(state, poseStack, bodyRot, entityScale);
            float scale = state.fallFlyingScale();
            if (!state.isAutoSpinAttack) {
                poseStack.mulPose(Axis.XP.rotationDegrees(scale * (-90.0F - xRot)));
            }
 
            if (state.shouldApplyFlyingYRot) {
                poseStack.mulPose(Axis.YP.rotation(state.flyingYRot));
            }
        } else if (swimAmount > 0.0F) {
            super.setupRotations(state, poseStack, bodyRot, entityScale);
            float targetXRot = state.isInWater ? -90.0F - xRot : -90.0F;
            float xAngle = Mth.lerp(swimAmount, 0.0F, targetXRot);
            poseStack.mulPose(Axis.XP.rotationDegrees(xAngle));
            if (state.isVisuallySwimming) {
                poseStack.translate(0.0F, -1.0F, 0.3F);
            }
        } else {
            super.setupRotations(state, poseStack, bodyRot, entityScale);
        }
    }
 
    public boolean isEntityUpsideDown(AvatarlikeEntity mob) {
        if (mob.isModelPartShown(PlayerModelPart.CAPE)) {
            return mob instanceof Player player ? isPlayerUpsideDown(player) : super.isEntityUpsideDown(mob);
        } else {
            return false;
        }
    }
 
    public static boolean isPlayerUpsideDown(Player player) {
        return isUpsideDownName(player.getGameProfile().name());
    }
}

引用的其他类