guest@6admin.io:~$

A DayZ autowalker in Java: decompile, patch for AZERTY, fork afterwards

Back in the DayZ days, I wanted an autowalker, that little utility that holds the forward key for you while your character crosses a huge map. One existed, in Java, but with no published sources and it was built for a QWERTY keyboard. I play on AZERTY, so it walked sideways and I also wanted it to handle the running state cleanly rather than jam a key. I did not overthink it: I decompiled it.

JavaDecompiler, or “compiled” does not mean “closed”

A .jar is bytecode and Java bytecode decompiles almost back to the original source. One pass through JavaDecompiler (JD, the tool of the time) and I had readable code, method names included, ready to repatch. That is the real lesson of the story, the same one I keep repeating elsewhere: shipping a binary is not shipping a secret, it is shipping the source with one extra step and conflating the two is a bet (security through obscurity is not security ). Distributing an autowalker as a “compiled” .jar was distributing its code, full stop.

What the thing actually did

Rereading the source, the setup is honest for the job:

  • a global keyboard hook via JNativeHook, to catch a key even while the game has focus;
  • a context guard via JNA on user32, GetForegroundWindow then GetWindowTextA, to fire only if the foreground window title contains DayZ and stay inert everywhere else;
  • and a java.awt.Robot doing the keyPress then keyRelease of the movement key, driven by a state boolean, one tap to start walking, another to stop.

My patches, the AZERTY side

This is where my fork diverges from the original. The forward key held by the Robot becomes walkKey = 90, that is the Z key, the forward of AZERTY’s ZQSD, where the original QWERTY pushed a W. I added separate handling for running, two distinct states, walk and sprint, each with its own toggle and its own keyPress/keyRelease, so a key no longer stays stuck. And I redid the interface in French, down to the Status: Actif button that turns red Inactif, with my old domain autowalker.vhalholl.info hardcoded in the credit label, a detail that dates the thing better than a signature.

Decompile first, fork afterwards

The end of the story is the silliest and the most instructive. After patching my decompiled copy on my own, I eventually found the original source published on GitHub, the one by feonx , so I forked it and pushed my modifications on top (my fork ). In other words, I had started on the worst path, a decompiled blob patched by hand with no history, before coming back to the right one, a versioned fork of a real source. It is exactly the anti-pattern I mock elsewhere, code without a repository that does not outlive the job that wrote it, except this time the culprit was me and the moral fits in one line: decompile if you want, but always end up in a repository.