Lagback/zh: Difference between revisions

From Minecraft Parkour Wiki
Content added Content deleted
(Created page with "== 常规解释 ==")
(Created page with "触发回弹有两种方法: * 与碰撞箱相交(卡在方块中,或与船相撞)。 * "''错误地''"移动。 第一种方法是无需解释的。")
Line 13: Line 13:
== 常规解释 ==
== 常规解释 ==


触发回弹有两种方法:
<div lang="en" dir="ltr" class="mw-content-ltr">
* 与碰撞箱相交(卡在方块中,或与船相撞)。
There are two main ways to trigger a lagback:
* "''错误地''"移动。
* Intersecting with a collision box (stuck in a block, or colliding with a boat).
第一种方法是无需解释的。
* Moving "''wrongly''".
The first method is self-explanatory.
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">

Revision as of 16:16, 6 September 2022

Other languages:

回弹是指玩家被传送回之前的位置。它可以被利用于卡进墙壁或以类似卡角的方式跳得更高,尽管这些做法在多人服务器上可能是禁止的。在本文中,我们主要关注1.8的单人模式,但大多数信息都与多人模式和1.9+相关。

以下是已知的回弹触发因素:

  • 卡在一个方块中。
  • 与船相撞。
  • 蜘蛛网中移动过快。
  • 以足够的速度在潜行时降落
  • 以极快的速度(例如速度100)通过步行辅助移动。
  • 靠着墙快速移动。


常规解释

触发回弹有两种方法:

  • 与碰撞箱相交(卡在方块中,或与船相撞)。
  • "错误地"移动。

第一种方法是无需解释的。

As for the second method, one must first understand how player movement is processed server-side (even in singleplayer, the game runs on an integrated server). Each tick, the client calculates the player's next position, and sends a packet to the server. The server validates the player's movement by recalculating it from their last position, which should theoretically result in the same position. However, the server does not undo the side effects of the player's movement, which may cause a discrepancy between the player's expected and actual positions. The discrepancy is considered significant if the horizontal distance between the two is strictly more than 0.25m, in which case the player is lagged back to their previous position.

Side effects that aren't undone prior to the validation process include:

  • The onGround flag being set to true when landing (which changes the behaviour of sneaking).
  • The inWeb flag being set to false when colliding with a cobweb.
  • The various collided flags being set to true when colliding with a wall or ceiling.

In short, the player's movement is calculated twice each tick, but the side effects of the first calculation may influence the result of the second one. If the player moves fast enough, the server thinks the player moves wrongly, and triggers a lagback.


Explanations for specific triggers


Intersecting with a collision box

The player is not supposed to move into a collision box. However, the server has a leniency of 0.0625b in each direction, meaning the player's bounding box can intersect with the "exterior shell" of a block and move normally. If the player move further inward, it triggers a lagback.

If the player is already fully inside a collision box, they do not get lagged back when moving.


Colliding with a cobweb

When colliding with a cobweb (detected at the end of the tick, but at the player's previous position), the player's inWeb flag is set to true. When the player is moved and and inWeb is true, it is immediately set to false, and the cobweb's effect is applied on the player's velocity. This causes a discrepancy between the original calculation and the recalculation, which triggers a lagback if sufficient speed is met.


Landing from a high fall while sneaking

This variant is achieved by landing and sneaking with the following requirements:

  • Moving horizontally at strictly more than 0.25m/t.
  • Being at least one block above ground on the tick before landing (or 0.6b in 1.11+).

The minimum jump height required to achieve at least -1m/t of vertical speed is -7.3125b. An easy setup to try this method is -9.5b. You are not required to time the sneak exactly, but sneaking too early will significantly reduce the player's horizontal speed.


Sneak Glitch

A sneak glitch (or shift glitch) happens when the player sneaks while landing on an edge, which causes them to fall anyway (this was fixed in 1.16.2).

When performing a sneak glitch, the server's expected movement for the player is different from their actual movement. Here's why:

  • During the original calculation, the player is sneaking but not "on ground", hence they move past the edge. However, they still land, which sets onGround = true.
  • During the recalculation, the player is now considered "on ground" before actually landing, which changes the behaviour of sneaking: they can not "fall off the edge", despite not being at ground level.

With at least 0.25m/t of horizontal speed and appropriate placement, performing a sneak glitch can therefore trigger a lagback. After being teleported back to their previous position, the player is now able to jump. The resulting jump looks similar to a blip-up, in the sense that the player can start jumping mid-air. Here is an example:

Some jump heights do not work. This is still being investigated.


Code

In singleplayer, lagbacks are caused by this section of code (heavily simplified, we ignore exceptional cases such as flying, sleeping, teleporting, respawning, mounting an entity...):
//in NetHandlerPlayServer.java
public void processPlayer(PacketPlayer packetIn)
{
    double posY_original = this.playerEntity.posY;
    this.lastPosX = this.playerEntity.posX;
    this.lastPosY = this.playerEntity.posY;
    this.lastPosZ = this.playerEntity.posZ;
    double next_posX = packetIn.getPositionX();
    double next_posY = packetIn.getPositionY();
    double next_posZ = packetIn.getPositionZ();
    float yaw = this.playerEntity.rotationYaw;
    float pitch = this.playerEntity.rotationPitch;
    if (packetIn.getRotating()) {yaw = packetIn.getYaw(); pitch = packetIn.getPitch();}
</div>

    <div lang="en" dir="ltr" class="mw-content-ltr">
//checks whether the player is starting from inside a collision box: in this case, there is no lagback
    boolean noCollisionInside = worldserver.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.getEntityBoundingBox().contract(0.0625, 0.0625, 0.0625).isEmpty();
</div>

    <div lang="en" dir="ltr" class="mw-content-ltr">
//begin movement verification
    double deltaX = next_posX - this.playerEntity.posX;
    double deltaY = next_posY - this.playerEntity.posY;
    double deltaZ = next_posZ - this.playerEntity.posZ;
</div>

    <div lang="en" dir="ltr" class="mw-content-ltr">
if (this.playerEntity.onGround && !packetIn.isOnGround() && deltaY > 0.0)
        this.playerEntity.jump();
    this.playerEntity.moveEntity(deltaX, deltaY, deltaZ);
    this.playerEntity.onGround = packetIn.isOnGround();
    
    //calculates error between the expected and actual positions
    double errorX = next_posX - this.playerEntity.posX;
    double errorZ = next_posZ - this.playerEntity.posZ;
    double error_squared = errorX * errorX + errorZ * errorZ;
    boolean movedWrongly = (error_squared > 0.0625 && !this.playerEntity.theItemInWorldManager.isCreative());
</div>

    <div lang="en" dir="ltr" class="mw-content-ltr">
//sets the player to their actual position, and checks for collisions
    this.playerEntity.setPositionAndRotation(next_posX, next_posY, next_posZ, yaw, pitch);
    boolean next_noCollisionInside = worldserver.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.getEntityBoundingBox().contract(0.0625, 0.0625, 0.0625).isEmpty();
</div>

    <div lang="en" dir="ltr" class="mw-content-ltr">
//detects an error: player moved wrongly, or moved inside a collision box
    if (noCollisionInside && (movedWrongly || !next_noCollisionInside))
    {
        //lags the player back to their previous position
        this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, yaw, pitch);
        return;
    }
</div>

    <div lang="en" dir="ltr" class="mw-content-ltr">
this.playerEntity.handleFalling(this.playerEntity.posY - posY_original, packetIn.isOnGround());
}
Note that the handling of fall damage is not processed if the player gets lagbacked. This may cause the player to suffer unexpectedly high fall damage when they eventually land. Since 1.15 (when the boat fall damage bug was fixed), jumping resets the player's fall distance, which can be abused to survive high falls when combined with lagback.