Lagback

From Minecraft Parkour Wiki
Revision as of 17:12, 5 September 2022 by MCPK (talk | contribs) (added more explanation)

A lagback is an occurrence of the player getting teleported back to a previous position. It can be abused to clip inside walls, or jump higher in a similar fashion as Blips, though this practice may be a bannable offense on multiplayer servers. In this article, we focus on singleplayer 1.8.

Known causes for lagback

  • Colliding with a boat.
  • Falling and sneaking at the last moment.
  • Moving inside a cobweb too quickly.
  • Moving through a steppable block with an obscene amount of speed (Speed 100, for example).
  • Moving close to a wall.

Explanation

In singleplayer, the lagback itself is caused by this portion of code (in class NetHandlerPlayServer):

public void processPlayer(PacketPlayer packetIn)
{
    //heavily simplified, ignores exceptional cases (flying, sleeping, teleporting, , noclip, mounted, respawning...)
    double posY_original = this.playerEntity.posY;
    this.lastPosX = this.playerEntity.posX;
    this.lastPosY = this.playerEntity.posY;
    this.lastPosZ = this.playerEntity.posZ;
    double posX = packetIn.getPositionX();
    double posY = packetIn.getPositionY();
    double posZ = packetIn.getPositionZ();
    
    float yaw = this.playerEntity.rotationYaw;
    float pitch = this.playerEntity.rotationPitch;
    if (packetIn.getRotating()) {yaw = packetIn.getYaw(); pitch = packetIn.getPitch();}

    this.playerEntity.onUpdateEntity();
    this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ, yaw, pitch);
    
    double deltaX = posX - this.playerEntity.posX;
    double deltaY = posY - this.playerEntity.posY;
    double deltaZ = posZ - this.playerEntity.posZ;

    boolean noCollisionInside = worldserver.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.getEntityBoundingBox().contract(0.0625, 0.0625, 0.0625).isEmpty();

    if (this.playerEntity.onGround && !packetIn.isOnGround() && deltaY > 0.0D)
        this.playerEntity.jump();

    this.playerEntity.moveEntity(deltaX, deltaY, deltaZ);
    this.playerEntity.onGround = packetIn.isOnGround();
                    
    double errorX = posX - this.playerEntity.posX;
    double errorZ = posZ - this.playerEntity.posZ;
    double error_squared = errorX * errorX + errorZ * errorZ;
    boolean movedWrongly = (delta_squared > 0.0625D && !this.playerEntity.theItemInWorldManager.isCreative());

    this.playerEntity.setPositionAndRotation(posX, posY, posZ, yaw, pitch);
    
    boolean noCollisionInside_updated = worldserver.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.getEntityBoundingBox().contract(0.0625, 0.0625, 0.0625).isEmpty();

    //detects a desync - "lagbacks" the player to their previous position
    if (noCollisionInside && (movedWrongly || !noCollisionInside_updated))
    {
        this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, yaw, pitch);
        return;
    }

    this.playerEntity.onGround = packetIn.isOnGround();
    this.playerEntity.handleFalling(this.playerEntity.posY - posY_original, packetIn.isOnGround());
}

There are essentially two ways to trigger a lagback:

  • Moving "wrongly".
  • Intersecting with a collision box (only seems to happen when colliding with boats, but this can also make the player move wrongly).

The next section shall be dedicated to detailing how the player can move wrongly.

Moving wrongly

The player is considered to have moved wrongly if their expected motion differs significantly from their actual motion (difference of at least 0.25m). The problem lies in the fact some nonreversible actions are performed twice.