Skip to content

Commit abf3f95

Browse files
authored
Fix Bedrock block placement rollback when quick place and scaffolding-style bridging (#6310)
* Fix: block place restore * Fix: scaffolding-style bridging block restore * Add client version test notes for fixCursorValue method
1 parent fc2681a commit abf3f95

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

core/src/main/java/org/geysermc/geyser/session/GeyserSession.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
510510
@Setter
511511
private Vector3i lastInteractionBlockPosition = Vector3i.ZERO;
512512

513+
@Setter
514+
private int lastInteractionBlockFace = -1;
515+
513516
/**
514517
* Stores the Java position of the player the last time they interacted.
515518
* Used to verify that the player did not move since their last interaction. <br>

core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,12 @@ public void translate(GeyserSession session, InventoryTransactionPacket packet)
193193
// Check to make sure the client isn't spamming interaction
194194
// Based on Nukkit 1.0, with changes to ensure holding down still works
195195
boolean hasAlreadyClicked = System.currentTimeMillis() - session.getLastInteractionTime() < 110.0 &&
196-
packetBlockPosition.distanceSquared(session.getLastInteractionBlockPosition()) < 0.00001;
196+
packetBlockPosition.distanceSquared(session.getLastInteractionBlockPosition()) < 0.00001 &&
197+
packet.getBlockFace() == session.getLastInteractionBlockFace();
197198
session.setLastInteractionBlockPosition(packetBlockPosition);
198199
session.setLastInteractionPlayerPosition(session.getPlayerEntity().position());
200+
session.setLastInteractionBlockFace(packet.getBlockFace());
201+
199202
if (hasAlreadyClicked) {
200203
session.getPlayerInventoryHolder().updateSlot(session.getPlayerInventory().getOffsetForHotbar(packet.getHotbarSlot()));
201204
break;
@@ -236,9 +239,13 @@ public void translate(GeyserSession session, InventoryTransactionPacket packet)
236239
return;
237240
}
238241

239-
double clickPositionFullX = (double) packetBlockPosition.getX() + (double) packet.getClickPosition().getX();
240-
double clickPositionFullY = (double) packetBlockPosition.getY() + (double) packet.getClickPosition().getY();
241-
double clickPositionFullZ = (double) packetBlockPosition.getZ() + (double) packet.getClickPosition().getZ();
242+
float cursorX = fixCursorValue(packet.getClickPosition().getX());
243+
float cursorY = fixCursorValue(packet.getClickPosition().getY());
244+
float cursorZ = fixCursorValue(packet.getClickPosition().getZ());
245+
246+
double clickPositionFullX = (double) packetBlockPosition.getX() + (double) cursorX;
247+
double clickPositionFullY = (double) packetBlockPosition.getY() + (double) cursorY;
248+
double clickPositionFullZ = (double) packetBlockPosition.getZ() + (double) cursorZ;
242249

243250
Vector3f blockCenter = Vector3f.from(packetBlockPosition.getX() + 0.5f, packetBlockPosition.getY() + 0.5f, packetBlockPosition.getZ() + 0.5f);
244251

@@ -281,7 +288,7 @@ public void translate(GeyserSession session, InventoryTransactionPacket packet)
281288
packet.getBlockPosition(),
282289
Direction.getUntrusted(packet, InventoryTransactionPacket::getBlockFace).mcpl(),
283290
Hand.MAIN_HAND,
284-
packet.getClickPosition().getX(), packet.getClickPosition().getY(), packet.getClickPosition().getZ(),
291+
cursorX, cursorY, cursorZ,
285292
false,
286293
false,
287294
sequence);
@@ -606,4 +613,28 @@ private boolean useItem(GeyserSession session, InventoryTransactionPacket packet
606613
session.useItem(Hand.MAIN_HAND, useTouchRotation);
607614
return true;
608615
}
616+
617+
/*
618+
* In Bedrock Edition behavior(scaffolding-style bridging), the cursor position (packet.getClickPosition())
619+
* is based on the player's foot position.
620+
*
621+
* When performing speed bridging (running/jumping while placing blocks), if there is a wall ahead,
622+
* and the last 1–3 blocks are about to touch or are already touching the wall, the click position
623+
* in that direction may become values like -1, -1.5, -2, 2, or 3.
624+
*
625+
* However, the normal max range should be between -0.5 and 1.5 (in java server that will not cancel place), so a temporary restriction is applied.
626+
*
627+
* This is a temporary fix, but I don’t have a better idea for now...
628+
*
629+
* Test with client version: 1.21.5x, 1.21.9x, 26.21.
630+
*/
631+
private float fixCursorValue(float value) {
632+
if (value <= -0.5f) {
633+
return -0.25f;
634+
} else if (value >= 2.0f) {
635+
return 1.25f;
636+
} else {
637+
return value;
638+
}
639+
}
609640
}

0 commit comments

Comments
 (0)