Lagback/ja: Difference between revisions

From Minecraft Parkour Wiki
Content added Content deleted
(Created page with "//エラーを検出する: プレイヤーが不正に、もしくは当たり判定の内部を移動した if (noCollisionInside && (movedWrongly || !next_noCollisionInside)) { //プレイヤーを前の位置に戻す this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, yaw, pitch); return; }")
No edit summary
 
(9 intermediate revisions by the same user not shown)
Line 66: Line 66:
=== スニークグリッチ ===
=== スニークグリッチ ===


スニークグリッチ(もしくはシフトグリッチ)はブロック縁に着地しながら[[Special:MyLanguage/Sneaking/ja|スニーク]]すると発生し、スニークしているにもかかわらず落下してしまうというもの(1.16.2で修正済み)。
<div lang="en" dir="ltr" class="mw-content-ltr">
A sneak glitch (or shift glitch) happens when the player [[Special:MyLanguage/Sneaking|sneaks]] while landing on an edge, which causes them to fall anyway (this was fixed in 1.16.2).
</div>


スニークグリッチを行う際、サーバーが想定するプレイヤーの動きと実際の動きが異なる。以下がその理由:
<div lang="en" dir="ltr" class="mw-content-ltr">
When performing a sneak glitch, the server's expected movement for the player is different from their actual movement. Here's why:
</div>


* 最初の計算中、プレイヤーはスニークしているが「地面にいる」わけではないため、ブロックの縁を越えて動く。しかし着地はするため、<code>onGround = true</code>に設定される。
<div lang="en" dir="ltr" class="mw-content-ltr">
* 再計算中、プレイヤーは実際に着地する前に「地面にいる」とみなされ、スニークの挙動が変わる: 地面にいないにもかかわらず、「縁から落ちる」ことができなくなる。
* During the original calculation, the player is sneaking but not "on ground", hence they move past the edge. However, they still land, which sets <code>onGround = true</code>.
* 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.
</div>


0.25m/t以上の水平方向の速度で、適切な位置でスニークグリッチを行うことで、lagbackを引き起こし、前の位置にテレポートさせられた後にジャンプすることができる。結果として、空中からジャンプを開始することができるという意味で、[[Special:MyLanguage/Blip/ja|blip-up]]のようなジャンプになる。以下はその例:
<div lang="en" dir="ltr" class="mw-content-ltr">
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 [[Special:MyLanguage/Blip|blip-up]], in the sense that the player can start jumping mid-air. Here is an example:
</div>


<youtube>https://youtu.be/IOrpHNqn5t0</youtube>
<youtube>https://youtu.be/IOrpHNqn5t0</youtube>


ジャンプの高さによっては効果のないものもある。現在調査中。
<div lang="en" dir="ltr" class="mw-content-ltr">
Some jump heights do not work. This is still being investigated.
</div>




Line 93: Line 83:
== ソースコード ==
== ソースコード ==


シングルプレイヤーでは、lagbackはソースコードのこの部分によって引き起こされる(大幅に簡略化済み、飛行・睡眠・テレポート・リスポーン・エンティティへの騎乗などの例外的なケースは無視る):<syntaxhighlight lang="java" line="1">
シングルプレイヤーでは、lagbackはソースコードのこの部分によって引き起こされる(大幅に簡略化済み、飛行・睡眠・テレポート・リスポーン・エンティティへの騎乗などの例外的なケースは無視している):<syntaxhighlight lang="java" line="1">
//NetHandlerPlayServer.java内
//NetHandlerPlayServer.java内
public void processPlayer(PacketPlayer packetIn)
public void processPlayer(PacketPlayer packetIn)
Line 139: Line 129:
}
}


