Affects Version/s: Minecraft 1.12
Fix Version/s: None
macOS 10.12.5, Java 8u131
Under specific conditions, exiting a boat will cause the boat to move back to the point where the player first entered it, and then the boat will move back into the correct position. The boat does not actually move on the server; it only moves on the client.
- Place a boat on land.
- Without entering the boat, move the boat by pushing it around.
- While moving it, enter the boat. This must be done within 10 ticks/.5 seconds of moving the boat, and even then it can take about half a dozen tries.
- While inside the boat, row it a few blocks in any direction. (The bug is easiest to observe when the boat is moved away from the original position.)
The boat stays in place on dismount.
The boat snaps back to the original position, and then moves back to the dismount point in about a second.
Note: The redstone contraption in the video is there to show that the issue is client-side only, because the boat does not activate the tripwire on either jump.
(Based on Minecraft 1.12, decompiled with MCP 9.37)
When the player moves the boat without entering it, it causes the server to send SPacketEntity to the client with the updated position, which is handled in NetHandlerPlayClient::handleEntityMovement. This calls EntityBoat::setPositionAndRotationDirect, which sets up linear interpolation of the movement by setting lerpSteps to 10 and storing the target position. Normally, EntityBoat::tickLerp is called every tick by EntityBoat::onUpdate to handle this, and the lerp will be complete in 10 ticks.
However, if the player enters the boat while lerpSteps != 0, EntityBoat::tickLerp stops decrementing lerpSteps, essentially "freezing" the remaining duration and target of the lerp. As the player moves the boat, even though SPacketEntity is still being sent to the client, NetHandlerPlayClient::handleEntityMovement does not call EntityBoat::setPositionAndRotationDirect because the boat's passenger (the player) can steer. This preserves the state of the lerp as long as the player is in the boat.
When the player exits the boat, the lerp is "unfrozen", and the boat completes the lerp'd movement by flying back to the starting position. When the server sends the next SPacketEntity, the boat starts a new lerp'd movement and flies back to where it should be.