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

Quickly tapping and releasing keybind once for actions that change camera/fov can cause it to happen twice

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • None
    • 1.18.2, 1.19.2
    • None
    • Confirmed
    • Input
    • Normal
    • Platform

      The bug

      For some actions that change the FOV or move the camera, quickly tapping and releasing the button for it once can cause it to visually happen twice. I've noticed it happen with sneaking, using a spyglass, sprinting, and sprint swimming. This usually only happens while playing on a server, or a very laggy singleplayer world.

      For sneaking, the camera moves down twice, but your character does not actually crouch twice. This is the only one I was able to reproduce in singleplayer.

      For sprinting and sprint swimming, the FOV will cycle twice.

      With a spyglass, the overlay will appear twice, however the zoom seemed to happen only once.

      I've attached videos for each instance. It may be difficult to notice, as it happens quite quickly.

      This happens because the client informs the server about the change in input, the server updates the player's state, and when sending out this change it also sends it back to the original client. If the original client has a high latency it will receive its own actions back with that delay. However, because clients store their current crouching and sprinting state in the entity metadata (shared flags and pose) the server overrides it for one tick before the client updates again.
       

      Reproduction Steps

      Since this bug is specific to high latency these reproduction steps use a third-party tool called clumsy (https://jagt.github.io/clumsy/) to create artificial lag.

      1. Locally run a client and a server
      2. Start clumsy with the filter "tcp and (tcp.DstPort == 25565 or tcp.SrcPort == 25565)" (filters all TCP packets on the default server port)
      3. Tick the Lag box and set delay to 100 ms (both Inbound and Outbound). This creates 200ms lag which is enough to see the issue
      4. Join the server and tap shift quickly to see the issue

      Code Analysis

      Code analysis by Aeltumn provided in duplicate MC-256865.

      The client informs the server when they start shifting, the server then runs updatePlayerPose and updates the pose to CROUCHING, this then triggers setPose, this updates the entity metadata which gets synced with the client where the pose is set. The client will thus be in the CROUCHING pose for the rest of the tick until it runs updatePlayerPose itself at the end of the tick and goes back to STANDING.

      This issue applies to both the pose and shared flags entity metadata, the problem being that the client receives information about their own actions with the added latency from the server. The pose and shared flags (specifically those for sprinting, swimming and gliding) are updated by both the client and the server to match the current state of the entity, the data in these flags should not get sent to a client by the server about the local player entity without overriding anything.

      A solution to only fix this issue with crouching is to prevent the server from ever sending a player their own pose. However, this does not solve the full issue as some flags in the shared flags data has the same issue. The problem is that while we can avoid ever sending the pose we cannot avoid sending the shared flags as some of the other flags are only ever set by the server. So the shared flags should be split into two sets of flags: shared flags and personal flags. Personal flags can be adjusted by both client and server and the server does not send a client their own personal flags, they are only sent to other clients. Shared flags are still sent to every client.

      If both the personal flags and pose are never sent to a client about their own local entity the duplicate crouching and sprinting is fixed. Other actions like swimming and gliding are possibly also affected but they rarely last long enough for the server to override it.

      It could also be possible to implement personal flags by adding a personal boolean to the EntityDataAccessor and adding this to every data type where this personal logic applies.

        1. Sneak.mp4
          537 kB
        2. Sprint.mp4
          1.50 MB
        3. Spyglass.mp4
          2.26 MB
        4. Swim.mp4
          2.11 MB

            Unassigned Unassigned
            Shadow_Walker13 Shade August
            Votes:
            8 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              CHK: