-
Bug
-
Resolution: Duplicate
-
None
-
1.19.2
-
None
-
Unconfirmed
-
(Unassigned)
Whenever a player crouches shortly (tapping the key) while connected to a multiplayer server at high latency the action happens twice. The same goes for sprinting. 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.
For an example of what it looks like when crouching, see the attached video: the camera goes down twice sometimes. It's hard to get a feel for this without pressing the key yourself but when you see sneaking happen twice in rapid succession in the video that's the bug happening.
The same happens when tapping sprint.
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.
- Locally run a client and a server
- Start clumsy with the filter "tcp and (tcp.DstPort == 25565 or tcp.SrcPort == 25565)" (filters all TCP packets on the default server port)
- 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
- Join the server and tap shift quickly to see the issue
Code Analysis
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.
- duplicates
-
MC-248973 Quickly tapping and releasing keybind once for actions that change camera/fov can cause it to happen twice
- Open