this.playerEntity.handleFalling(this.playerEntity.posY - posY_original, packetIn.isOnGround());
<div lang="en" dir="ltr" class="mw-content-ltr">
this.playerEntity.handleFalling(this.playerEntity.posY - posY_original, packetIn.isOnGround());
}
}
</syntaxhighlight>なお、落下ダメージの処理はlagback時には行われない。このため、最終的な落下時に予想外に高い落下ダメージを受けることがある。<br>1.15([https://bugs.mojang.com/browse/MC-153698 ボートの落下ダメージバグ]の修正)以降は、ジャンプによりプレイヤーの落下距離がリセットされるため、lagbackと組み合わせ悪用することで、高所からの落下を乗り切ることが可能。
</syntaxhighlight>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 [https://bugs.mojang.com/browse/MC-153698 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.
</div>

Latest revision as of 05:36, 5 February 2023

Other languages:

Lagbackとは、プレイヤーが以前の位置にテレポートで戻される現象である。悪用することで、壁にめり込んだりBlipと同様により高くジャンプしたりできるが、マルチプレイヤーサーバーでは実行が禁止されている場合がある。このページでは1.8のシングルプレイヤーに焦点を当てているが、ほとんどの情報はマルチプレイヤー及び1.9以降にも関連している。

lagbackのトリガーとして知られている動作は以下の通り:

  • ブロックに埋まる。
  • ボートにぶつかる。
  • クモの巣の中で素早く移動する。
  • 充分な速度で、スニークしながら着地する。
  • stepping発動可能なブロックを、超高速(移動速度上昇100など)で通り抜ける。
  • 壁に向かって素早く移動する。


一般的な説明

lagbackを引き起こす方法は、大きく分けて2つある:

  • 当たり判定と重なる(ブロックに埋まる、ボートにぶつかるなど)。
  • 不正に」移動する。

1つ目の方法については、説明の必要はないだろう。

2つ目の方法については、まずプレイヤーの動きがサーバー側でどのように処理されているかを理解する必要がある(シングルプレイヤーであっても、ゲームは統合サーバー上で動作している)。
毎tick、クライアントはプレイヤーの次の位置を計算し、サーバーにパケットを送信する。サーバーは、プレイヤーの動きを前回の位置から再計算することで検証する。この時、理論上は計算結果は同じ位置になるはずである。しかし、サーバーはプレイヤーの移動による副作用を元に戻さず計算するため、プレイヤーの予想される位置と実際の位置にズレが生じることがある。2つの計算結果のズレは、水平方向の距離が0.25mを超えていると重大と判断され、その場合、プレイヤーは前回の位置に戻される。

検証の過程で元に戻されない副作用には以下が含まれる:

  • 着地時にonGroundフラグがtrueに設定される(スニークの挙動が変わる)。
  • クモの巣に接触時にinWebフラグがfalseに設定される。
  • 壁や天井に衝突時に各種collidedフラグがtrueに設定される。

つまり、プレイヤーの動きは1tickに2回計算されるが、1回目の計算による副作用が2回目の計算結果に影響を与える可能性がある。プレイヤーの動きが十分に速ければ、サーバーはプレイヤーが不正に移動したと判断し、lagbackを発生させる。


具体的なトリガーの説明

当たり判定と重なる

プレイヤーが当たり判定の中に入ることは想定されていない。しかし、サーバーが当たり判定の各方向に0.0625bの猶予を設けているため、プレイヤーのバウンディングボックスはブロックの「外殻」と重なりながらでも通常通り動くことができる。それ以上内側に動くと、lagbackが引き起こされる。

既に完全に当たり判定の内側にいる場合は、動いても戻されることはない。


クモの巣に接触する(WIP)

クモの巣に接触する(tickの終わりに検知される)と、プレイヤーのinWebフラグがtrueに設定される。プレイヤーが移動してinWebtrueになると、すぐにfalseに設定され、プレイヤーの速度にクモの巣の効果が適用される。これにより元の計算と再計算の間にズレが生じ、条件速度が満たされればlagbackが引き起こされる。

高所から落下しスニークしながら着地する

この種類は、以下の必要条件のもとで着地・スニークすることで実現される:

  • 水平方向に0.25m/tより高い速度で移動している。
  • 着地1tick前に地面の最低1ブロック上にいる(1.11+では0.6b)。

スニークのタイミングは正確である必要はないが、早すぎると水平方向の速度が著しく低下する。

垂直方向の速度を-1m/t以上にするために必要なジャンプの高さは-7.3125b。この方法を試すための簡単なセットアップは-9.5b。以下がその例:


スニークグリッチ

スニークグリッチ(もしくはシフトグリッチ)はブロック縁に着地しながらスニークすると発生し、スニークしているにもかかわらず落下してしまうというもの(1.16.2で修正済み)。

スニークグリッチを行う際、サーバーが想定するプレイヤーの動きと実際の動きが異なる。以下がその理由:

  • 最初の計算中、プレイヤーはスニークしているが「地面にいる」わけではないため、ブロックの縁を越えて動く。しかし着地はするため、onGround = trueに設定される。
  • 再計算中、プレイヤーは実際に着地する前に「地面にいる」とみなされ、スニークの挙動が変わる: 地面にいないにもかかわらず、「縁から落ちる」ことができなくなる。

0.25m/t以上の水平方向の速度で、適切な位置でスニークグリッチを行うことで、lagbackを引き起こし、前の位置にテレポートさせられた後にジャンプすることができる。結果として、空中からジャンプを開始することができるという意味で、blip-upのようなジャンプになる。以下はその例:

ジャンプの高さによっては効果のないものもある。現在調査中。


ソースコード

シングルプレイヤーでは、lagbackはソースコードのこの部分によって引き起こされる(大幅に簡略化済み、飛行・睡眠・テレポート・リスポーン・エンティティへの騎乗などの例外的なケースは無視している):

//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();}

    //プレイヤーが当たり判定の内部から動き始めているかをチェック: その場合、lagbackは発生しない
    boolean noCollisionInside = worldserver.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.getEntityBoundingBox().contract(0.0625, 0.0625, 0.0625).isEmpty();

    //動きの検証を開始
    double deltaX = next_posX - this.playerEntity.posX;
    double deltaY = next_posY - this.playerEntity.posY;
    double deltaZ = next_posZ - this.playerEntity.posZ;

    if (this.playerEntity.onGround && !packetIn.isOnGround() && deltaY > 0.0)
        this.playerEntity.jump();
    this.playerEntity.moveEntity(deltaX, deltaY, deltaZ);
    this.playerEntity.onGround = packetIn.isOnGround();
    
    //予想位置と実際の位置の誤差を算出
    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());

    //プレイヤーを実際の位置に動かし、衝突判定をチェックする
    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();

    //エラーを検出する: プレイヤーが不正に、もしくは当たり判定の内部を移動した
    if (noCollisionInside && (movedWrongly || !next_noCollisionInside))
    {
        //プレイヤーを前の位置に戻す
        this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, yaw, pitch);
        return;
    }

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

なお、落下ダメージの処理はlagback時には行われない。このため、最終的な落下時に予想外に高い落下ダメージを受けることがある。
1.15(ボートの落下ダメージバグの修正)以降は、ジャンプによりプレイヤーの落下距離がリセットされるため、lagbackと組み合わせ悪用することで、高所からの落下を乗り切ることが可能。