blog > Minecraft: removing 4 tick mining delay (14 May 2020)
Every once in a while I return to playing Minecraft. One thing I always tend to do is removing a 4-tick delay between mining blocks. Usually there should be 20 ticks per second, meaning there's 50ms between ticks. So after breaking a block, there is a 200ms delay before the next block will start to be mined. Since I usually spend most of my time mining, this delay frustrates me quite a bit. Even if you have a pickaxe that breaks a block as good as instantly, you'd still have to wait for those annoying 200ms for every block.
Years ago, in a previous life,
I used MCP (which stood for Minecraft Coder Pack) to decompile minecraft.
There I found how to remove the delay, by setting the blockHitDelay
to 0
in PlayerControllerMP#onPlayerDamageBlock
.
It usually takes a while for MCP to get updated for newer versions,
and nowadays I don't even try to find updated version anymore since at
some point it started to get impossible to find them
(it may not even exist anymore now and/or be replaced with something else).
So the way I've been doing it now is to find the class, edit the value and recompile it. Then attach a debugger to the running JVM instance and hot-swap the class.
To begin, we would need to find the class.
Most identifiers are usually minified, so this can be done by searching for a pattern.
I saw this code in the (older versions) of the class we need,
and thought maybe the 4.5
value would be easy to find.
public float getBlockReachDistance() { return !creativeMode ? 4.5F : 5F; }
The JVM specs for CONSTANT_Float_info structure
tells us that a float constant consists of a byte with value 4
,
followed by the float value in IEEE-754 format, big endian.
So, find the jar (in my case %APPDATA%\.minecraft\versions\20w20b\20w20b.jar
),
extract it somewhere and grep for our pattern.
$ find . -name "*.class" | xargs grep -obUaP "\x04\x40\x90\x00\x00" ./azg.class:2765:@P ./dls$a.class:1083:@P ./dvt.class:348:@P ./dwx.class:591:@P ./dxn.class:1969:@P ./ebd$m.class:1185:@P ./efs.class:277:@P ./eik.class:724:@P
Note: I get can't this to work anymore. The grep options seem correct and should work but alas. An alternative for windows is BareGrep by baremetalsoft.com, it works with the same pattern if the regex checkbox is checked.
There aren't too many matches,
so it's doable to go through every one of them with your favorite decompiler
and see if it's the target class. In dxn.class
, I found following
method which sort of looks like the getBlockReachDistance()
method we're trying to find.
public float c() { return this.j.e() ? 5.0F : 4.5F; }
So this is the class that we need and will modify and hot-swap.
Copy the contents of that class file and copy it into a source file in a project in your favorite IDE, with the same name. One method up is this method:
public boolean b(ft var1, fy var2) { this.n(); if (this.h > 0) { --this.h; return true; } else { cel var3; (..)
That if
is checking the block hit delay,
so I put this line above the if
to get rid of the block hit delay.
this.h = 0;
To compile the file you probably need to link the jar and some libraries,
which can usually be found in %APPDATA%\.minecraft\libraries
.
The file %APPDATA%\.minecraft\versions\<version>\<version>.json
has a "libraries" property that should help with the names and versions.
I used Fernflower to decompile and had to fix some usages of an enum.
For some reason it added an import for rz.a
but the compiler wasn't accepting it,
so I removed the import and replace all usages of the enum type a
in method parameters with rz.a
.
One time for version 1.18.2, the class contained the line below. That won't compile
because it's calling a method named do
, which of course is a keyword
in Java (the reason that it's there is because the JVM has less constrains on naming
than the Java programming language, so modifications to bytecode can make it that
decompiled class files to Java source files may not be compilable).
Luckily I could comment this line and the game doesn't seem different in
any way or crashing, so I got lucky there.
this.c.a(new wb.b($$0.dc(), $$0.de(), $$0.di(), $$0.dn(), $$0.do(), $$0.aw()));
The next step is to add some arguments to Minecraft to enable debugging, it doesn't seem too hard to do with the new launcher. I added following arguments:
-Xdebug -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1052
Then simply launch the game, attach the debugger of your favorite IDE and hot-swap the class.