Summary
The server judges every sword hit and bullet against where fighters are now,
not where the attacker saw them. Remote fighters are rendered by rollback
prediction at the present instant, which is a large improvement over the old
150ms interpolation delay, but prediction is not the same as truth: a fighter
seen at the present predicted position is still resolved against the
authoritative one.
Untested against real latency. Everything measured so far is localhost, where
rollback.avgLeadTicks is around 1 and the difference is invisible.
Why it matters now
Real players, on real connections, are the first case where this bites — and the
symptom is the most demoralising one in any online game: "I hit them and
nothing happened." A player at 80ms sees an opponent roughly 5 ticks ahead of
where the server will resolve their swing, which at walk speed is ~18px and at
dash speed ~80px. The sword's reach is not large compared to that.
What exists already
The netcode is unusually well placed to add this:
- The simulation is deterministic and shared, so re-simulating a past tick is the
same code path as any other tick.
- Snapshots already carry a server
tick, and inputs already carry a seq, so
the server knows exactly which tick a client's input was formed against.
netSummary.rollback already reports how far ahead each client is running.
The missing piece is a short ring buffer of past authoritative states per fighter
and resolving an attack against the tick the attacker actually saw.
Constraints
- Favour-the-shooter has a victim. Rewinding means a player who has already
broken line of sight can still be hit, which is its own complaint. The trade is
a design decision, not a technical one, and belongs in specs/netcode.md
before it is built.
- Cap the rewind. Beyond ~150-200ms it stops being fairness and starts being a
reward for a bad connection.
- Measure it.
deathmatch-probe.mjs and diagnose.mjs both run on localhost,
so neither can see this. Artificial latency is needed before any of it can be
called fixed — Chromium's CDP supports network emulation, and that plumbing does
not exist yet.
Definition of done
- A decision in
specs/netcode.md on whether hits favour the shooter, with the
rewind cap written down.
- A way to run the harness under simulated latency, and a measurement of hit
registration before and after at a couple of representative pings.
specs/netcode.md "Not implemented" updated.
Notes
Currently listed under "Not implemented" in specs/netcode.md. Filing it as an
issue because it is the most likely complaint from the first session with real
people, and it is worth having the trade written down before anyone reacts to
that complaint under pressure.
Summary
The server judges every sword hit and bullet against where fighters are now,
not where the attacker saw them. Remote fighters are rendered by rollback
prediction at the present instant, which is a large improvement over the old
150ms interpolation delay, but prediction is not the same as truth: a fighter
seen at the present predicted position is still resolved against the
authoritative one.
Untested against real latency. Everything measured so far is localhost, where
rollback.avgLeadTicksis around 1 and the difference is invisible.Why it matters now
Real players, on real connections, are the first case where this bites — and the
symptom is the most demoralising one in any online game: "I hit them and
nothing happened." A player at 80ms sees an opponent roughly 5 ticks ahead of
where the server will resolve their swing, which at walk speed is ~18px and at
dash speed ~80px. The sword's reach is not large compared to that.
What exists already
The netcode is unusually well placed to add this:
same code path as any other tick.
tick, and inputs already carry aseq, sothe server knows exactly which tick a client's input was formed against.
netSummary.rollbackalready reports how far ahead each client is running.The missing piece is a short ring buffer of past authoritative states per fighter
and resolving an attack against the tick the attacker actually saw.
Constraints
broken line of sight can still be hit, which is its own complaint. The trade is
a design decision, not a technical one, and belongs in
specs/netcode.mdbefore it is built.
reward for a bad connection.
deathmatch-probe.mjsanddiagnose.mjsboth run on localhost,so neither can see this. Artificial latency is needed before any of it can be
called fixed — Chromium's CDP supports network emulation, and that plumbing does
not exist yet.
Definition of done
specs/netcode.mdon whether hits favour the shooter, with therewind cap written down.
registration before and after at a couple of representative pings.
specs/netcode.md"Not implemented" updated.Notes
Currently listed under "Not implemented" in
specs/netcode.md. Filing it as anissue because it is the most likely complaint from the first session with real
people, and it is worth having the trade written down before anyone reacts to
that complaint under pressure.