83 lines
5.2 KiB
Markdown
83 lines
5.2 KiB
Markdown
# 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.
|
|
|
|
### 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
|
|
- [Module dependency register](module_dependency_register.md)
|