Anti-desync toolchain for Project Zomboid Build 42 multiplayer.
Drift, as in simulation drift: two machines running the same world and slowly disagreeing about where things are. Knox County is where it happens.
PZ simulates vehicle physics client-authoritatively. BaseVehicle.Authorization has
the values Server, LocalCollide, RemoteCollide, Local, Remote, and exactly one
client runs the Bullet simulation for any given vehicle — normally the driver. Everyone
else follows.
That is not a bug, it is the architecture. And it means that when two players have different FPS and different ping, their simulations diverge by construction. A Indie Stone moderator says as much: "Vehicles are fairly sensitive to FPS and Ping — if you and your friends have wildly different pings and FPS, there will be problems with synchronizing."
Build 42 went stable on 29 July 2026 with 42.20, which reworked the NetworkState system and moved inventory and TimedActions server-side. Desync is better. It is not gone — the bug tracker still carries [42.20] The desynchronization continues…
Three phases, each shippable on its own, each gating the next.
| Phase | Status | |
|---|---|---|
| 1 | DesyncScope — measure. Position divergence, packet census, wire reliability profile. Changes nothing. | done, untested in-game |
| 2 | Correct. RakNet reliability tuning on UdpConnection.endPacket*, plus BeamMP-style soft correction for vehicles. |
not started |
| 3 | Own the stack. Only if Phase 1 data justifies it — see docs/02. | conditional |
Phase 1 comes first because a fix you cannot measure is a guess. Desync is ping- and FPS-dependent enough that subjective "feels better" is worthless as evidence, and the failure mode of netcode work is shipping a change that helps on your machine and hurts on everyone else's.
Asked and answered in docs/02. Short version:
- Lua cannot load native code. PZ runs Kahlua2, a Lua 5.1 VM written in Java. No
package.loadlib, no FFI, noio, no sockets. Not disabled — absent. - The determinism argument died with JDK 17. JEP 306
restored always-strict IEEE-754 floating point. Java is already platform-deterministic
for arithmetic;
StrictMathcloses the gap for transcendentals. And you cannot make Bullet deterministic anyway, in any language. - Performance is not the bottleneck. The correction maths is a few dozen flops per vehicle per tick.
- The strongest lever is already in Java.
UdpConnectionexposesendPacket(priority, reliability, ordering)over RakNet's fullPacketPriority_*/PacketReliability_*range — the same layer BetterNetworking operates on in Valheim.
Rust stays on the table for Phase 3, and if it happens it will be a sidecar daemon with its own UDP channel, not a JNI library. A segfault in JNI takes the whole JVM down without a Java stack trace; for a game mod that means crash reports nobody can debug.
DesyncScope/ Phase 1 mod - drop this folder into <Zomboid>/mods/
docs/ Research that produced the plan (German)
docs/01— B42 MP state of play, root-cause analysis, what every netcode technique is worth here, competitor and prior-art surveydocs/02— carrier paths for native code, verified against cloned source rather than blog posts
Docs are in German, code and mod documentation in English.
- Project Zomboid Build 42 (developed against 42.20, Java 17)
- ZombieBuddy ≥ 1.6.0
Phase 1 compiles clean under -Xlint:all --release 17 and passes 40 offline checks
covering percentile maths, window eviction, census counting, divergence filtering, CSV
format, report rendering and the reflection layer's failure modes.
It has never run against a live JVM. First launch should use
DesyncScope.setVerbose(true), which logs every game symbol the reflection layer could
not resolve. If a signature differs in your build, that is where it shows up.
- BeamMP —
positionVE.luais the reference implementation for vehicle soft correction: clock sync, second-order dead reckoning capped at 0.3 s, force-based correction with saturation and anti-windup, staged speed-dependent hard snap - OpenRA —
Sync.cs/SyncReport.cs, the best open-source desync detection there is: hash to detect, field dump to localise - BetterNetworking (Valheim) — proof that touching only transport parameters can be enough
- se-performance-improvements — the governance model to copy: every fix individually switchable, conservative defaults, new fixes off by default
MIT. See LICENSE.