mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-22 00:09:32 +00:00
Fix chunks not loading when riding a vehicle, fix world border corrections not applying (#5410)
This commit is contained in:
@@ -76,7 +76,7 @@ final class BedrockMovePlayer {
|
|||||||
boolean hasVehicle = entity.getVehicle() != null;
|
boolean hasVehicle = entity.getVehicle() != null;
|
||||||
|
|
||||||
// shouldSendPositionReminder also increments a tick counter, so make sure it's always called unless the player is on a vehicle.
|
// shouldSendPositionReminder also increments a tick counter, so make sure it's always called unless the player is on a vehicle.
|
||||||
boolean positionChanged = !hasVehicle && (session.getInputCache().shouldSendPositionReminder() || actualPositionChanged);
|
boolean positionChangedAndShouldUpdate = !hasVehicle && (session.getInputCache().shouldSendPositionReminder() || actualPositionChanged);
|
||||||
boolean rotationChanged = hasVehicle || (entity.getYaw() != yaw || entity.getPitch() != pitch || entity.getHeadYaw() != headYaw);
|
boolean rotationChanged = hasVehicle || (entity.getYaw() != yaw || entity.getPitch() != pitch || entity.getHeadYaw() != headYaw);
|
||||||
|
|
||||||
if (session.getLookBackScheduledFuture() != null) {
|
if (session.getLookBackScheduledFuture() != null) {
|
||||||
@@ -87,15 +87,23 @@ final class BedrockMovePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Client is telling us it wants to move down, but something is blocking it from doing so.
|
// Client is telling us it wants to move down, but something is blocking it from doing so.
|
||||||
boolean isOnGround = packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && packet.getDelta().getY() < 0;
|
boolean isOnGround;
|
||||||
|
if (hasVehicle) {
|
||||||
|
// VERTICAL_COLLISION is not accurate while in a vehicle (as of 1.21.62)
|
||||||
|
isOnGround = Math.abs(packet.getDelta().getY()) < 0.1;
|
||||||
|
} else {
|
||||||
|
isOnGround = packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && packet.getDelta().getY() < 0;
|
||||||
|
}
|
||||||
|
|
||||||
// This takes into account no movement sent from the client, but the player is trying to move anyway.
|
// This takes into account no movement sent from the client, but the player is trying to move anyway.
|
||||||
// (Press into a wall in a corner - you're trying to move but nothing actually happens)
|
// (Press into a wall in a corner - you're trying to move but nothing actually happens)
|
||||||
|
// This isn't sent when a player is riding a vehicle (as of 1.21.62)
|
||||||
boolean horizontalCollision = packet.getInputData().contains(PlayerAuthInputData.HORIZONTAL_COLLISION);
|
boolean horizontalCollision = packet.getInputData().contains(PlayerAuthInputData.HORIZONTAL_COLLISION);
|
||||||
|
|
||||||
// If only the pitch and yaw changed
|
// If only the pitch and yaw changed
|
||||||
// This isn't needed, but it makes the packets closer to vanilla
|
// This isn't needed, but it makes the packets closer to vanilla
|
||||||
// It also means you can't "lag back" while only looking, in theory
|
// It also means you can't "lag back" while only looking, in theory
|
||||||
if (!positionChanged && rotationChanged) {
|
if (!positionChangedAndShouldUpdate && rotationChanged) {
|
||||||
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(isOnGround, horizontalCollision, yaw, pitch);
|
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(isOnGround, horizontalCollision, yaw, pitch);
|
||||||
|
|
||||||
entity.setYaw(yaw);
|
entity.setYaw(yaw);
|
||||||
@@ -103,71 +111,79 @@ final class BedrockMovePlayer {
|
|||||||
entity.setHeadYaw(headYaw);
|
entity.setHeadYaw(headYaw);
|
||||||
|
|
||||||
session.sendDownstreamGamePacket(playerRotationPacket);
|
session.sendDownstreamGamePacket(playerRotationPacket);
|
||||||
} else if (positionChanged) {
|
|
||||||
|
// Player position MUST be updated on our end, otherwise e.g. chunk loading breaks
|
||||||
|
if (hasVehicle) {
|
||||||
|
entity.setPositionManual(packet.getPosition());
|
||||||
|
session.getSkullCache().updateVisibleSkulls();
|
||||||
|
}
|
||||||
|
} else if (positionChangedAndShouldUpdate) {
|
||||||
if (isValidMove(session, entity.getPosition(), packet.getPosition())) {
|
if (isValidMove(session, entity.getPosition(), packet.getPosition())) {
|
||||||
CollisionResult result = session.getCollisionManager().adjustBedrockPosition(packet.getPosition(), isOnGround, packet.getInputData().contains(PlayerAuthInputData.HANDLE_TELEPORT));
|
if (!session.getWorldBorder().isPassingIntoBorderBoundaries(entity.getPosition(), true)) {
|
||||||
if (result != null) { // A null return value cancels the packet
|
CollisionResult result = session.getCollisionManager().adjustBedrockPosition(packet.getPosition(), isOnGround, packet.getInputData().contains(PlayerAuthInputData.HANDLE_TELEPORT));
|
||||||
Vector3d position = result.correctedMovement();
|
if (result != null) { // A null return value cancels the packet
|
||||||
boolean isBelowVoid = entity.isVoidPositionDesynched();
|
Vector3d position = result.correctedMovement();
|
||||||
|
boolean isBelowVoid = entity.isVoidPositionDesynched();
|
||||||
|
|
||||||
boolean teleportThroughVoidFloor, mustResyncPosition;
|
boolean teleportThroughVoidFloor, mustResyncPosition;
|
||||||
// Compare positions here for void floor fix below before the player's position variable is set to the packet position
|
// Compare positions here for void floor fix below before the player's position variable is set to the packet position
|
||||||
if (entity.getPosition().getY() >= packet.getPosition().getY() && !isBelowVoid) {
|
if (entity.getPosition().getY() >= packet.getPosition().getY() && !isBelowVoid) {
|
||||||
int floorY = position.getFloorY();
|
int floorY = position.getFloorY();
|
||||||
int voidFloorLocation = entity.voidFloorPosition();
|
int voidFloorLocation = entity.voidFloorPosition();
|
||||||
teleportThroughVoidFloor = floorY <= (voidFloorLocation + 1) && floorY >= voidFloorLocation;
|
teleportThroughVoidFloor = floorY <= (voidFloorLocation + 1) && floorY >= voidFloorLocation;
|
||||||
} else {
|
} else {
|
||||||
teleportThroughVoidFloor = false;
|
teleportThroughVoidFloor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (teleportThroughVoidFloor || isBelowVoid) {
|
if (teleportThroughVoidFloor || isBelowVoid) {
|
||||||
// https://github.com/GeyserMC/Geyser/issues/3521 - no void floor in Java so we cannot be on the ground.
|
// https://github.com/GeyserMC/Geyser/issues/3521 - no void floor in Java so we cannot be on the ground.
|
||||||
isOnGround = false;
|
isOnGround = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBelowVoid) {
|
if (isBelowVoid) {
|
||||||
int floorY = position.getFloorY();
|
int floorY = position.getFloorY();
|
||||||
int voidFloorLocation = entity.voidFloorPosition();
|
int voidFloorLocation = entity.voidFloorPosition();
|
||||||
mustResyncPosition = floorY < voidFloorLocation && floorY >= voidFloorLocation - 1;
|
mustResyncPosition = floorY < voidFloorLocation && floorY >= voidFloorLocation - 1;
|
||||||
} else {
|
} else {
|
||||||
mustResyncPosition = false;
|
mustResyncPosition = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double yPosition = position.getY();
|
double yPosition = position.getY();
|
||||||
if (entity.isVoidPositionDesynched()) { // not using the cached variable on purpose
|
if (entity.isVoidPositionDesynched()) { // not using the cached variable on purpose
|
||||||
yPosition += 4; // We are de-synched since we had to teleport below the void floor.
|
yPosition += 4; // We are de-synched since we had to teleport below the void floor.
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet movePacket;
|
Packet movePacket;
|
||||||
if (rotationChanged) {
|
if (rotationChanged) {
|
||||||
// Send rotation updates as well
|
// Send rotation updates as well
|
||||||
movePacket = new ServerboundMovePlayerPosRotPacket(
|
movePacket = new ServerboundMovePlayerPosRotPacket(
|
||||||
isOnGround,
|
isOnGround,
|
||||||
horizontalCollision,
|
horizontalCollision,
|
||||||
position.getX(), yPosition, position.getZ(),
|
position.getX(), yPosition, position.getZ(),
|
||||||
yaw, pitch
|
yaw, pitch
|
||||||
);
|
);
|
||||||
entity.setYaw(yaw);
|
entity.setYaw(yaw);
|
||||||
entity.setPitch(pitch);
|
entity.setPitch(pitch);
|
||||||
entity.setHeadYaw(headYaw);
|
entity.setHeadYaw(headYaw);
|
||||||
} else {
|
} else {
|
||||||
// Rotation did not change; don't send an update with rotation
|
// Rotation did not change; don't send an update with rotation
|
||||||
movePacket = new ServerboundMovePlayerPosPacket(isOnGround, horizontalCollision, position.getX(), yPosition, position.getZ());
|
movePacket = new ServerboundMovePlayerPosPacket(isOnGround, horizontalCollision, position.getX(), yPosition, position.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.setPositionManual(packet.getPosition());
|
||||||
|
|
||||||
|
// Send final movement changes
|
||||||
|
session.sendDownstreamGamePacket(movePacket);
|
||||||
|
|
||||||
|
if (teleportThroughVoidFloor) {
|
||||||
|
entity.teleportVoidFloorFix(false);
|
||||||
|
} else if (mustResyncPosition) {
|
||||||
|
entity.teleportVoidFloorFix(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
session.getInputCache().markPositionPacketSent();
|
||||||
|
session.getSkullCache().updateVisibleSkulls();
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.setPositionManual(packet.getPosition());
|
|
||||||
|
|
||||||
// Send final movement changes
|
|
||||||
session.sendDownstreamGamePacket(movePacket);
|
|
||||||
|
|
||||||
if (teleportThroughVoidFloor) {
|
|
||||||
entity.teleportVoidFloorFix(false);
|
|
||||||
} else if (mustResyncPosition) {
|
|
||||||
entity.teleportVoidFloorFix(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
session.getInputCache().markPositionPacketSent();
|
|
||||||
session.getSkullCache().updateVisibleSkulls();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not a valid move
|
// Not a valid move
|
||||||
|
|||||||
Reference in New Issue
Block a user