Skip to content

Server-authoritative damage validation + death broadcast#20

Open
constripacity wants to merge 1 commit into
mainfrom
feat/server-authoritative-damage
Open

Server-authoritative damage validation + death broadcast#20
constripacity wants to merge 1 commit into
mainfrom
feat/server-authoritative-damage

Conversation

@constripacity
Copy link
Copy Markdown
Member

@constripacity constripacity commented May 30, 2026

Problem

Combat was both broken and trivially cheatable. The server logged damage (case 2) and death (case 3) but never relayed them, so:

  • nobody ever took damage or died, and
  • a hand-written client could claim any damage (e.g. 99999) and the server believed it.

Fix the server now owns combat

  • Validates every damage event before it counts: rejects damage > MAX_DAMAGE (200), self-damage, unknown players, non-positive values. Rejections log as [ANTICHEAT] REJECTED ... and the victim never takes the hit.
  • Relays only validated damage to the victim (protocol 2 / argument 4) → real combat works.
  • Broadcasts death (protocol 2 / argument 5) and tallies kills/deaths.

No client change required the client already handles arguments 4 and 5 (DamageReceived, PlayerDied).

Why it matters

This defeats a protocol-level cheat (spoofed one-shots) that client integrity / EAC cannot stop, because the attacker never runs the game binary. Verified live: a PoC sending 99999 got 8/8 hits rejected; the real player survived; legitimate player-vs-player combat works and kills register.

Scope (v1) + follow-ups

This PR is damage authority. Deliberately out of scope (TODO in code):

  • server-owned HP (stops god-mode-by-ignoring-damage),
  • per-weapon damage caps (vs a single global cap),
  • distance / line-of-sight + fire-rate checks,
  • real per-connection auth (currently a shared magic constant),
  • the ProcessPacket one-packet-per-read framing fix (coalesced packets parse as garbage; currently dropped harmlessly as 0-damage).

Combat was unplayable and trivially cheatable: the server logged damage
(case 2) and death (case 3) but never relayed them, so no one took damage
or died, and a hand-written client could claim any damage value.

Now the server owns combat:
- validates every damage event before it counts -- rejects damage above
  MAX_DAMAGE (200), self-damage, unknown players, non-positive values
  (logged as [ANTICHEAT] REJECTED ...);
- relays only validated damage to the victim (protocol 2 / argument 4),
  so real combat works;
- broadcasts death (protocol 2 / argument 5) and tallies kills/deaths.

No client change required -- the client already handles arguments 4 and 5.
Defeats a protocol-level cheat (spoofed 99999 one-shots) that client
integrity / EAC cannot, since the attacker never runs the game binary.

Scope (v1): damage authority. Follow-ups: server-owned HP (stops
god-mode-by-ignoring-damage), per-weapon caps, distance/LoS + fire-rate
checks, real auth, and the one-packet-per-read framing fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant