Shooter: lag-compensated hits

Click inside the arena to shoot. The server rewinds every candidate to the instant you rendered it and tests the ray there (live.smooth({ hitTest })) - so a shot that landed on your screen lands on the server. The window it covers is the one it measured itself - your real uplink and interpolation - capped by maxRewindMs: 400. Crank the latency slider and the compensation does not follow it: a shot is stamped when its send leaves, so the wait ages your aim rather than widening the rewind.

you

WASD / arrows to move; click the arena or press Space to shoot.

Touch controls

Score

0

Authoritative: onHit credits the shooter through the shared apply (ctx.applyTo), so this number is the server's answer, not a local guess.

hp: 3

shots fired: 0

hit events seen: 0

Extra latency: 0ms

Delays your shots with a setTimeout wrapper - movement stays predicted and immediate, so your own dot never lags your keys. The shot fires (and the muzzle flash draws) when the send actually leaves, and the render-time it carries is stamped at that moment - so the server rewinds to when the send left, not to when you clicked. Your aim keeps ageing during the wait while the compensation does not grow to match, so aimed shots start to miss as you drag this up. That is the honest half of the fairness rule: the rewind is measured from your real uplink and interpolation, and a delay you invent locally is not latency you earned.