# 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.