Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-271185

Player speed limit check has multiple mathematical errors

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Invalid
    • None
    • 1.20.5, 1.20.6 Release Candidate 1
    • None
    • Plausible
    • Networking

      This calculation has been documented on wiki.vg for a very long time, so I can only assume this bug has been known for about as long. Still, I couldn't find a report on it, so here we go.

      Here's the formula used to check for excessively fast movement in net.minecraft.server.network.ServerGamePacketListenerImpl.handleMovePlayer:

      (Δx² + Δy² + Δz²) - (Vx² + Vy² + Vz²) > limit² * packetCount
      

      where Δ is the movement delta proposed by the packet relative to the position on the last server tick, V is the player's server-side velocity (player.deltaMovement), limit is the maximum movement speed, and packetCount is the number of movement packets received since the last tick, including this one.

      Spot the 3 mistakes!!!

      Well, this is a bug report, so I'm supposed to spell them out for you:

      1. |A| - |B| doesn't necessarily equal |A - B|, where A and B are vectors. (In this case those vectors are Δ and V.) If Δ is facing opposite to V, then the velocity compensation as implemented increases the amount Δ is allowed to diverge from V. There is some chance this one might have been intentional, since e.g. bouncing on a slime block will lead to a quick upwards acceleration correlating with the old downwards velocity; though I can't think of any other examples, and am pretty sure this code was written long before the addition of slime blocks.
      2. a² - b² doesn't necessarily equal (a - b)². (a and b are |Δ| and |V|.) This can even cause the calculated "square of movement speed" to go negative! I didn't realize players could move at an imaginary speed, and still pass the check.
      3. a² * b doesn't necessarily equal (a * b)². (a and b are limit and packetCount.) The limit ends up being scaled by the square root of packetCount. (Note that this lag compensation measure as currectly implemented has some problems that will become worse as a result of fixing the bug. See this comment for details.)

      All this is surely fixed by any decent anticheat plugin, but it would still be nice to see the vanilla server's presently abysmal movement validation improve. And who knows, maybe fixing this will make some of the elytra false positives that necessitate disableElytraMovementCheck magically disappear.

      Oh, and here's how to do it correctly:

      (Δx - Vx)² + (Δy - Vy)² + (Δz - Vz)² > limit² * packetCount²
      

            Unassigned Unassigned
            lassipulkkinen Lassi Pulkkinen
            Votes:
            2 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved:
              CHK: