Short description of the issue
In 26.3, delayed block breaking uses the player's absolute tick count at mining start instead of elapsed mining time. This causes blocks to break prematurely or progress to stall.
Steps to reproduce the issue
In Survival mode, select a block that cannot be instantly mined with the held tool.
Using a modified client or test harness, send
START_DESTROY_BLOCKimmediately followed bySTOP_DESTROY_BLOCKfor the same block.Test with both a player who has been online longer than the block's normal mining duration and a fresh player whose online time is shorter. Keep mining conditions unchanged and allow sufficient time for normal breaking to finish.
Expected result
Delayed breaking progresses according to time spent mining the target, independently of how long the player existed before mining began.
Actual result
With a sufficiently high player tick count, the block breaks on the next tick despite no pre-mining. With a low tick count, progress remains constant and waiting does not complete the break. A stalled operation can also block subsequent delayed-breaking attempts.
Attachments
Comments 2
Found this issue independently and after some tinkering I found that it allows you to break pretty much any block instantly once the ticks accumulate. This looks to be caused by vanilla changing the argument of ServerPlayerGameMode#incrementDestroyProgress from taking starting time to taking a time spent, while forgetting to update one of the calls of this method.
See https://mcsrc.dev/2/diff/26.2/26.4-snapshot-3/net/minecraft/server/level/ServerPlayerGameMode#R119 for reference
Attaching a reproduction kit (
MC-311994_repro_kit.zip, ~37 KB, Python source only, no binaries) that reproduces both halves of this issue against an unmodified vanilla 26.3 server in one command.Contents
repro_mc311994.py– joins the server as a minimal offline-mode client (fake_player.py, Python 3.10+, standard library only), places a stone block, waits until the player's tick counter exceeds the block's mining time, then sendsSTART_DESTROY_BLOCKimmediately followed bySTOP_DESTROY_BLOCK. The result is derived from the server's ownblock_updatepackets. With--stallit then joins a second, fresh player and repeats the sequence to show the stalled case.Two console logs from the original test runs (format explained in the README).
README.mdwith server settings, usage, expected output, and pointers to the relevant code.How to run (throwaway test server with
online-mode=falseandnetwork-compression-threshold=-1):Op the player when the script asks for it.
Result on 26.3
On a correct build the first block should still be there 3 s after STOP, and the fresh player's block should break after ~7.5 s.
In normal play this path is hit whenever the server's mining progress lags the client's (e.g. low TPS), so it is not limited to modified clients.