mojira.dev
MC-108948

Boats / boats with chest on top of slime blocks hover over block

The bug

When a boat is falling while over a slime block, once it gets to about 5 blocks on top of the slime block, the boat will start rising and falling very slowly. As of 22w12a, this also occurs with boats with chests. As of 1.21.2 Pre-Release 2, the effect is not as large and does not occur with every bounce, but still happens.

How to reproduce

Video demonstrating the issue: https://gfycat.com/PrestigiousDistantGardensnake

Code analysis

Code analysis by @unknown can be found in this comment.

Linked issues

Attachments

Comments 21

Confirmed for 1.12

Actually the boat movements seems to get softened, and that makes it visually bounce on the air when it hits the slime block server-side and it goes up again before it hits the ground client-side.

MC-111271 describes it better, and the gif in this issue is still relevant for 1.12.

EDIT: on a side note, slime blocks pushed by pistons sometimes fail to launch a boat in the air and only push it a few blocks. Is that a different issue?

Confirmed for 1.12-pre6

Konrad Linkowski

A possible cause could be an interference with how the game extrapolates positions of a moving object and with collision detection. A similar behavior is seen in MC-110648 (possibly the same cause, different issue though). This issue is also in 18w08b.

Confirmed for 1.13.1.

11 more comments

Can confirm in 1.18 Pre-release 1.

[media][media]

Code Analysis (Yarn - 1.18.1)

The issue here is that the client does not run the same calculations as the server.

BoatEntity.java

public void tick() {
   //...
   if (this.isLogicalSideForUpdatingMovement()) {
      if (!(this.getFirstPassenger() instanceof PlayerEntity)) {
         this.setPaddleMovings(false, false);
      }

      this.updateVelocity();
      if (this.world.isClient) {
         this.updatePaddles();
         this.world.sendPacket(new BoatPaddleStateC2SPacket());
      }

      this.move(MovementType.SELF, this.getVelocity());
   } else {
      this.setVelocity(Vec3d.ZERO);
   }
   //...
}

isLogicalSideForUpdatingMovement() returns true if the client is running the code and the client player is controlling the boat, or if the server is running the code.

Basically, when you are not controlling the boat, the client will run this.setVelocity(Vec3d.ZERO); instead of running the actual physics.
Resulting in de-sync of the client & server.

Proposed Fix:

public void tick() {
   //...
   if (!(this.getFirstPassenger() instanceof PlayerEntity)) {
      this.setPaddleMovings(false, false);
   }

   this.updateVelocity();
   if (this.world.isClient && this.isLogicalSideForUpdatingMovement()) {
      this.updatePaddles();
      this.world.sendPacket(new BoatPaddleStateC2SPacket());
   }

   this.move(MovementType.SELF, this.getVelocity());
   //...
}

This has been tested and works perfectly. It will simply allow the client to run the physics while still limiting the updating & packets for when it's being controlled.

Wouldn't it be

if (this.world.isClient && this.isLogicalSideForUpdatingMovement())

Can confirm in 1.18.2 and 22w16b.

Can confirm in 1.19.2.

BCNOFNeNaMg

(Unassigned)

Confirmed

Gameplay

Normal

Entities

boat, boat-with-chest, slime_block

Minecraft 1.10.2, Minecraft 16w41a, Minecraft 16w42a, Minecraft 1.11.2, Minecraft 1.12 Pre-Release 6, ..., 1.20.1, 1.20.3 Pre-Release 2, 1.21, 24w34a, 1.21.2 Pre-Release 2

Retrieved