Skip to content

No lag compensation: the server resolves hits against present positions #19

Description

@WilsonNet

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions