6.6 KiB
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:
playerIdtickmoveXmoveY
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:
playerIdtickdirXdirY- 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:
playerIdtickpositionrotationhp- 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:
tickeventTypeattackerIdtargetIddamage- optional
hitPosition
Typical event types:
HitDamageAppliedDeathShootRejected
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
MoveInputcontinuously while movement changes - Apply local predicted movement immediately
- Send
ShootInputwhen firing - Optionally play local fire effect immediately
- When
PlayerStatearrives:- compare authoritative position against predicted position
- if error is small, smooth correct
- if error is large, snap or fast-correct
- When
CombatEventarrives:- update HP and combat result using server truth
Remote Players
- Do not predict their gameplay logic
- Buffer recent
PlayerStatesnapshots - Interpolate between snapshots for smooth rendering
- Apply
CombatEventimmediately
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 laneShootInput-> reliable lanePlayerState-> sync laneCombatEvent-> reliable lane
Important:
- Do not keep both movement and shooting inside the same
PlayerInputmessage 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:
MoveInputandPlayerStatemay drop stale packetsShootInputandCombatEventshould 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
PlayerInputis too broad for this MVP if movement and shooting need different reliability - Prefer adding separate message types for
MoveInputandShootInput - Keep
PlayerStateas 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
MoveInputandShootInput - Server owns all gameplay truth
- Server sends
PlayerStateandCombatEvent - 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.