mojira.dev
MC-258579

Player head does not rotate smoothly (with delay) in third person view while riding a vehicle

The Bug

Normally, when the player moves the cursor in third person view, it's model head rotates smoothly (with a slight delay from the camera). However, this doesn't happen while the player is on a vehicle.

This bug is caused by two different mistakes in the code of the game. The first one affects all vehicles and it's just from client-side and the second only affects boats.

How to reproduce

  1. Enter third person view.

  2. Move the camera left and right
    → ✔ Your head moves smoothly

  3. Place a minecart or any other rideable entity and enter it
    → ❌  Your head doesn't move smoothly

Code analysis (using the official mappings and code from 1.19.2, with my own variable names)

In "net.minecraft.client.player.LocalPlayer", the method "getViewYRot(float)" that overrides LivingEntity's, it returns the player's current Y rotation (not the head Y rotation) only when the player is not a passenger. This causes that when "net.minecraft.client.Camera" calls this method when the player is a passenger, the camera uses the head rotation, always rendering the head directly and being unable to see the it's sides.

@Override
public float getViewYRot(float partialTick) {
  return this.isPassenger() ? super.getViewYRot(partialTick) : this.getYRot();
}

This can be easily fixed by changing LocalPlayer's "getViewYRot" method to always return the Y rotation "getYRot()", regardless of if the player is a passenger or not. (just like "getViewXRot(float)"):

@Override
public float getViewYRot(float partialTick) {
  return this.getYRot();
}

By fixing what's described above, the head will now move smoothly (with the "delay") when the player is riding any vehicle without (most likely) any side effects on gameplay. But this will not fix this issue for boats.

This bug also happens when riding a boat (if just this is fixed and not the above, this will not work):

In "net.minecraft.world.entity.vehicle.Boat", at the method "clampRotation(Entity)" which prevents the player from moving his head too away from it's front, when setting the player's Head Y rotation using "setYHeadRot(float)", it just copies the Main Y rotation of the player that was adjusted, removing the delay (or smoothness) of the head movement at third person view.

protected void clampRotation(Entity psngr) {
  psngr.setYBodyRot(this.getYRot());
  float wrappedYrot = Mth.wrapDegrees(psngr.getYRot() - this.getYRot());
  float clampedYrot = Mth.clamp(wrappedYrot, -105.0F, 105.0F);
  psngr.yRotO += clampedYrot - wrappedYrot;
  psngr.setYRot(psngr.getYRot() + clampedYrot - wrappedYrot);
  psngr.setYHeadRot(psngr.getYRot);
}

This can be fixed by using it's own clamp calculation rather than using the main Y rotation's, as shown in this example:

protected void clampRotation(Entity psngr) {
  psngr.setYBodyRot(this.getYRot());
  float wrappedYrot = Mth.wrapDegrees(psngr.getYRot() - this.getYRot());
  float clampedYrot = Mth.clamp(wrappedYrot, -105.0F, 105.0F);
  psngr.yRotO += clampedYrot - wrappedYrot;
  psngr.setYRot(psngr.getYRot() + clampedYrot - wrappedYrot);
  float wrappedYheadrot = Mth.wrapDegrees(psngr.getYHeadRot() - this.getYRot());
  float clampedYheadrot = Mth.clamp(wrappedYheadrot, -105.0F, 105.0F);
  psngr.setYHeadRot(psngr.getYHeadRot() + clampedYheadrot - wrappedYheadrot);
}

Deeper investigation (what caused this bug, very important)

This bug happens since snapshot 17w48a, when MC-122211 (the camera jitters when turning a boat while riding it) was fixed by changing the LocalPlayer's "getViewYRot" method to return the Head rotation instead of the Main rotation if the player is a passenger. However, this was a lazy fix (or may be because the summary of that bug report was wrong and Mojang misunderstood it) because that bug actually caused the boat to stutter, not the camera, and resulted in this new bug.

MC-122211 should've been fixed by modifying the "yRotO" value of the boat to be consistent with the "yRot" when "deltaRotatation" field value changes it in the "controlBoat()" method, as you can see in this example:

(at net.minecraft.world.entity.vehicle.Boat)

private void controlBoat() {
   if (this.isVehicle()) {
      float f = 0.0F;
      if (this.inputLeft) {
         --this.deltaRotation;
      }

      if (this.inputRight) {
         ++this.deltaRotation;
      }

      if (this.inputRight != this.inputLeft && !this.inputUp && !this.inputDown) {
         f += 0.005F;
      }

      this.yRotO += this.deltaRotation;//ADD THIS
      this.setYRot(this.getYRot() + this.deltaRotation);
      if (this.inputUp) {
         f += 0.04F;
      }

      if (this.inputDown) {
         f -= 0.005F;
      }

      this.setDeltaMovement(this.getDeltaMovement().add((double)(Mth.sin(-this.getYRot() * ((float)Math.PI / 180F)) * f), 0.0D, (double)(Mth.cos(this.getYRot() * ((float)Math.PI / 180F)) * f)));
      this.setPaddleState(this.inputRight && !this.inputLeft || this.inputUp, this.inputLeft && !this.inputRight || this.inputUp);
   }
}

This is very important to do because if you just do the two fixes from the code analysis and ignore this, the boat will stutter when it turns, reviving MC-122211.

Linked issues

Attachments

Comments 5

After further testing, this bug seems to happen since 1.13 snapshot 17w48a.

This may duplicate MC-122731

@EliteTracker This bug doesn't have anything to do with camera stuttering, that's only mentioned in the history of a related boat bug which indirectly affected this.

@unknown Yeah correct, but it may duplicate MC-122731. Because if you watch the video attached to the report, you will realize that its the same bug this report describes, but you are indeed correct, MC-122731 does mainly focus on camera jittering/stuttering so it could just relate to MC-122731.

@BugTracker But that's just pure coincidental, for example, the video from the report of MC-180 also shows the bug of MC-193749 (and it's not considered a duplicate)

ISRosillo14

(Unassigned)

Confirmed

Platform

Low

Networking, Rendering

1.19.3, 23w07a, 1.19.4 Pre-release 1, 1.19.4, 23w16a, ..., 1.20.2, 1.20.3, 1.20.5, 1.21, 1.21.7

Retrieved