268 lines
6.6 KiB
Markdown
268 lines
6.6 KiB
Markdown
# MOBA Hybrid Sync MVP
|
|
|
|
## Goal
|
|
|
|
Build a minimal hybrid sync model for a MOBA-like game:
|
|
|
|
- Client sends only player inputs
|
|
- Server runs authoritative gameplay logic
|
|
- Server sends authoritative state and combat results back to clients
|
|
- Client uses prediction for local control and interpolation/reconciliation for presentation
|
|
|
|
This MVP supports only two player inputs:
|
|
|
|
- Move
|
|
- Shoot
|
|
|
|
Other core gameplay data such as position and HP remain server-authoritative.
|
|
|
|
## Core Model
|
|
|
|
### Client Responsibilities
|
|
|
|
- Capture local input
|
|
- Send input messages to server
|
|
- Predict local movement immediately
|
|
- Play local shooting presentation immediately if desired
|
|
- Reconcile local player state when authoritative state arrives
|
|
- Interpolate remote player movement for smooth display
|
|
|
|
### Server Responsibilities
|
|
|
|
- Receive all player inputs
|
|
- Validate and apply movement
|
|
- Validate shooting requests
|
|
- Resolve hit, damage, death, and other combat results
|
|
- Maintain authoritative position, HP, and combat state
|
|
- Broadcast authoritative state snapshots
|
|
- Broadcast authoritative combat events
|
|
|
|
## Message Plan
|
|
|
|
| Message | Direction | Reliability | Frequency | Purpose |
|
|
|---|---|---|---|---|
|
|
| `MoveInput` | Client -> Server | Low reliability / latest wins | 10-20 Hz | Report movement input |
|
|
| `ShootInput` | Client -> Server | Reliable ordered | On demand | Report shoot request |
|
|
| `PlayerState` | Server -> Client | Low reliability / latest wins | 10-20 Hz | Sync position, rotation, HP |
|
|
| `CombatEvent` | Server -> Client | Reliable ordered | On demand | Sync hit, damage, death |
|
|
| `Heartbeat` / `ClockSync` | Both ways | Reliable ordered | 1-2 Hz | Keepalive and server tick sync |
|
|
|
|
## Message Definitions
|
|
|
|
### MoveInput
|
|
|
|
Sent frequently. Old packets can be dropped.
|
|
|
|
Suggested fields:
|
|
|
|
- `playerId`
|
|
- `tick`
|
|
- `moveX`
|
|
- `moveY`
|
|
|
|
Notes:
|
|
|
|
- Represents current movement intent
|
|
- Should be treated as a high-frequency sync message
|
|
- Latest input matters more than full delivery history
|
|
|
|
### ShootInput
|
|
|
|
Sent only when player fires.
|
|
|
|
Suggested fields:
|
|
|
|
- `playerId`
|
|
- `tick`
|
|
- `dirX`
|
|
- `dirY`
|
|
- optional `targetId`
|
|
|
|
Notes:
|
|
|
|
- Must be delivered reliably
|
|
- Server decides whether shooting is valid
|
|
- Client may play local muzzle flash or firing animation immediately, but not authoritative hit resolution
|
|
|
|
### PlayerState
|
|
|
|
Sent from server as authoritative snapshot.
|
|
|
|
Suggested fields:
|
|
|
|
- `playerId`
|
|
- `tick`
|
|
- `position`
|
|
- `rotation`
|
|
- `hp`
|
|
- optional `velocity`
|
|
|
|
Notes:
|
|
|
|
- Used for local reconciliation and remote interpolation
|
|
- Position and HP are server-authoritative
|
|
- Older states should be discarded if a newer state already exists
|
|
|
|
### CombatEvent
|
|
|
|
Sent when authoritative combat logic produces a result.
|
|
|
|
Suggested fields:
|
|
|
|
- `tick`
|
|
- `eventType`
|
|
- `attackerId`
|
|
- `targetId`
|
|
- `damage`
|
|
- optional `hitPosition`
|
|
|
|
Typical event types:
|
|
|
|
- `Hit`
|
|
- `DamageApplied`
|
|
- `Death`
|
|
- `ShootRejected`
|
|
|
|
Notes:
|
|
|
|
- Reliable ordered delivery is required
|
|
- Clients update HP, death state, hit reactions, and combat UI from this message class
|
|
|
|
## Authority Rules
|
|
|
|
### Client Authoritative
|
|
|
|
Only for temporary presentation:
|
|
|
|
- Local movement prediction
|
|
- Local fire animation / local FX preplay
|
|
|
|
These are visual conveniences only and must be correctable.
|
|
|
|
### Server Authoritative
|
|
|
|
Always authoritative for:
|
|
|
|
- Final position
|
|
- HP
|
|
- Combat resolution
|
|
- Shoot validation
|
|
- Hit validation
|
|
- Death state
|
|
|
|
Clients must never be allowed to finalize these outcomes.
|
|
|
|
## Client Handling Rules
|
|
|
|
### Local Player
|
|
|
|
- Send `MoveInput` continuously while movement changes
|
|
- Apply local predicted movement immediately
|
|
- Send `ShootInput` when firing
|
|
- Optionally play local fire effect immediately
|
|
- When `PlayerState` arrives:
|
|
- compare authoritative position against predicted position
|
|
- if error is small, smooth correct
|
|
- if error is large, snap or fast-correct
|
|
- When `CombatEvent` arrives:
|
|
- update HP and combat result using server truth
|
|
|
|
### Remote Players
|
|
|
|
- Do not predict their gameplay logic
|
|
- Buffer recent `PlayerState` snapshots
|
|
- Interpolate between snapshots for smooth rendering
|
|
- Apply `CombatEvent` immediately
|
|
|
|
## Transport Mapping
|
|
|
|
This repository already has the right high-level direction:
|
|
|
|
- High-frequency sync lane for movement/state-like messages
|
|
- Reliable lane for guaranteed gameplay events
|
|
|
|
Recommended mapping:
|
|
|
|
- `MoveInput` -> sync lane
|
|
- `ShootInput` -> reliable lane
|
|
- `PlayerState` -> sync lane
|
|
- `CombatEvent` -> reliable lane
|
|
|
|
Important:
|
|
|
|
- Do not keep both movement and shooting inside the same `PlayerInput` message if they need different delivery policies
|
|
- Split them into distinct message types so delivery policy stays explicit
|
|
|
|
## Tick and Ordering
|
|
|
|
Use `tick` on all gameplay-relevant messages.
|
|
|
|
Purposes:
|
|
|
|
- detect stale sync messages
|
|
- support reconciliation
|
|
- align state snapshots to server simulation
|
|
- simplify debugging
|
|
|
|
Recommended rules:
|
|
|
|
- `MoveInput` and `PlayerState` may drop stale packets
|
|
- `ShootInput` and `CombatEvent` should remain ordered and reliable
|
|
|
|
## Recommended MVP Scope
|
|
|
|
### Phase 1
|
|
|
|
- Implement `MoveInput`
|
|
- Implement authoritative `PlayerState`
|
|
- Run local prediction for self
|
|
- Run interpolation for remote players
|
|
|
|
### Phase 2
|
|
|
|
- Implement `ShootInput`
|
|
- Implement authoritative `CombatEvent`
|
|
- Server resolves hit and damage
|
|
- Clients update HP and hit feedback from server results
|
|
|
|
### Phase 3
|
|
|
|
- Add optional projectile authority model if needed
|
|
- Add more combat event types
|
|
- Add anti-cheat diagnostics or state hash logging only as auxiliary tooling
|
|
|
|
## Non-Goals For MVP
|
|
|
|
Do not include these in the first version:
|
|
|
|
- Client-side authoritative combat
|
|
- Client majority voting
|
|
- Client hash majority recovery
|
|
- Full deterministic lockstep
|
|
- Complex rollback netcode
|
|
- Advanced anti-cheat enforcement
|
|
|
|
## Implementation Notes For This Repository
|
|
|
|
Based on the current network architecture:
|
|
|
|
- Current `PlayerInput` is too broad for this MVP if movement and shooting need different reliability
|
|
- Prefer adding separate message types for `MoveInput` and `ShootInput`
|
|
- Keep `PlayerState` as a high-frequency authoritative snapshot
|
|
- Add a new reliable message type for `CombatEvent`
|
|
|
|
If the current transport setup uses only one underlying transport instance, the application layer can still distinguish message policy logically, but true sync/reliable isolation is better when backed by distinct lanes or transport behavior.
|
|
|
|
## Summary
|
|
|
|
For the MVP:
|
|
|
|
- Client sends only `MoveInput` and `ShootInput`
|
|
- Server owns all gameplay truth
|
|
- Server sends `PlayerState` and `CombatEvent`
|
|
- Client predicts local movement
|
|
- Client interpolates remote movement
|
|
- Client corrects to server state when divergence appears
|
|
|
|
This gives a practical, controllable, and extensible baseline for a small MOBA-style networking model.
|