1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2026-01-04 15:31:36 +00:00

Fix: water bucket placing on mobile devices (#5590)

* Fixed water placing.

* Don't send ServerboundUseItemOnPacket when you're already sending ServerboundUseItemPacket

* Fixed wrong comment placement.

* Requested changes.

* Move this code back to the right place.

* Again, move this code to the right place.

* Removed lookBackScheduledFuture.
This commit is contained in:
oryxel
2025-07-17 20:36:44 +07:00
committed by GitHub
parent 26f283f421
commit 1748daa1ed
4 changed files with 11 additions and 75 deletions

View File

@@ -109,6 +109,12 @@ public class SessionPlayerEntity extends PlayerEntity {
@Getter @Setter
private Vector3f lastTickEndVelocity = Vector3f.ZERO;
/**
* The client claimed interact rotation, intended for touch (pocket) user.
*/
@Getter @Setter
private Vector2f bedrockInteractRotation = Vector2f.ZERO;
/**
* Determines if our position is currently out-of-sync with the Java server
* due to our workaround for the void floor

View File

@@ -684,12 +684,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
@Setter
private long worldTicks;
/**
* Used to return the player to their original rotation after using an item in BedrockInventoryTransactionTranslator
*/
@Setter
private ScheduledFuture<?> lookBackScheduledFuture = null;
/**
* Used to return players back to their vehicles if the server doesn't want them unmounting.
*/
@@ -1397,8 +1391,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
return;
}
sendDownstreamGamePacket(new ServerboundUseItemPacket(
hand, worldCache.nextPredictionSequence(), playerEntity.getYaw(), playerEntity.getPitch()));
sendDownstreamGamePacket(new ServerboundUseItemPacket(hand, worldCache.nextPredictionSequence(), playerEntity.getBedrockInteractRotation().getY(), playerEntity.getBedrockInteractRotation().getX()));
}
public void releaseItem() {

View File

@@ -633,67 +633,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
}
}
Vector3f target = packet.getBlockPosition().toFloat().add(packet.getClickPosition());
lookAt(session, target);
session.useItem(Hand.MAIN_HAND);
return true;
}
/**
* Determine the rotation necessary to activate this transaction.
* <p>
* The position between the intended click position and the player can be determined with two triangles.
* First, we compute the difference of the X and Z coordinates:
* <p>
* Player position (0, 0)
* |
* |
* |
* |_____________ Intended target (-3, 2)
* <p>
* We then use the Pythagorean Theorem to find the direct line (hypotenuse) on the XZ plane. Finding the angle of the
* triangle from there, closest to the player, gives us our yaw rotation value
* Then doing the same using the new XZ distance and Y difference, we can find the direct line of sight from the
* player to the intended target, and the pitch rotation value. We can then send the necessary packets to update
* the player's rotation.
*
* @param session the Geyser Session
* @param target the position to look at
*/
private void lookAt(GeyserSession session, Vector3f target) {
// Use the bounding box's position since we need the player's position seen by the Java server
Vector3d playerPosition = session.getCollisionManager().getPlayerBoundingBox().getBottomCenter();
float xDiff = (float) (target.getX() - playerPosition.getX());
float yDiff = (float) (target.getY() - (playerPosition.getY() + session.getEyeHeight()));
float zDiff = (float) (target.getZ() - playerPosition.getZ());
// First triangle on the XZ plane
float yaw = (float) -Math.toDegrees(Math.atan2(xDiff, zDiff));
// Second triangle on the Y axis using the hypotenuse of the first triangle as a side
double xzHypot = Math.sqrt(xDiff * xDiff + zDiff * zDiff);
float pitch = (float) -Math.toDegrees(Math.atan2(yDiff, xzHypot));
SessionPlayerEntity entity = session.getPlayerEntity();
ServerboundMovePlayerPosRotPacket returnPacket = new ServerboundMovePlayerPosRotPacket(entity.isOnGround(), session.getInputCache().lastHorizontalCollision(),
playerPosition.getX(), playerPosition.getY(), playerPosition.getZ(), entity.getYaw(), entity.getPitch());
// This matches Java edition behavior
ServerboundMovePlayerPosRotPacket movementPacket = new ServerboundMovePlayerPosRotPacket(entity.isOnGround(), session.getInputCache().lastHorizontalCollision(),
playerPosition.getX(), playerPosition.getY(), playerPosition.getZ(), yaw, pitch);
session.sendDownstreamGamePacket(movementPacket);
if (session.getLookBackScheduledFuture() != null) {
session.getLookBackScheduledFuture().cancel(false);
}
if (Math.abs(entity.getYaw() - yaw) > 1f || Math.abs(entity.getPitch() - pitch) > 1f) {
session.setLookBackScheduledFuture(session.scheduleInEventLoop(() -> {
Vector3d newPlayerPosition = session.getCollisionManager().getPlayerBoundingBox().getBottomCenter();
if (!newPlayerPosition.equals(playerPosition) || entity.getYaw() != returnPacket.getYaw() || entity.getPitch() != returnPacket.getPitch()) {
// The player moved/rotated so there is no need to change their rotation back
return;
}
session.sendDownstreamGamePacket(returnPacket);
}, 150, TimeUnit.MILLISECONDS));
}
}
}

View File

@@ -49,6 +49,10 @@ final class BedrockMovePlayer {
SessionPlayerEntity entity = session.getPlayerEntity();
if (!session.isSpawned()) return;
// We need to save player interact rotation value, as this rotation is used for Touch device and indicate where the player is touching.
// This is needed so that we can interact with where player actually touch on the screen on Bedrock and not just from the center of the screen.
entity.setBedrockInteractRotation(packet.getInteractRotation());
// Ignore movement packets until Bedrock's position matches the teleported position
if (session.getUnconfirmedTeleport() != null) {
session.confirmTeleport(packet.getPosition().toDouble().sub(0, EntityDefinitions.PLAYER.offset(), 0));
@@ -79,13 +83,6 @@ final class BedrockMovePlayer {
boolean positionChangedAndShouldUpdate = !hasVehicle && (session.getInputCache().shouldSendPositionReminder() || actualPositionChanged);
boolean rotationChanged = hasVehicle || (entity.getYaw() != yaw || entity.getPitch() != pitch || entity.getHeadYaw() != headYaw);
if (session.getLookBackScheduledFuture() != null) {
// Resend the rotation if it was changed by Geyser
rotationChanged |= !session.getLookBackScheduledFuture().isDone();
session.getLookBackScheduledFuture().cancel(false);
session.setLookBackScheduledFuture(null);
}
// Simulate jumping since it happened this tick, not from the last tick end.
if (entity.isOnGround() && packet.getInputData().contains(PlayerAuthInputData.START_JUMPING)) {
entity.setLastTickEndVelocity(Vector3f.from(entity.getLastTickEndVelocity().getX(), Math.max(entity.getLastTickEndVelocity().getY(), entity.getJumpVelocity()), entity.getLastTickEndVelocity().getZ()));