This commit is contained in:
SepComet
2026-04-06 11:58:36 +08:00
parent b1b38b485e
commit aebc4011c7
84 changed files with 5796 additions and 238 deletions
@@ -0,0 +1,21 @@
# authoritative-movement-bootstrap Specification
## Purpose
Define how the controlled client bootstraps steady-state movement prediction from server-confirmed authoritative movement parameters.
## Requirements
### Requirement: Client prediction bootstraps from server-confirmed movement parameters
The client SHALL establish controlled-player prediction parameters from server-confirmed authoritative movement settings before treating local prediction as steady-state truth. Client-local candidate values MAY exist before login succeeds, but long-lived prediction MUST switch to the server-confirmed parameters for the controlled player.
#### Scenario: Login success provides authoritative movement parameters for prediction
- **WHEN** the controlled client completes login and receives the server-confirmed movement bootstrap data
- **THEN** the client stores the authoritative movement parameters for that controlled player
- **THEN** subsequent local movement prediction uses those server-confirmed parameters instead of continuing to rely on an unrelated local UI value
### Requirement: Server-owned movement parameters remain the single gameplay authority
The server SHALL keep authoritative ownership of movement tuning used for authoritative movement resolution, and any client-visible movement parameters used for prediction MUST be derived from that server-owned configuration rather than from an independent client-only truth source.
#### Scenario: Client candidate speed does not override server movement authority
- **WHEN** a client proposes or locally configures a movement speed that differs from the server-owned movement speed
- **THEN** the server-owned movement configuration remains authoritative for gameplay resolution
- **THEN** the client's steady-state prediction parameters converge to the server-confirmed value instead of preserving the divergent local candidate
@@ -0,0 +1,21 @@
# authoritative-movement-cadence Specification
## Purpose
Define the fixed authoritative movement cadence contract and its observability for server runtime diagnostics and regression coverage.
## Requirements
### Requirement: Server authoritative movement uses a fixed cadence contract
The shared server runtime SHALL define a fixed authoritative movement cadence for simulation and snapshot production. Authoritative movement updates MUST be stepped from that configured cadence instead of arbitrary caller-provided elapsed values.
#### Scenario: Runtime advances movement using configured cadence
- **WHEN** the server runtime advances authoritative movement while one or more managed peers have movement state
- **THEN** the authoritative movement coordinator steps simulation using the configured cadence interval
- **THEN** the same cadence governs later authoritative `PlayerState` production for that runtime
### Requirement: Cadence information is observable for diagnostics and regression tests
The shared runtime SHALL expose the active authoritative movement cadence through diagnostics or runtime state that tests and debugging tools can read without inspecting private loop internals.
#### Scenario: Tests can read active movement cadence
- **WHEN** an edit-mode regression or debugging path inspects the server runtime after movement setup
- **THEN** it can observe the authoritative movement cadence configured for that runtime
- **THEN** the observed value matches the cadence used by authoritative movement stepping
@@ -13,13 +13,23 @@ The client SHALL keep one explicit owned authoritative `PlayerState` snapshot fo
- **THEN** presentation and diagnostics read authoritative `position`, `rotation`, `hp`, and optional `velocity` from that owned snapshot
### Requirement: Local player reconciliation applies the full authoritative state by tick
The controlled client SHALL continue reconciling local prediction from authoritative `PlayerState.Tick`, and that reconciliation MUST apply the accepted authoritative `position` and `rotation` while keeping authoritative HP and optional velocity synchronized with the owned player-state snapshot.
The controlled client SHALL continue reconciling local prediction from authoritative `PlayerState` snapshots while keeping authoritative HP and optional velocity synchronized with the owned player-state snapshot. Reconciliation MUST use the acknowledged movement-input tick defined by the sync strategy, and the visible controlled-player transform MUST keep authoritative gameplay truth separate from short-lived visual correction state. Small divergence after replay MUST converge through explicit bounded correction state, while large divergence or failed convergence MUST still snap immediately to authoritative `position` and `rotation`.
#### Scenario: Local authoritative state corrects predicted presentation
- **WHEN** the controlled player accepts an authoritative `PlayerState` for tick `N`
- **WHEN** the controlled player accepts an authoritative `PlayerState` whose acknowledged movement-input tick is `N`
- **THEN** local reconciliation prunes or replays predicted movement using tick `N` according to the sync strategy
- **THEN** the local player's visible transform is corrected toward authoritative `position` and `rotation`
- **THEN** the local player's authoritative HP on the client matches the accepted `PlayerState`
- **THEN** the controlled player's authoritative gameplay state updates immediately to the accepted `position`, `rotation`, HP, and optional velocity
- **THEN** the local player's visible transform may temporarily differ only through bounded visual correction state that converges back to the authoritative baseline
#### Scenario: Consecutive small corrections replace or fold into active visual correction
- **WHEN** the controlled player accepts a newer authoritative `PlayerState` while a bounded visual correction is still active and the new residual error remains inside the configured bounded-correction limits
- **THEN** the client updates the active visual correction state according to the sync strategy instead of preserving stale correction targets indefinitely
- **THEN** the controlled player's authoritative gameplay state still reflects only the newest accepted `PlayerState`
#### Scenario: Large local divergence bypasses bounded correction
- **WHEN** the controlled player accepts an authoritative `PlayerState` and the remaining transform error exceeds the configured snap threshold or the active bounded correction can no longer converge within its budget
- **THEN** the controlled player's visible transform snaps immediately to authoritative `position` and `rotation`
- **THEN** any temporary visual correction state is cleared before later local prediction resumes from that authoritative baseline
### Requirement: Remote players apply authoritative state without inventing gameplay truth
Remote player presentation SHALL consume the accepted authoritative player-state snapshot owned by the client and MUST NOT invent HP or final gameplay state locally. Remote movement presentation MUST smooth authoritative position and rotation through a small buffered snapshot interpolation path instead of applying only the latest snapshot directly. Stale remote `PlayerState` packets that are older than the latest accepted authoritative tick for that player MUST NOT overwrite the owned snapshot or enter the interpolation buffer.
@@ -26,10 +26,33 @@ The edit-mode regression suite SHALL cover the client path that buffers and cons
- **THEN** the test verifies the resulting interpolation or latest-snapshot clamp decision matches the MVP remote-presentation rules
### Requirement: Gameplay-flow regressions include a fake-transport authoritative round trip
The edit-mode regression suite SHALL include at least one deterministic fake-transport test that spans client send behavior, server-authoritative processing, and outgoing authoritative results. That round-trip regression MUST cover `MoveInput -> PlayerState` and `ShootInput -> CombatEvent` within the same MVP gameplay-flow suite.
The edit-mode regression suite SHALL include at least one deterministic fake-transport test that spans client send behavior, server-authoritative processing, and outgoing authoritative results. That round-trip regression MUST cover `MoveInput -> PlayerState` and `ShootInput -> CombatEvent` within the same MVP gameplay-flow suite, and it MUST assert that authoritative movement stepping follows the configured cadence contract.
#### Scenario: Fake-transport round trip preserves server authority across movement and combat
- **WHEN** an edit-mode regression test drives gameplay input through fake client/server transports and advances the server authority loop
- **THEN** the authoritative server path emits `PlayerState` snapshots in response to movement input
- **THEN** the authoritative server path emits `PlayerState` snapshots in response to movement input using the configured authoritative movement cadence
- **THEN** the authoritative server path emits `CombatEvent` results in response to shooting input
- **THEN** the combined test protects both client single-session input flow and server multi-session authoritative behavior from regression
### Requirement: Gameplay-flow regressions cover controlled-player correction decisions
The edit-mode regression suite SHALL cover the controlled-player reconciliation path after authoritative movement replay, including bounded correction for small cadence-aligned error, correction replacement under consecutive authoritative snapshots, and hard snap fallback for large or non-convergent divergence.
#### Scenario: Controlled-player reconciliation uses bounded correction for small error
- **WHEN** an edit-mode regression test applies an authoritative local `PlayerState` that leaves only small post-replay divergence
- **THEN** the controlled-player path keeps authoritative ownership of the snapshot
- **THEN** visible correction converges without an immediate hard snap on the acceptance frame
#### Scenario: Controlled-player reconciliation updates active correction on repeated small snapshots
- **WHEN** an edit-mode regression test feeds multiple authoritative local `PlayerState` updates whose residual divergence remains inside bounded-correction limits while a prior correction is still active
- **THEN** the controlled-player path replaces or folds the active correction according to the sync strategy
- **THEN** the test proves the client does not accumulate multiple stale correction tails
#### Scenario: Controlled-player reconciliation snaps on large divergence
- **WHEN** an edit-mode regression test applies an authoritative local `PlayerState` that leaves divergence beyond the configured snap threshold
- **THEN** the controlled-player path immediately applies the authoritative transform state
- **THEN** later prediction resumes from that authoritative baseline
#### Scenario: Controlled-player reconciliation snaps after failed convergence
- **WHEN** an edit-mode regression test feeds consecutive authoritative local `PlayerState` updates that keep bounded correction from converging within the configured budget
- **THEN** the controlled-player path escalates to a hard snap
- **THEN** the active correction state is cleared before later local prediction continues
@@ -17,7 +17,7 @@ The repository SHALL keep the source protobuf schema that defines gameplay netwo
- **THEN** the checked-in generated code matches the schema contract used by client and server hosts
### Requirement: Gameplay messages expose explicit MVP payload fields
The shared networking contract SHALL define the MVP payload fields for gameplay messages explicitly in the source protobuf schema and generated C# messages. `MoveInput` MUST expose `playerId`, `tick`, `moveX`, and `moveY`; `ShootInput` MUST expose `playerId`, `tick`, `dirX`, `dirY`, and an optional `targetId`; `PlayerState` MUST expose `playerId`, `tick`, `position`, `rotation`, `hp`, and an optional `velocity`; `CombatEvent` MUST expose `tick`, `eventType`, `attackerId`, `targetId`, `damage`, and an optional `hitPosition`. The shared contract MUST also provide `CombatEventType` so combat results use explicit event categories rather than ad hoc integer payload conventions.
The shared networking contract SHALL define the MVP payload fields for gameplay messages explicitly in the source protobuf schema and generated C# messages. `MoveInput` MUST expose `playerId`, `tick`, `moveX`, and `moveY`; `ShootInput` MUST expose `playerId`, `tick`, `dirX`, `dirY`, and an optional `targetId`; `PlayerState` MUST expose `playerId`, `tick`, `acknowledgedMoveTick`, `position`, `rotation`, `hp`, and an optional `velocity`; `CombatEvent` MUST expose `tick`, `eventType`, `attackerId`, `targetId`, `damage`, and an optional `hitPosition`. The shared contract MUST also provide `CombatEventType` so combat results use explicit event categories rather than ad hoc integer payload conventions.
#### Scenario: Movement input carries explicit movement fields
- **WHEN** client or server code constructs or parses `MoveInput`
@@ -31,8 +31,8 @@ The shared networking contract SHALL define the MVP payload fields for gameplay
#### Scenario: Authoritative player state carries explicit gameplay state fields
- **WHEN** client or server code constructs or parses `PlayerState`
- **THEN** the message exposes `playerId`, `tick`, `position`, `rotation`, `hp`, and `velocity`
- **THEN** authoritative movement and health state are expressed without ad hoc payload extensions
- **THEN** the message exposes `playerId`, `tick`, `acknowledgedMoveTick`, `position`, `rotation`, `hp`, and `velocity`
- **THEN** snapshot ordering and acknowledged-input reconciliation are both expressed without ad hoc payload extensions or overloaded tick semantics
#### Scenario: Combat events carry explicit result fields and event categories
- **WHEN** client or server code constructs or parses `CombatEvent`
+17 -2
View File
@@ -41,13 +41,28 @@ The high-frequency sync strategy SHALL tag gameplay synchronization messages wit
- **THEN** reliable ordered handling remains responsible for preserving event delivery semantics
### Requirement: Authoritative correction prunes acknowledged prediction history
The client sync strategy SHALL reconcile local prediction against authoritative player-state updates by pruning acknowledged movement inputs at or before the authoritative tick and only reapplying newer pending `MoveInput` messages.
The client sync strategy SHALL reconcile local prediction against authoritative player-state updates by pruning acknowledged movement inputs at or before the authoritative acknowledged movement tick and only reapplying newer pending `MoveInput` messages. For the controlled player, reconciliation MUST classify authoritative error after replay into a bounded-correction path for small cadence-aligned divergence and an immediate snap path for large divergence. When bounded correction is already active, later authoritative snapshots MUST deterministically replace, fold into, or escalate that correction based on the newest residual error instead of stacking unbounded visual offsets.
#### Scenario: Reconciliation removes already acknowledged movement inputs
- **WHEN** the client accepts an authoritative `PlayerState` update for tick `N`
- **WHEN** the client accepts an authoritative `PlayerState` update that acknowledges movement tick `N`
- **THEN** locally buffered predicted `MoveInput` messages with tick less than or equal to `N` are removed from the replay buffer
- **THEN** only `MoveInput` messages newer than `N` remain eligible for re-simulation
#### Scenario: Small post-replay error uses bounded correction
- **WHEN** the controlled client finishes replay after accepting an authoritative `PlayerState` and the remaining position or rotation error stays within the configured bounded-correction threshold
- **THEN** the client keeps authoritative ownership of the accepted snapshot
- **THEN** local presentation converges through bounded correction instead of an immediate hard snap on that frame
#### Scenario: New small error updates active bounded correction
- **WHEN** the controlled client accepts another authoritative `PlayerState` before the previous bounded correction has finished and the new residual error still stays within bounded-correction limits
- **THEN** the sync strategy updates the active bounded correction state using the newest authoritative residual error
- **THEN** the client does not queue multiple independent correction tails for the same controlled player
#### Scenario: Failed bounded correction escalates to snap
- **WHEN** the controlled client detects that the residual error from consecutive authoritative updates exceeds the snap threshold or remains non-convergent beyond the configured correction budget
- **THEN** the client immediately applies the authoritative transform state
- **THEN** any active bounded correction state is discarded before later prediction continues from the authoritative baseline
### Requirement: Clock synchronization is a separate sync-policy concern
The shared networking core SHALL process server-tick or clock-synchronization samples through a dedicated sync-policy component rather than storing clock-sync ownership inside `SessionManager`.
@@ -23,11 +23,11 @@ The shared server networking path SHALL register `MoveInput` handling through th
- **THEN** authoritative movement state for other managed peers remains unchanged
### Requirement: Server owns authoritative movement resolution
The shared server networking path SHALL own the final movement state for each managed peer, including position, rotation, velocity, and stop state. Zero-vector movement input MUST stop authoritative movement rather than leaving the peer in its previous moving state.
The shared server networking path SHALL own the final movement state for each managed peer, including position, rotation, velocity, and stop state. Zero-vector movement input MUST stop authoritative movement rather than leaving the peer in its previous moving state. The authoritative movement integrator MUST advance using the runtime's configured authoritative movement cadence so that movement resolution and later `PlayerState` snapshots are produced from the same server-side stepping contract.
#### Scenario: Non-zero input advances authoritative movement state
- **WHEN** the server processes an accepted non-zero `MoveInput` for a managed peer during an authority update step
- **THEN** the server updates that peer's authoritative position, rotation, and velocity from server-side movement resolution
- **THEN** the server updates that peer's authoritative position, rotation, and velocity from server-side movement resolution using the configured authoritative movement cadence
- **THEN** the resulting state becomes the source of truth for later `PlayerState` broadcast
#### Scenario: Zero-vector input stops authoritative movement
@@ -39,7 +39,7 @@ The shared server networking path SHALL own the final movement state for each ma
The shared server networking path SHALL emit authoritative `PlayerState` snapshots for managed peers at a fixed cadence using the existing sync-lane message contract. Each snapshot MUST be derived from the server-owned authoritative player state and include the authoritative tick for client reconciliation and interpolation. Authoritative HP changes produced by server-side combat resolution MUST be reflected in later snapshots for the affected peer.
#### Scenario: Authority update step emits sync-lane player snapshots
- **WHEN** the server reaches a configured authority broadcast cadence while one or more managed peers have authoritative player state
- **WHEN** the server reaches the configured authoritative movement cadence while one or more managed peers have authoritative player state
- **THEN** it sends `PlayerState` snapshots using the sync-lane delivery policy when a distinct sync transport exists
- **THEN** each snapshot includes the authoritative position, rotation, velocity, HP, and tick from server-owned state