2525
2626package org .geysermc .geyser .translator .protocol .bedrock .entity .player .input ;
2727
28+ import net .kyori .adventure .util .TriState ;
2829import org .cloudburstmc .math .vector .Vector3d ;
2930import org .cloudburstmc .math .vector .Vector3f ;
3031import org .cloudburstmc .protocol .bedrock .data .PlayerAuthInputData ;
3132import org .cloudburstmc .protocol .bedrock .packet .PlayerAuthInputPacket ;
3233import org .geysermc .geyser .entity .EntityDefinitions ;
3334import org .geysermc .geyser .entity .type .player .SessionPlayerEntity ;
3435import org .geysermc .geyser .level .physics .CollisionResult ;
36+ import org .geysermc .geyser .network .GameProtocol ;
3537import org .geysermc .geyser .session .GeyserSession ;
3638import org .geysermc .geyser .text .ChatColor ;
3739import org .geysermc .mcprotocollib .network .packet .Packet ;
@@ -86,6 +88,14 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
8688 session .setLookBackScheduledFuture (null );
8789 }
8890
91+ TriState maybeOnGround ;
92+ if (GameProtocol .isPre1_21_30 (session )) {
93+ // VERTICAL_COLLISION input data does not exist.
94+ maybeOnGround = TriState .NOT_SET ;
95+ } else {
96+ // Client is telling us it wants to move down, but something is blocking it from doing so.
97+ maybeOnGround = TriState .byBoolean (packet .getInputData ().contains (PlayerAuthInputData .VERTICAL_COLLISION ) && packet .getDelta ().getY () < 0 );
98+ }
8999 // This takes into account no movement sent from the client, but the player is trying to move anyway.
90100 // (Press into a wall in a corner - you're trying to move but nothing actually happens)
91101 boolean horizontalCollision = packet .getInputData ().contains (PlayerAuthInputData .HORIZONTAL_COLLISION );
@@ -94,7 +104,7 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
94104 // This isn't needed, but it makes the packets closer to vanilla
95105 // It also means you can't "lag back" while only looking, in theory
96106 if (!positionChanged && rotationChanged ) {
97- ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket (entity .isOnGround (), horizontalCollision , yaw , pitch );
107+ ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket (maybeOnGround . toBooleanOrElse ( entity .isOnGround () ), horizontalCollision , yaw , pitch );
98108
99109 entity .setYaw (yaw );
100110 entity .setPitch (pitch );
@@ -103,10 +113,10 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
103113 session .sendDownstreamGamePacket (playerRotationPacket );
104114 } else if (positionChanged ) {
105115 if (isValidMove (session , entity .getPosition (), packet .getPosition ())) {
106- CollisionResult result = session .getCollisionManager ().adjustBedrockPosition (packet .getPosition (), packet .getInputData ().contains (PlayerAuthInputData .HANDLE_TELEPORT ));
116+ CollisionResult result = session .getCollisionManager ().adjustBedrockPosition (packet .getPosition (), maybeOnGround . toBooleanOrElse ( false ), packet .getInputData ().contains (PlayerAuthInputData .HANDLE_TELEPORT ));
107117 if (result != null ) { // A null return value cancels the packet
108118 Vector3d position = result .correctedMovement ();
109- boolean onGround = result . onGround (). toBooleanOrElse ( entity .isOnGround ());
119+ boolean onGround = maybeOnGround . toBooleanOrElseGet (() -> session . getCollisionManager () .isOnGround ());
110120 boolean isBelowVoid = entity .isVoidPositionDesynched ();
111121
112122 boolean teleportThroughVoidFloor , mustResyncPosition ;
@@ -155,7 +165,6 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
155165 }
156166
157167 entity .setPositionManual (packet .getPosition ());
158- entity .setOnGround (onGround );
159168
160169 // Send final movement changes
161170 session .sendDownstreamGamePacket (movePacket );
@@ -174,11 +183,12 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
174183 session .getGeyser ().getLogger ().debug ("Recalculating position..." );
175184 session .getCollisionManager ().recalculatePosition ();
176185 }
177- } else if (horizontalCollision != session .getInputCache ().lastHorizontalCollision ()) {
178- session .sendDownstreamGamePacket (new ServerboundMovePlayerStatusOnlyPacket (entity . isOnGround ( ), horizontalCollision ));
186+ } else if (horizontalCollision != session .getInputCache ().lastHorizontalCollision () || maybeOnGround . toBooleanOrElse ( entity . isOnGround ()) != entity . isOnGround () ) {
187+ session .sendDownstreamGamePacket (new ServerboundMovePlayerStatusOnlyPacket (maybeOnGround . toBooleanOrElse ( false ), horizontalCollision ));
179188 }
180189
181190 session .getInputCache ().setLastHorizontalCollision (horizontalCollision );
191+ entity .setOnGround (maybeOnGround .toBooleanOrElse (entity .isOnGround ()));
182192
183193 // Move parrots to match if applicable
184194 if (entity .getLeftParrot () != null ) {
0 commit comments