playerAnimator

playerAnimator

28M Downloads

[API] Bug Report: replaceAnimationWithFade() does not update FirstPersonConfiguration correctly

RazorPlay01 opened this issue ยท 3 comments

commented

Bug Report: replaceAnimationWithFade() does not update FirstPersonConfiguration correctly

Describe the bug

The replaceAnimationWithFade() method does not seem to correctly update the FirstPersonConfiguration object of the AnimationContainer.

The goal of my implementation is to render one or both of the player's arms depending on the action they are performing, ensuring that the player's main arm is always visible. For example:

  • If the player is holding a sword in their main hand, only that arm should be visible.
  • If they are also holding a shield in their secondary hand, both arms should be visible until the items are unequipped.

The problem is that while the conditions to detect changes in the player's items and actions are executed successfully, the secondary arm is not rendered until the player interacts with an item (e.g., eats an apple), which forces the renderer to update.


To Reproduce

  1. Implement the following method to handle the animation and arm visibility logic:

    @Unique
    private void playCurrentAnimation(boolean condition, ModifierLayer<IAnimation> animationContainer, KeyframeAnimation animation) {
        System.out.println("Pre Load Anim: " + animationContainer.getFirstPersonConfiguration(0));
        if (condition) {
            animationContainer.replaceAnimationWithFade(AbstractFadeModifier.standardFadeIn(fadeTime, INOUTSINE),
                    new KeyframeAnimationPlayer(animation)
                            .setFirstPersonMode(FirstPersonMode.THIRD_PERSON_MODEL)
                            .setFirstPersonConfiguration(new FirstPersonConfiguration(true, true, true, true)), true);
            System.out.println("Set all visible");
        } else {
            animationContainer.replaceAnimationWithFade(AbstractFadeModifier.standardFadeIn(fadeTime, INOUTSINE),
                    new KeyframeAnimationPlayer(animation)
                            .setFirstPersonMode(FirstPersonMode.THIRD_PERSON_MODEL)
                            .setFirstPersonConfiguration(new FirstPersonConfiguration(true, false, true, false)), true);
            System.out.println("Set left parts not visible");
        }
        System.out.println("Pos Load Anim: " + animationContainer.getFirstPersonConfiguration(0));
    }
  2. Observe the log results for different conditions:

    • Condition false:

      [19:52:24] [Render thread/INFO] (Minecraft) [STDOUT]: Pre Load Anim: FirstPersonConfiguration(showRightArm=true, showLeftArm=false, showRightItem=true, showLeftItem=false)
      [19:52:24] [Render thread/INFO] (Minecraft) [STDOUT]: Set left parts not visible
      [19:52:24] [Render thread/INFO] (Minecraft) [STDOUT]: Pos Load Anim: FirstPersonConfiguration(showRightArm=true, showLeftArm=false, showRightItem=true, showLeftItem=false)
      
    • Condition true:

      [19:52:25] [Render thread/INFO] (Minecraft) [STDOUT]: Pre Load Anim: FirstPersonConfiguration(showRightArm=true, showLeftArm=false, showRightItem=true, showLeftItem=false)
      [19:52:25] [Render thread/INFO] (Minecraft) [STDOUT]: Set all visible
      [19:52:25] [Render thread/INFO] (Minecraft) [STDOUT]: Pos Load Anim: FirstPersonConfiguration(showRightArm=true, showLeftArm=true, showRightItem=true, showLeftItem=true)
      
  3. Notice that while the log shows FirstPersonConfiguration being updated correctly, the changes are not visually reflected until the player interacts with an item that forces the renderer to update.


Expected behavior

Depending on the condition passed to the method, one or both of the player's arms should be displayed without requiring additional interaction.


Screenshots or Videos

Video of the issue
Pd: the video was made with the option to show the secondary hand item on true.


Setup

  • Minecraft version: 1.21.1
  • Mod loader: Fabric 0.16.5
  • PlayerAnimator Library version: 2.0.0-alpha1+1.21

Other mods

The issue is not caused by mod incompatibility, as the problem persists even when PlayerAnimator is the only mod installed.


Technical details

I have debugged the mixin used by PlayerAnimator to render the player's arms. The relevant mixin code is as follows:

@Inject(method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
        at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V"))
private void hideBonesInFirstPerson(AbstractClientPlayer entity,
                                    float f, float g, PoseStack matrixStack,
                                    MultiBufferSource vertexConsumerProvider,
                                    int i, CallbackInfo ci) {
    if (FirstPersonMode.isFirstPersonPass()) {
        var animationApplier = ((IAnimatedPlayer) entity).playerAnimator_getAnimation();
        var config = animationApplier.getFirstPersonConfiguration();

        if (entity == Minecraft.getInstance().getCameraEntity()) {
            // Hiding all parts, because they should not be visible in first person
            setAllPartsVisible(false);
            // Showing arms based on configuration
            var showRightArm = config.isShowRightArm();
            var showLeftArm = config.isShowLeftArm();
            this.model.rightArm.visible = showRightArm;
            this.model.rightSleeve.visible = showRightArm;
            this.model.leftArm.visible = showLeftArm;
            this.model.leftSleeve.visible = showLeftArm;
        }
    }

    // No `else` case needed to show parts, since the default state should be correct already
}

I noticed that the config variable in this mixin is returning the unmodified state of FirstPersonConfiguration, even though it is being updated elsewhere.

commented

I have noticed something else while testing and it is that now debugging in the mixin of PlayerEntityMixin to see the behavior of animationApplier I have realized that this currently manages 4 layers among which the 0 has the modifications made to FirstPersonConfiguration but the 1 presents the old ones and when getting animationApplier in PlayerRendererMixin and use
animationApplier.getFirstPersonConfiguration(); this returns the data of layer 1 and not of layer 0 which is the one that presents the change.

commented

Analyzing even more the code I have managed to understand what happens at last :V basically is that having several modifiers for the different things of my mod because each modifier has its own first person settings making that even though I was modifying it in the animation the modifiers kept the old settings and then when loading the settings the modifiers have preference before the animation. now I have created a new modifier which will be only and exclusively to handle the first person and I think that should solve all my problems.

commented

Solved but I think I would not have been so complicated with a little documentation the truth xd