@@ -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