neon-sprawl/docs/decomposition/modules/client_server_authority.md

85 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Client vs server authority (Neon Sprawl)
This doc answers **who owns truth** for gameplay-relevant state and what the client may assume or predict. It complements [contracts.md](contracts.md) (what shapes cross the wire) and [`docs/architecture/tech_stack.md`](../../architecture/tech_stack.md) (stack locks).
---
## Default rule
- **Server** is authoritative for anything that affects **persistence**, **other players**, **economy**, **progression**, **security / PvP policy**, or **anti-cheat**.
- **Client** owns **input**, **presentation**, **UI**, **camera framing**, and **optional local prediction** that must **reconcile** to the server without changing committed outcomes.
Matches tech stack: client sends **intents**; server emits **state** (deltas or snapshots). Authoritative logic stays in **ASP.NET Core**, not Godot multiplayer templates.
---
## Intents vs authoritative state
| Direction | Content | Rule |
|-----------|---------|------|
| Client → server | **Intents** (move path, ability use, craft request, interact, chat, …) | Server validates every intent against rules, content, and current sim state. |
| Server → client | **Authoritative state** (`PositionState`, inventory, combat resolution, quest flags, zone tier, PvP eligibility, …) | Client displays and may predict; server wins on conflict. |
Naming on the wire may use `*Command` or `*Intent` for client→server and `*State` / `*Resolution` / snapshots for server→client; the **role** (intent vs truth) matters more than the suffix.
---
## By module (prototype defaults)
### E1.M1: InputAndMovementRuntime
- **Authoritative:** `PositionState` (and any rule derived from it: interaction range, zone presence) is owned by the **server** simulation.
- **Client:** Sends movement **intent** (e.g. destination, path id, or tick-aligned input—exact wire shape in Protobuf later). May **predict** the local avatar for responsiveness.
- **Reconciliation:** One documented ruleset: on server snapshot or correction, the client **must** converge to server truth (snap or blend—implementation choice; server outcome is final). Log material desync via [E9.M1 — TelemetryEventSchema](E9_M1_TelemetryEventSchema.md) when schema exists.
- **Deferred (not fixed here):** Sim tick rate, snapshot cadence, delta vs full snapshot protocol, and prediction smoothing curves—pick when networking MVP is scoped.
### E1.M2: IsometricCameraController
- **Authoritative:** **None** for prototype gameplay. Camera follow, zoom band, and occlusion are **client-local**; the server does **not** need `CameraState` for combat, zones, or PvP unless a future feature (e.g. replay) explicitly requires it.
- **Server:** Must not use client-reported camera pose for **gameplay checks** (targeting, line of sight, etc.); those use **world geometry + server-known positions**, not “what the player saw.”
### E1.M3: InteractionAndTargetingLayer
- **Authoritative:** Valid **target** and **interactable** eligibility (range, faction, phase, alive/dead) are decided on the **server**. Client sends selection or use **intent**; server responds with accepted `TargetState` or denial.
- **Client:** Hover, highlights, and tentative selection are presentation; may be wrong until server confirms.
### E1.M4: AbilityInputScaffold
- **Client:** Emits ability **intent** (`AbilityCastRequest` / equivalent) with ability id, target id, optional aim data as designed.
- **Server:** [E5.M1 — CombatRulesEngine](E5_M1_CombatRulesEngine.md) (and related systems) validate cooldowns, resources, range, facing/LOS rules, and [E6.M1](E6_M1_PvPEligibilityAndFlagState.md) where relevant; emits **CombatResolution** (or denies with reason).
### E5.M1: CombatRulesEngine
- **Never trust** client-supplied **damage**, **healing**, **crit rolls**, or **death** outcomes as source of truth.
- **Trust** only what the client can **observe** as intent: which action, which target, timing within tolerance—then **recompute** everything server-side from `SkillDef`, stats, and combat state.
- **Player targets:** Before applying hostile effects to another player, consult [E6.M1](E6_M1_PvPEligibilityAndFlagState.md) in-process; one combat engine for PvE and PvP — [details](pvp_combat_integration.md).
### Economy, crafting, inventory, quests, zones, PvP
- **E3.\*, E7.\*, E4.\*, E6.\*:** Commit state and validate requests **only** on the server; client UI is a **view** over server-driven data. Already assumed in epics; this doc makes the split explicit for implementers.
---
## Telemetry and debugging
- **Authority violations** (client assumed an outcome the server denied) should be **visible**: denied intents with reason codes, optional lightweight desync counters—not silent fixes in production without logging.
---
## What this doc does not fix yet
- Exact **network update rate** and **interest management** (who receives which entity updates).
- **Lag compensation** model for tab-target combat (if any)—decide with combat design and E5.M1 implementation.
- **Rollback** vs **hard snap** reconciliation for movement—engineering choice after first multiplayer vertical slice.
Revisit when the first **Protobuf** game channel and a **multiplayer** milestone are defined.
---
## Related docs
- [`docs/architecture/tech_stack.md`](../../architecture/tech_stack.md) — server-authoritative critical paths, intents vs state
- [contracts.md](contracts.md) — wire vs content artifacts
- [PvP and the combat engine](pvp_combat_integration.md) — E5.M1 × E6.M1 integration shape
- [Module dependency register](module_dependency_register.md)