Netcode

Server-authoritative combat, client-predicted movement

Two problems that most servers treat as one. Damage validation belongs on the server. Movement does not.

Commitments

Three things this server will not trade away

Hit validation on the server

Damage is validated by MatchServer against a rewind snapshot buffer, so a hit is judged against where your target actually was at the moment you fired — not against whatever a peer claims. Direct client-to-client damage application is being stripped out.

StatusIn migration

K-Style is untouched

Butterfly, half-step, slash shot, reload shot, wall canceling, dash canceling. Movement and animation cancels stay client-predicted, with the original frame delays intact. Zero added input latency, and no “fixes” to timings the technique depends on.

StatusLocked

One stat block per class

Every weapon in a class carries the same damage, delay, magazine and reload. Within a class only the mesh differs, so a cosmetic can never be an edge. No donor stats, no custom weapons, no reskins with numbers attached, no stat item behind a payment. Nothing you can buy changes a fight.

StatusLocked

The legacy model

In the original build, the match server handles the lobby, the room list, the stage and the scoreboard. It does not decide who dies. Once a match starts, clients talk to each other directly over UDP, and the messages they exchange include the ones that apply damage.

That design was reasonable in 2006 and it produces two failures that every GunZ player recognises:

  • The connection decides the fight. Two clients disagree about where each other are. Whoever's view of the world is more delayed loses hits they saw connect, and takes hits from angles that never happened on their screen.
  • Damage is a claim, not a fact. If a peer says it hit you, the legacy path largely believes it. Editing that claim is the single most common GunZ cheat and it has never had a real answer on a peer-to-peer damage model.

Where authority moves

Direct client-to-client damage application is being removed. Instead of a peer telling you that you took damage, a client reports a shot: the weapon, the origin, the direction, and the client's own timestamp. The server decides whether that shot hit anything.

Validation happens against the server's own record of the world, not against anything the shooter asserts about the target. A rejected shot does nothing. An accepted shot produces damage that the server applies and both clients are told about.

The distinction that matters: the client still decides when you fire. It no longer decides whether you hit.

Lag compensation

Server authority without lag compensation is worse than no authority at all, because every player would have to lead their shots by their own ping. The server therefore keeps a short history of where every player has been — a rewind snapshot buffer.

When a shot arrives, the server reconstructs the world as the shooter saw it. It rewinds by the shooter's own measured round trip — the world the server had already delivered to them is everything that left here at least one round trip ago — and checks the shot against the positions that were on the shooter's screen at that instant. Positions between two stored snapshots are interpolated rather than snapped, so the reconstruction is smooth rather than stepped.

That rewind is measured, never claimed. The shot carries the client's own timestamp and the server does not resolve against it. A client that gets to nominate the moment its shot is judged against will nominate a favourable one, so the timestamp is kept only to log the skew between what the client claimed and what the server measured. The one lever a modified client has left is inflating its own ping by delaying pongs, and the rewind window is bounded: a rewind further back than the buffer holds is clamped rather than extrapolated.

Server-side rewind

Three views of one instant: the shooter's screen, the server's present, and the server rewound by one round trip.

What you saw when you fired

Hit

The server's present, one round trip later

target has moved

Miss

The server, rewound by your measured round trip

rewound

Hit

The shot is tested against the third row, not the second. Without the rewind every player would have to lead by their own ping; with it, what was on your screen is what the server checks. The rewind comes from the round trip the server measured, never from a moment the client asked for. The arrow in the second row is the target moving during that trip; in the third it is the server putting it back.

What stays untouched

Movement, animation cancels and weapon switching remain client-predicted and locally authoritative. Nothing has been inserted between your input and the animation, and nothing will be.

This is not an oversight to be tidied up later. K-Style exists because of specific animation-cancel delays and state overrides in the original code. Treating those as bugs and fixing them is how a GunZ server becomes a different game:

  • Butterfly — slash cancelled into a dash, repeatedly.
  • Half-step — the shortened dash that comes from cancelling the dash animation early.
  • Slash shot and reload shot — the weapon-switch timing windows.
  • Wall canceling and dash canceling — state overrides on contact and on input.

None of these are validated by the server, delayed pending confirmation, or rewritten. The frame delays they depend on are treated as part of the specification.

What that costs

Being honest about the trade: because movement is client-authoritative, a modified client can still move in ways it should not. That is a detection problem, not a simulation problem, and it is answered with plausibility checks and observation rather than by taking control of movement away from the client. Given the choice between a server that catches every possible movement exploit and a server where butterfly feels right, this one picks the second.

Cheating

Moving damage to the server removes an entire class of cheat outright. A client that claims damage no longer gets it, because nothing on the server reads that claim any more.

What remains is aim assistance and movement manipulation. Those are handled by server-side plausibility checks on the shot stream and the movement stream, combined with the fact that a small competitive population notices. There is no kernel-level anticheat and there will not be one.

Status

This work is in progress and this page describes where it is going. The current state, plainly:

Shot validationImplemented on the server for melee and ranged weapons, running in the live build.
Rewind bufferImplemented. Snapshot history with interpolated reconstruction; window size is being tuned against real latency spreads.
Peer damage pathStill present in the client for compatibility during the migration. Being removed.
Rejection loggingImplemented, opt-in. Every hit test can write its outcome and reason code — wall, out of range, out of cone, guarded, rate-limited — alongside the rewind it resolved with. Off by default because one shotgun blast is twelve lines; switched on per match to settle a disputed round.
Movement authorityClient. Unchanged, and not scheduled to change.

Patch notes