Skip to content

Commit 32160c5

Browse files
Fix chunks not loading when riding a vehicle, fix world border corrections not applying (#5410)
1 parent f27290a commit 32160c5

File tree

1 file changed

+78
-62
lines changed

1 file changed

+78
-62
lines changed

core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockMovePlayer.java

+78-62
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
7676
boolean hasVehicle = entity.getVehicle() != null;
7777

7878
// shouldSendPositionReminder also increments a tick counter, so make sure it's always called unless the player is on a vehicle.
79-
boolean positionChanged = !hasVehicle && (session.getInputCache().shouldSendPositionReminder() || actualPositionChanged);
79+
boolean positionChangedAndShouldUpdate = !hasVehicle && (session.getInputCache().shouldSendPositionReminder() || actualPositionChanged);
8080
boolean rotationChanged = hasVehicle || (entity.getYaw() != yaw || entity.getPitch() != pitch || entity.getHeadYaw() != headYaw);
8181

8282
if (session.getLookBackScheduledFuture() != null) {
@@ -87,87 +87,103 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
8787
}
8888

8989
// Client is telling us it wants to move down, but something is blocking it from doing so.
90-
boolean isOnGround = packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && packet.getDelta().getY() < 0;
90+
boolean isOnGround;
91+
if (hasVehicle) {
92+
// VERTICAL_COLLISION is not accurate while in a vehicle (as of 1.21.62)
93+
isOnGround = Math.abs(packet.getDelta().getY()) < 0.1;
94+
} else {
95+
isOnGround = packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && packet.getDelta().getY() < 0;
96+
}
97+
9198
// This takes into account no movement sent from the client, but the player is trying to move anyway.
9299
// (Press into a wall in a corner - you're trying to move but nothing actually happens)
100+
// This isn't sent when a player is riding a vehicle (as of 1.21.62)
93101
boolean horizontalCollision = packet.getInputData().contains(PlayerAuthInputData.HORIZONTAL_COLLISION);
94102

95103
// If only the pitch and yaw changed
96104
// This isn't needed, but it makes the packets closer to vanilla
97105
// It also means you can't "lag back" while only looking, in theory
98-
if (!positionChanged && rotationChanged) {
106+
if (!positionChangedAndShouldUpdate && rotationChanged) {
99107
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(isOnGround, horizontalCollision, yaw, pitch);
100108

101109
entity.setYaw(yaw);
102110
entity.setPitch(pitch);
103111
entity.setHeadYaw(headYaw);
104112

105113
session.sendDownstreamGamePacket(playerRotationPacket);
106-
} else if (positionChanged) {
107-
if (isValidMove(session, entity.getPosition(), packet.getPosition())) {
108-
CollisionResult result = session.getCollisionManager().adjustBedrockPosition(packet.getPosition(), isOnGround, packet.getInputData().contains(PlayerAuthInputData.HANDLE_TELEPORT));
109-
if (result != null) { // A null return value cancels the packet
110-
Vector3d position = result.correctedMovement();
111-
boolean isBelowVoid = entity.isVoidPositionDesynched();
112-
113-
boolean teleportThroughVoidFloor, mustResyncPosition;
114-
// Compare positions here for void floor fix below before the player's position variable is set to the packet position
115-
if (entity.getPosition().getY() >= packet.getPosition().getY() && !isBelowVoid) {
116-
int floorY = position.getFloorY();
117-
int voidFloorLocation = entity.voidFloorPosition();
118-
teleportThroughVoidFloor = floorY <= (voidFloorLocation + 1) && floorY >= voidFloorLocation;
119-
} else {
120-
teleportThroughVoidFloor = false;
121-
}
122114

123-
if (teleportThroughVoidFloor || isBelowVoid) {
124-
// https://github.com/GeyserMC/Geyser/issues/3521 - no void floor in Java so we cannot be on the ground.
125-
isOnGround = false;
126-
}
127-
128-
if (isBelowVoid) {
129-
int floorY = position.getFloorY();
130-
int voidFloorLocation = entity.voidFloorPosition();
131-
mustResyncPosition = floorY < voidFloorLocation && floorY >= voidFloorLocation - 1;
132-
} else {
133-
mustResyncPosition = false;
134-
}
135-
136-
double yPosition = position.getY();
137-
if (entity.isVoidPositionDesynched()) { // not using the cached variable on purpose
138-
yPosition += 4; // We are de-synched since we had to teleport below the void floor.
139-
}
140-
141-
Packet movePacket;
142-
if (rotationChanged) {
143-
// Send rotation updates as well
144-
movePacket = new ServerboundMovePlayerPosRotPacket(
115+
// Player position MUST be updated on our end, otherwise e.g. chunk loading breaks
116+
if (hasVehicle) {
117+
entity.setPositionManual(packet.getPosition());
118+
session.getSkullCache().updateVisibleSkulls();
119+
}
120+
} else if (positionChangedAndShouldUpdate) {
121+
if (isValidMove(session, entity.getPosition(), packet.getPosition())) {
122+
if (!session.getWorldBorder().isPassingIntoBorderBoundaries(entity.getPosition(), true)) {
123+
CollisionResult result = session.getCollisionManager().adjustBedrockPosition(packet.getPosition(), isOnGround, packet.getInputData().contains(PlayerAuthInputData.HANDLE_TELEPORT));
124+
if (result != null) { // A null return value cancels the packet
125+
Vector3d position = result.correctedMovement();
126+
boolean isBelowVoid = entity.isVoidPositionDesynched();
127+
128+
boolean teleportThroughVoidFloor, mustResyncPosition;
129+
// Compare positions here for void floor fix below before the player's position variable is set to the packet position
130+
if (entity.getPosition().getY() >= packet.getPosition().getY() && !isBelowVoid) {
131+
int floorY = position.getFloorY();
132+
int voidFloorLocation = entity.voidFloorPosition();
133+
teleportThroughVoidFloor = floorY <= (voidFloorLocation + 1) && floorY >= voidFloorLocation;
134+
} else {
135+
teleportThroughVoidFloor = false;
136+
}
137+
138+
if (teleportThroughVoidFloor || isBelowVoid) {
139+
// https://github.com/GeyserMC/Geyser/issues/3521 - no void floor in Java so we cannot be on the ground.
140+
isOnGround = false;
141+
}
142+
143+
if (isBelowVoid) {
144+
int floorY = position.getFloorY();
145+
int voidFloorLocation = entity.voidFloorPosition();
146+
mustResyncPosition = floorY < voidFloorLocation && floorY >= voidFloorLocation - 1;
147+
} else {
148+
mustResyncPosition = false;
149+
}
150+
151+
double yPosition = position.getY();
152+
if (entity.isVoidPositionDesynched()) { // not using the cached variable on purpose
153+
yPosition += 4; // We are de-synched since we had to teleport below the void floor.
154+
}
155+
156+
Packet movePacket;
157+
if (rotationChanged) {
158+
// Send rotation updates as well
159+
movePacket = new ServerboundMovePlayerPosRotPacket(
145160
isOnGround,
146161
horizontalCollision,
147162
position.getX(), yPosition, position.getZ(),
148163
yaw, pitch
149-
);
150-
entity.setYaw(yaw);
151-
entity.setPitch(pitch);
152-
entity.setHeadYaw(headYaw);
153-
} else {
154-
// Rotation did not change; don't send an update with rotation
155-
movePacket = new ServerboundMovePlayerPosPacket(isOnGround, horizontalCollision, position.getX(), yPosition, position.getZ());
156-
}
157-
158-
entity.setPositionManual(packet.getPosition());
159-
160-
// Send final movement changes
161-
session.sendDownstreamGamePacket(movePacket);
162-
163-
if (teleportThroughVoidFloor) {
164-
entity.teleportVoidFloorFix(false);
165-
} else if (mustResyncPosition) {
166-
entity.teleportVoidFloorFix(true);
164+
);
165+
entity.setYaw(yaw);
166+
entity.setPitch(pitch);
167+
entity.setHeadYaw(headYaw);
168+
} else {
169+
// Rotation did not change; don't send an update with rotation
170+
movePacket = new ServerboundMovePlayerPosPacket(isOnGround, horizontalCollision, position.getX(), yPosition, position.getZ());
171+
}
172+
173+
entity.setPositionManual(packet.getPosition());
174+
175+
// Send final movement changes
176+
session.sendDownstreamGamePacket(movePacket);
177+
178+
if (teleportThroughVoidFloor) {
179+
entity.teleportVoidFloorFix(false);
180+
} else if (mustResyncPosition) {
181+
entity.teleportVoidFloorFix(true);
182+
}
183+
184+
session.getInputCache().markPositionPacketSent();
185+
session.getSkullCache().updateVisibleSkulls();
167186
}
168-
169-
session.getInputCache().markPositionPacketSent();
170-
session.getSkullCache().updateVisibleSkulls();
171187
}
172188
} else {
173189
// Not a valid move

0 commit comments

Comments
 (0)