-
Bug
-
Resolution: Unresolved
-
None
-
1.19.3, 23w07a, 1.19.4 Pre-release 1, 1.19.4, 23w16a, 1.20, 1.20.1, 1.20.2, 1.20.3, 1.20.5, 1.21
-
None
-
Confirmed
-
Networking, Rendering
-
Low
-
Platform
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
- Enter third person view.
- Move the camera left and right
→ Your head moves smoothly - 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.
- relates to
-
MC-122211 Boat jitters when you turn
- Resolved
-
MC-261026 The player's head is not fully synced with the mouse cursor
- Resolved
-
MC-108765 Passengers in boats only rotate client-side if player is steering
- Open
-
MC-236497 The head rotations of passengers in boats are not correctly displayed for other players
- Open
-
MC-237679 The head rotations of passengers in boats are constantly forced to turn in certain directions if the rider were to dismount the boat while moving left or right
- Open
-
MC-270970 The player's camera shakes when attempting to step up blocks with a boat above them
- Open