process TODO.md step7
This commit is contained in:
+2
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-29
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
## Context
|
||||
|
||||
`ServerNetworkHost` already owns transport startup, message draining, and `MultiSessionManager`, but it does not yet register gameplay handlers or retain any authoritative movement model per peer. `MessageManager` can already route `MoveInput` and `PlayerState` across reliable/sync lanes, and `SyncSequenceTracker` already accepts stale filtering rules for high-frequency messages, but the server currently lacks a component that turns accepted `MoveInput` into authoritative state and periodic `PlayerState` output.
|
||||
|
||||
This change needs to stay inside the shared networking/server code under `Assets/Scripts/Network/` so the authoritative loop remains host-agnostic and testable in edit-mode tests. The client single-session path and existing dual-transport startup contract must remain intact.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Add a server-side movement authority component that registers `MoveInput` handling and owns authoritative per-player movement state.
|
||||
- Keep stale filtering and last-accepted tick tracking independent for each peer so multi-session traffic cannot interfere across connections.
|
||||
- Broadcast authoritative `PlayerState` snapshots at a fixed cadence on the existing sync lane contract.
|
||||
- Make zero-vector `MoveInput` stop authoritative movement instead of relying on client-only visuals.
|
||||
- Keep the runtime entry point easy to test from fake transports and edit-mode regression tests.
|
||||
|
||||
**Non-Goals:**
|
||||
- Implement shooting, combat resolution, or authoritative HP changes beyond preserving fields needed by `PlayerState` broadcasting.
|
||||
- Introduce Unity-specific frame-loop dependencies into shared networking code.
|
||||
- Replace the existing client reconciliation/interpolation logic in this change.
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Introduce a dedicated server-authoritative movement coordinator
|
||||
The server needs a focused component, owned by the server host/runtime, that accepts decoded `MoveInput`, validates it, mutates authoritative state, and produces broadcast snapshots. Extending `ServerNetworkHost` with orchestration hooks is appropriate because it already owns `MessageManager`, transport lifetime, and access to `MultiSessionManager`, but the movement rules themselves should live in a dedicated authority/coordinator type rather than being spread across `ServerRuntimeHandle` and ad-hoc handlers.
|
||||
|
||||
Alternative considered: put movement mutation directly inside `MultiSessionManager`. Rejected because `MultiSessionManager` currently owns generic lifecycle state, not gameplay simulation rules or snapshot broadcast cadence.
|
||||
|
||||
### 2. Store authoritative movement state per managed peer
|
||||
The authoritative state must be keyed per remote peer and include the last accepted movement tick, current position, facing/rotation, current velocity, and current movement intent. That state can be attached alongside `ManagedNetworkSession` ownership or maintained in a peer-keyed store owned by the authority coordinator, but the key requirement is that all stale-input evaluation and movement mutation remain peer-scoped.
|
||||
|
||||
Alternative considered: a single global last-move tick tracker. Rejected because it would let one peer's late or advanced traffic affect another peer's acceptance window.
|
||||
|
||||
### 3. Reuse the existing message routing and sync lane contract for `PlayerState`
|
||||
The new authority loop should keep using `MessageManager` and the current delivery policy resolver rather than inventing a separate server broadcast channel. Authoritative snapshots remain ordinary `PlayerState` messages, which preserves the existing client reconciliation path and keeps the sync-lane policy centralized.
|
||||
|
||||
Alternative considered: special-case `PlayerState` broadcast outside `MessageManager`. Rejected because it would duplicate lane-selection logic and make regression coverage harder.
|
||||
|
||||
### 4. Drive authoritative simulation and broadcast with explicit server ticks/cadence hooks
|
||||
The server runtime already exposes message draining and lifecycle updates through `ServerRuntimeHandle`. This change should add or define a similarly explicit authority update hook so hosts can advance movement resolution and emit snapshots on a known cadence. The cadence source should be injectable/testable so edit-mode tests can deterministically assert broadcast timing and stale-filter behavior.
|
||||
|
||||
Alternative considered: only mutate state when input arrives and broadcast immediately. Rejected because clients need regular authoritative `PlayerState` output for reconciliation and interpolation, including periods where input is zero and state is stable.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Additional server-side state per peer increases lifecycle cleanup complexity. → Mitigation: tie authoritative movement state ownership to the same per-peer registration and removal flow used by `MultiSessionManager`.
|
||||
- [Risk] Cadence-driven broadcasting can spam unchanged snapshots or create unnecessary test brittleness. → Mitigation: keep cadence configuration explicit and default to a small fixed interval that tests can control.
|
||||
- [Risk] Validation rules may be underspecified for MVP movement. → Mitigation: keep initial validation narrow and deterministic (peer identity, monotonic tick acceptance, finite vector input, zero-vector stop) and leave richer anti-cheat rules for later changes.
|
||||
- [Risk] Extending shared server code can accidentally affect the client single-session path. → Mitigation: keep all new authority types behind the server host/runtime path and add regression tests that cover both reliable-only and dual-lane server setups.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add the new capability/spec coverage for server-authoritative movement and the per-peer multi-session requirement update.
|
||||
2. Introduce the server authority coordinator and peer movement state model in shared server code.
|
||||
3. Register `MoveInput` handling through the server host/runtime composition path and expose an explicit authority update/broadcast cadence hook.
|
||||
4. Add edit-mode regression tests for per-peer stale filtering, zero-vector stop, and sync-lane `PlayerState` broadcasting.
|
||||
5. Re-run build/test once the .NET runtime environment is available.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Whether authoritative position integration should use a simple fixed-speed MVP model or plug into an existing gameplay movement service outside `Assets/Scripts/Network/`.
|
||||
- Whether the first implementation should broadcast every cadence tick for all managed peers or suppress unchanged snapshots once client reconciliation coverage is confirmed.
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
## Why
|
||||
|
||||
The networking layer can now start a real server runtime, but the server still does not own player movement or produce authoritative `PlayerState` snapshots. Until that loop exists, client reconciliation and remote interpolation remain disconnected from actual server truth, so the MVP still relies on local visuals instead of authoritative simulation.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a concrete server-authoritative movement capability that accepts `MoveInput`, validates it per peer, updates authoritative movement state, and emits `PlayerState` snapshots on a fixed sync cadence.
|
||||
- Introduce explicit server-side movement ownership for position, velocity, rotation, and last accepted movement tick so zero-vector input can stop movement through server truth.
|
||||
- Keep stale-input filtering peer-scoped so one client's out-of-order `MoveInput` packets cannot suppress another client's movement updates.
|
||||
- Define the server broadcast contract for authoritative `PlayerState` snapshots so clients can reconcile the local player and interpolate remote players from server output.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `server-authoritative-movement`: Server-side handling of `MoveInput`, authoritative movement state mutation, and fixed-cadence `PlayerState` broadcast.
|
||||
|
||||
### Modified Capabilities
|
||||
- `multi-session-lifecycle`: Server multi-session coordination also tracks authoritative movement state and stale-input evaluation independently for each managed peer.
|
||||
|
||||
## Impact
|
||||
|
||||
Affected areas include the shared server host/runtime under `Assets/Scripts/Network/`, server-side gameplay state ownership, authoritative `PlayerState` broadcast wiring, and edit-mode regression coverage for multi-peer movement handling.
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Multi-session hosts can observe and evaluate each managed session
|
||||
The multi-session lifecycle coordinator SHALL expose per-session lookup or enumeration and MUST evaluate timeout, heartbeat, login, reconnect, and authoritative movement tick rules for each managed session independently using the shared session lifecycle vocabulary. Server-side stale-input acceptance and authoritative movement tracking MUST remain scoped to the peer that produced the traffic.
|
||||
|
||||
#### Scenario: Timeout affects only one managed session
|
||||
- **WHEN** one managed session stops receiving liveness updates while another session continues receiving heartbeat or message activity
|
||||
- **THEN** the timed-out session transitions through timeout or reconnect states according to policy
|
||||
- **THEN** the active session remains in its current healthy state
|
||||
|
||||
#### Scenario: Host can inspect current managed sessions
|
||||
- **WHEN** server-side code needs to inspect the current connection state of connected peers
|
||||
- **THEN** it can look up or enumerate managed sessions through the multi-session coordinator
|
||||
- **THEN** each entry exposes the shared session lifecycle state for that specific peer
|
||||
|
||||
#### Scenario: Movement tick filtering remains peer-scoped
|
||||
- **WHEN** two managed peers send `MoveInput` traffic with different tick progress or ordering
|
||||
- **THEN** stale-input acceptance is evaluated independently for each managed peer
|
||||
- **THEN** one peer's late or advanced movement input does not overwrite or suppress the other's authoritative movement state
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Server registers and validates `MoveInput` per peer
|
||||
The shared server networking path SHALL register `MoveInput` handling through the server host/runtime composition and SHALL validate inbound movement input against the sending peer before mutating authoritative state. Validation MUST reject stale ticks for that peer, malformed numeric values, and payloads that do not map to the sender's managed movement state.
|
||||
|
||||
#### Scenario: Accepted `MoveInput` updates the sender's authoritative movement intent
|
||||
- **WHEN** a managed peer sends a well-formed `MoveInput` with a tick newer than the last accepted movement tick for that peer
|
||||
- **THEN** the server accepts the input for that peer only
|
||||
- **THEN** the sender's authoritative movement intent and last accepted movement tick are updated
|
||||
|
||||
#### Scenario: Stale `MoveInput` is rejected without affecting other peers
|
||||
- **WHEN** one managed peer sends a `MoveInput` whose tick is older than the last accepted movement tick for that same peer
|
||||
- **THEN** the server rejects that input for that peer
|
||||
- **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.
|
||||
|
||||
#### 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 resulting state becomes the source of truth for later `PlayerState` broadcast
|
||||
|
||||
#### Scenario: Zero-vector input stops authoritative movement
|
||||
- **WHEN** the server processes an accepted zero-vector `MoveInput` for a managed peer
|
||||
- **THEN** the peer's authoritative velocity becomes zero
|
||||
- **THEN** subsequent authoritative state snapshots reflect that stopped state until a newer movement input is accepted
|
||||
|
||||
### Requirement: Server broadcasts authoritative `PlayerState` snapshots on the sync cadence
|
||||
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 movement state and include the authoritative tick for client reconciliation and interpolation.
|
||||
|
||||
#### 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 movement 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, and tick from server-owned state
|
||||
|
||||
#### Scenario: Reliable transport remains fallback when no sync transport exists
|
||||
- **WHEN** the server broadcasts authoritative `PlayerState` snapshots without a dedicated sync transport
|
||||
- **THEN** the shared routing path still emits `PlayerState` through the existing fallback lane behavior
|
||||
- **THEN** the authoritative snapshot contract remains unchanged
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
## 1. Server Authority Core
|
||||
|
||||
- [x] 1.1 Add a dedicated server-authoritative movement coordinator and per-peer authoritative movement state model under `Assets/Scripts/Network/`.
|
||||
- [x] 1.2 Register `MoveInput` handling through the server host/runtime composition path and validate sender-scoped movement payloads before accepting them.
|
||||
- [x] 1.3 Keep stale movement tick acceptance independent per managed peer and ensure zero-vector input clears authoritative movement velocity.
|
||||
|
||||
## 2. Authoritative Snapshot Broadcast
|
||||
|
||||
- [x] 2.1 Add an explicit server authority update hook that advances authoritative movement resolution on a fixed cadence.
|
||||
- [x] 2.2 Broadcast authoritative `PlayerState` snapshots through the existing `MessageManager` sync-lane contract, with reliable fallback when no sync transport exists.
|
||||
- [x] 2.3 Expose the minimal runtime/host surface needed for host processes and tests to drive movement authority updates and inspect authoritative peer state.
|
||||
|
||||
## 3. Regression Coverage And Documentation
|
||||
|
||||
- [x] 3.1 Add edit-mode regression tests for accepted vs stale `MoveInput` handling across multiple peers.
|
||||
- [x] 3.2 Add edit-mode regression tests for zero-vector movement stop and fixed-cadence `PlayerState` broadcasting on sync and fallback lanes.
|
||||
- [x] 3.3 Update `TODO.md` and related change tracking/docs to reflect the completed server-authoritative movement/state broadcast work.
|
||||
@@ -13,7 +13,7 @@ The shared networking core SHALL provide a multi-session lifecycle coordinator f
|
||||
- **THEN** lifecycle changes for one peer do not overwrite or hide the state of the other peer
|
||||
|
||||
### Requirement: Multi-session hosts can observe and evaluate each managed session
|
||||
The multi-session lifecycle coordinator SHALL expose per-session lookup or enumeration and MUST evaluate timeout, heartbeat, login, and reconnect rules for each managed session independently using the shared session lifecycle vocabulary.
|
||||
The multi-session lifecycle coordinator SHALL expose per-session lookup or enumeration and MUST evaluate timeout, heartbeat, login, reconnect, and authoritative movement tick rules for each managed session independently using the shared session lifecycle vocabulary. Server-side stale-input acceptance and authoritative movement tracking MUST remain scoped to the peer that produced the traffic.
|
||||
|
||||
#### Scenario: Timeout affects only one managed session
|
||||
- **WHEN** one managed session stops receiving liveness updates while another session continues receiving heartbeat or message activity
|
||||
@@ -25,6 +25,11 @@ The multi-session lifecycle coordinator SHALL expose per-session lookup or enume
|
||||
- **THEN** it can look up or enumerate managed sessions through the multi-session coordinator
|
||||
- **THEN** each entry exposes the shared session lifecycle state for that specific peer
|
||||
|
||||
#### Scenario: Movement tick filtering remains peer-scoped
|
||||
- **WHEN** two managed peers send `MoveInput` traffic with different tick progress or ordering
|
||||
- **THEN** stale-input acceptance is evaluated independently for each managed peer
|
||||
- **THEN** one peer's late or advanced movement input does not overwrite or suppress the other's authoritative movement state
|
||||
|
||||
### Requirement: Session removal is explicit and does not corrupt remaining peers
|
||||
The multi-session lifecycle coordinator SHALL support explicit removal or disconnection handling for one managed session without resetting unrelated sessions that remain active.
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# server-authoritative-movement Specification
|
||||
|
||||
## Purpose
|
||||
Define the shared server-side movement authority contract that accepts `MoveInput`, mutates authoritative per-peer movement state, and broadcasts authoritative `PlayerState` snapshots for client reconciliation and interpolation.
|
||||
|
||||
## Requirements
|
||||
### Requirement: Server registers and validates `MoveInput` per peer
|
||||
The shared server networking path SHALL register `MoveInput` handling through the server host/runtime composition and SHALL validate inbound movement input against the sending peer before mutating authoritative state. Validation MUST reject stale ticks for that peer, malformed numeric values, and payloads that do not map to the sender's managed movement state.
|
||||
|
||||
#### Scenario: Accepted `MoveInput` updates the sender's authoritative movement intent
|
||||
- **WHEN** a managed peer sends a well-formed `MoveInput` with a tick newer than the last accepted movement tick for that peer
|
||||
- **THEN** the server accepts the input for that peer only
|
||||
- **THEN** the sender's authoritative movement intent and last accepted movement tick are updated
|
||||
|
||||
#### Scenario: Stale `MoveInput` is rejected without affecting other peers
|
||||
- **WHEN** one managed peer sends a `MoveInput` whose tick is older than the last accepted movement tick for that same peer
|
||||
- **THEN** the server rejects that input for that peer
|
||||
- **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.
|
||||
|
||||
#### 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 resulting state becomes the source of truth for later `PlayerState` broadcast
|
||||
|
||||
#### Scenario: Zero-vector input stops authoritative movement
|
||||
- **WHEN** the server processes an accepted zero-vector `MoveInput` for a managed peer
|
||||
- **THEN** the peer's authoritative velocity becomes zero
|
||||
- **THEN** subsequent authoritative state snapshots reflect that stopped state until a newer movement input is accepted
|
||||
|
||||
### Requirement: Server broadcasts authoritative `PlayerState` snapshots on the sync cadence
|
||||
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 movement state and include the authoritative tick for client reconciliation and interpolation.
|
||||
|
||||
#### 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 movement 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, and tick from server-owned state
|
||||
|
||||
#### Scenario: Reliable transport remains fallback when no sync transport exists
|
||||
- **WHEN** the server broadcasts authoritative `PlayerState` snapshots without a dedicated sync transport
|
||||
- **THEN** the shared routing path still emits `PlayerState` through the existing fallback lane behavior
|
||||
- **THEN** the authoritative snapshot contract remains unchanged
|
||||
Reference in New Issue
Block a user