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:
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
|
||||
Reference in New Issue
Block a user