AoI: line-of-sight filter (don't stream entities through walls) #150

Closed
opened 2026-07-22 16:45:39 +02:00 by marco · 1 comment
Owner

Discovered by the PvP-arena design review (#109). The server streams every entity within the AoI Chebyshev radius (PlayersWithin(pos, radius) / InterestManager / InterestDiff) regardless of walls — it filters on distance, not line of sight. So a modified client sees enemy positions through walls and cover, defeating any cover/LoS play (the arena's whole point) and breaking the server-authoritative fairness pillar.

Fix

Add a line-of-sight filter to AoI membership: an observer is only sent an entity it has TileMap.HasLineOfSight to (in addition to being in range). Entering/leaving LoS reconciles like entering/leaving range (spawn/remove). Compatible with the 'broadcasts carry absolute positions' invariant — this is a membership change, not a delta change.

Notes

  • Keep it single-threaded on the sim (AoI already reconciles per tick).
  • Tune cost: LoS check only for in-range candidates; friends-scale so N is small.
  • Interaction with hearing/say (AoI-scoped chat): decide whether chat still carries through walls (probably yes — you hear a shout you don't see). Scope this issue to visual entity reconciliation.

Definition of Done

Base DoD applies.

  • A player behind a wall/blocking static is not sent to an observer who has no line of sight, even within AoI radius (verifiable by a unit test on the interest reconciliation + a wall).
  • Entity reappears when LoS is regained; no flicker/dupe.
  • No regression to in-range, in-LoS reconciliation.
Discovered by the PvP-arena design review (#109). The server streams every entity within the AoI Chebyshev radius (`PlayersWithin(pos, radius)` / `InterestManager` / `InterestDiff`) **regardless of walls** — it filters on distance, not line of sight. So a modified client sees enemy positions **through walls and cover**, defeating any cover/LoS play (the arena's whole point) and breaking the *server-authoritative fairness* pillar. ## Fix Add a **line-of-sight filter to AoI membership**: an observer is only sent an entity it has `TileMap.HasLineOfSight` to (in addition to being in range). Entering/leaving LoS reconciles like entering/leaving range (spawn/remove). Compatible with the 'broadcasts carry absolute positions' invariant — this is a **membership** change, not a delta change. ## Notes - Keep it single-threaded on the sim (AoI already reconciles per tick). - Tune cost: LoS check only for in-range candidates; friends-scale so N is small. - Interaction with hearing/`say` (AoI-scoped chat): decide whether chat still carries through walls (probably yes — you hear a shout you don't see). Scope this issue to **visual** entity reconciliation. ## Definition of Done _Base DoD applies._ - [ ] A player behind a wall/blocking static is **not** sent to an observer who has no line of sight, even within AoI radius (verifiable by a unit test on the interest reconciliation + a wall). - [ ] Entity reappears when LoS is regained; no flicker/dupe. - [ ] No regression to in-range, in-LoS reconciliation.
Author
Owner

Closing — won't do (wrong feature). Hiding entities out of line-of-sight is:

  • not UO — UO sends everyone in your radius; cover stops you being hit, it doesn't hide bodies;
  • bad UX — with tile-by-tile movement + pillars, players would flicker in/out as LoS breaks/regains;
  • redundant — the arena's cover is already real: attacks (melee range, bolt, archery #111) are LoS-checked server-side, so you can't hit through a wall regardless of what a client knows;
  • premature anti-cheat — the only gain is denying a modified client positional info, which vision.md explicitly defers ('friends-scale; no anti-abuse machinery until publicly exposed').

Decision: AoI stays = Chebyshev radius (UO-style visibility); cover is enforced by server-side attack-LoS. Revisit only if the game goes public or gains large room maps. Arena design doc corrected to drop this dependency.

Closing — **won't do (wrong feature).** Hiding entities out of line-of-sight is: - **not UO** — UO sends everyone in your radius; cover stops you being *hit*, it doesn't hide bodies; - **bad UX** — with tile-by-tile movement + pillars, players would flicker in/out as LoS breaks/regains; - **redundant** — the arena's cover is already real: attacks (melee range, bolt, archery #111) are LoS-checked **server-side**, so you can't hit through a wall regardless of what a client knows; - **premature anti-cheat** — the only gain is denying a modified client positional info, which `vision.md` explicitly defers ('friends-scale; no anti-abuse machinery until publicly exposed'). Decision: AoI stays = Chebyshev radius (UO-style visibility); cover is enforced by server-side attack-LoS. Revisit only if the game goes public or gains large room maps. Arena design doc corrected to drop this dependency.
marco closed this issue 2026-07-22 17:17:08 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marco/IsoMmo#150
No description provided.