0.2.0-0-pre.2-fix.1
This commit is contained in:
321
docs/studies/006-REALTIME_MULTIPLAYER_SERVER_STUDY.md
Normal file
321
docs/studies/006-REALTIME_MULTIPLAYER_SERVER_STUDY.md
Normal file
@@ -0,0 +1,321 @@
|
||||
<!-- file: docs/studies/006-REALTIME_MULTIPLAYER_SERVER_STUDY.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Étude serveur multijoueur temps réel
|
||||
|
||||
## Statut
|
||||
|
||||
Étude non normative pour `0.2.0-0-pre.2.fix.1`.
|
||||
|
||||
Ce document complète l'inventaire initial. Il ne choisit pas encore une stack serveur, un crate WebSocket ou une fréquence de tick unique.
|
||||
|
||||
## Objectif
|
||||
|
||||
Séparer clairement :
|
||||
|
||||
- transport réseau ;
|
||||
- protocole de session ;
|
||||
- synchronisation d'état ;
|
||||
- simulation authoritative ;
|
||||
- services Web persistants.
|
||||
|
||||
Un WebSocket fournit un canal bidirectionnel ; il ne résout pas à lui seul la synchronisation multijoueur.
|
||||
|
||||
## Plan de contrôle et plan de données
|
||||
|
||||
### Control plane
|
||||
|
||||
Responsabilités plausibles :
|
||||
|
||||
- authentification ;
|
||||
- matchmaking ;
|
||||
- création/allocation de partie ;
|
||||
- roster ;
|
||||
- invitation/join/leave ;
|
||||
- ready/start/end ;
|
||||
- sélection d'une instance realtime ;
|
||||
- reprise de session.
|
||||
|
||||
Ces opérations peuvent passer par HTTP(S), WebSocket ou une combinaison, sans être exécutées dans la boucle de simulation.
|
||||
|
||||
### Realtime data plane
|
||||
|
||||
Responsabilités plausibles :
|
||||
|
||||
- accepter les connexions de joueurs ;
|
||||
- associer connexion, joueur et session ;
|
||||
- recevoir les inputs/commands ;
|
||||
- sequencer les messages ;
|
||||
- maintenir le tick/cycle de simulation ;
|
||||
- faire évoluer l'état authoritative ;
|
||||
- diffuser snapshots et deltas ;
|
||||
- détecter pertes/timeouts ;
|
||||
- gérer reconnexion et resynchronisation ;
|
||||
- appliquer backpressure/rate limits ;
|
||||
- produire observability et health.
|
||||
|
||||
## Modèles de synchronisation
|
||||
|
||||
Aucun modèle unique ne convient à tous les jeux.
|
||||
|
||||
### Input authoritative
|
||||
|
||||
Le client envoie principalement ses inputs.
|
||||
|
||||
Le serveur :
|
||||
|
||||
1. valide l'input ;
|
||||
2. l'applique à la simulation ;
|
||||
3. avance l'état ;
|
||||
4. publie l'état ou son delta.
|
||||
|
||||
Approprié à de nombreux jeux compétitifs.
|
||||
|
||||
### State replication
|
||||
|
||||
Le serveur publie :
|
||||
|
||||
- snapshots périodiques ;
|
||||
- deltas entre snapshots ;
|
||||
- revision/tick associé ;
|
||||
- éventuellement ack/last-applied revision.
|
||||
|
||||
Le client reconstruit un état local de présentation.
|
||||
|
||||
### Prediction / reconciliation
|
||||
|
||||
Pour réduire la latence perçue :
|
||||
|
||||
- le client prédit localement ;
|
||||
- conserve les inputs non confirmés ;
|
||||
- reçoit l'état serveur ;
|
||||
- corrige/rejoue si nécessaire.
|
||||
|
||||
À réserver aux jeux qui en ont besoin.
|
||||
|
||||
### Rollback
|
||||
|
||||
Particulièrement pertinent pour certains jeux de combat :
|
||||
|
||||
- historique court d'états ;
|
||||
- inputs retardés ou prédits ;
|
||||
- rollback/re-simulation.
|
||||
|
||||
Ce modèle ne doit pas contaminer le runtime de tous les jeux.
|
||||
|
||||
## Contrats techniques candidats
|
||||
|
||||
### Envelope réseau
|
||||
|
||||
Champs conceptuels possibles :
|
||||
|
||||
- protocol version ;
|
||||
- message type ;
|
||||
- session id ;
|
||||
- player id/connection id si nécessaire ;
|
||||
- sequence ;
|
||||
- server tick ;
|
||||
- client tick/time ;
|
||||
- payload.
|
||||
|
||||
Le format exact n'est pas encore décidé.
|
||||
|
||||
### Snapshot
|
||||
|
||||
Doit permettre :
|
||||
|
||||
- état complet cohérent ;
|
||||
- revision/tick ;
|
||||
- application atomique côté client ;
|
||||
- point de reprise après resync.
|
||||
|
||||
### Delta
|
||||
|
||||
Doit préciser :
|
||||
|
||||
- base revision ;
|
||||
- target revision ;
|
||||
- mutations ;
|
||||
- comportement si la base manque.
|
||||
|
||||
Un delta manquant doit conduire à une resynchronisation contrôlée, pas à une divergence silencieuse.
|
||||
|
||||
## Reconnexion et resynchronisation
|
||||
|
||||
Cas à traiter :
|
||||
|
||||
- coupure courte ;
|
||||
- suspension mobile ;
|
||||
- changement de réseau ;
|
||||
- client trop en retard ;
|
||||
- trou dans les séquences ;
|
||||
- restart d'une instance serveur.
|
||||
|
||||
États conceptuels possibles :
|
||||
|
||||
```text
|
||||
Disconnected
|
||||
Connecting
|
||||
Joining
|
||||
Synchronized
|
||||
Resynchronizing
|
||||
Leaving
|
||||
```
|
||||
|
||||
Le jeu ne doit pas confondre « socket ouvert » et « état de gameplay synchronisé ».
|
||||
|
||||
## Rooms, instances et scaling
|
||||
|
||||
Pour plusieurs parties simultanées :
|
||||
|
||||
- une room/session possède une autorité unique à un instant donné ;
|
||||
- les connexions sont routées vers l'instance responsable ;
|
||||
- l'instance peut héberger plusieurs rooms selon charge ;
|
||||
- la distribution des rooms peut évoluer indépendamment du protocole client ;
|
||||
- les données persistantes ne doivent pas être écrites dans la DB à chaque tick sans nécessité.
|
||||
|
||||
À plus grande échelle, il faudra étudier :
|
||||
|
||||
- session placement ;
|
||||
- shard/region ;
|
||||
- sticky routing ;
|
||||
- handoff/migration ;
|
||||
- recovery après crash ;
|
||||
- autoscaling ;
|
||||
- limites par instance.
|
||||
|
||||
## Interest management
|
||||
|
||||
Pour un petit Snake 2 joueurs, diffuser tout l'état peut être acceptable.
|
||||
|
||||
Pour une map plus grande/MMORPG, il faut pouvoir limiter les données à :
|
||||
|
||||
- zone visible ;
|
||||
- proximité ;
|
||||
- équipe ;
|
||||
- objets pertinents ;
|
||||
- fréquence adaptée au type d'entité.
|
||||
|
||||
L'interest management appartient au service realtime/game server, pas au renderer client.
|
||||
|
||||
## Persistence
|
||||
|
||||
Séparer :
|
||||
|
||||
### État éphémère
|
||||
|
||||
- positions ;
|
||||
- velocities ;
|
||||
- animation/state machine ;
|
||||
- projectiles ;
|
||||
- tick courant.
|
||||
|
||||
### État durable
|
||||
|
||||
- compte ;
|
||||
- progression ;
|
||||
- inventory ;
|
||||
- résultat de match ;
|
||||
- rewards ;
|
||||
- classement.
|
||||
|
||||
Le durable est persisté à des frontières métier appropriées, pas mécaniquement à chaque frame.
|
||||
|
||||
## Sécurité / anti-cheat
|
||||
|
||||
Principes candidats :
|
||||
|
||||
- ne pas faire confiance à une position envoyée directement par un client compétitif ;
|
||||
- valider les actions et contraintes de jeu côté serveur ;
|
||||
- rate limit ;
|
||||
- protéger join/session tokens ;
|
||||
- empêcher replay/double-submit d'actions sensibles ;
|
||||
- enregistrer suffisamment de données pour diagnostiquer une divergence ou fraude.
|
||||
|
||||
## Observability
|
||||
|
||||
Le realtime nécessite au minimum des dimensions dédiées :
|
||||
|
||||
- connexions actives ;
|
||||
- rooms actives ;
|
||||
- joueurs/session ;
|
||||
- tick duration ;
|
||||
- tick lag ;
|
||||
- queue/backpressure ;
|
||||
- messages/s ;
|
||||
- bytes/s ;
|
||||
- reconnects ;
|
||||
- resyncs ;
|
||||
- dropped/invalid inputs ;
|
||||
- snapshot/delta sizes ;
|
||||
- errors par protocole/version.
|
||||
|
||||
Le logging par domaines devra pouvoir distinguer transport, session, sync et simulation.
|
||||
|
||||
## Technologies
|
||||
|
||||
Le choix exact reste volontairement ouvert.
|
||||
|
||||
Candidats à étudier ultérieurement selon le POC serveur :
|
||||
|
||||
- HTTP(S) pour control plane/API ;
|
||||
- WebSocket pour data plane bidirectionnel ;
|
||||
- gRPC pour backend-to-backend ou services structurés ;
|
||||
- WebRTC uniquement si un besoin P2P/media le justifie.
|
||||
|
||||
Le framework ne doit pas imposer une technologie unique à tous les services.
|
||||
|
||||
## Pressure test rapide
|
||||
|
||||
### Snake 2 joueurs
|
||||
|
||||
Peut probablement fonctionner avec :
|
||||
|
||||
- tick modéré ;
|
||||
- inputs directionnels ;
|
||||
- état authoritative ;
|
||||
- snapshot/delta simple ;
|
||||
- interpolation limitée ;
|
||||
- reconnect/resync.
|
||||
|
||||
### Racing
|
||||
|
||||
Exigera potentiellement :
|
||||
|
||||
- tick plus fréquent ;
|
||||
- prediction/reconciliation ;
|
||||
- interpolation ;
|
||||
- lag compensation selon gameplay ;
|
||||
- snapshots/deltas optimisés.
|
||||
|
||||
### Fighting 1v1
|
||||
|
||||
Peut nécessiter :
|
||||
|
||||
- input synchronization très stricte ;
|
||||
- rollback netcode ou stratégie équivalente ;
|
||||
- historique court déterministe.
|
||||
|
||||
### MMORPG
|
||||
|
||||
Exigera potentiellement :
|
||||
|
||||
- zones/shards ;
|
||||
- interest management ;
|
||||
- sessions longues ;
|
||||
- persistence structurée ;
|
||||
- chat/presence ;
|
||||
- recovery/scaling.
|
||||
|
||||
## Questions ouvertes pour le futur POC serveur
|
||||
|
||||
- Axum + Tokio + WebSocket suffit-il pour le premier service realtime ?
|
||||
- Une room est-elle une task, un actor, un shard ou une structure pilotée par scheduler ?
|
||||
- Quelle cadence de tick pour chaque genre ?
|
||||
- Quel codec : JSON de debug, bincode/postcard/protobuf/autre en production ?
|
||||
- Quelle frontière entre types de protocole partagés et logique serveur ?
|
||||
- Comment versionner le protocole sans coupler toutes les apps ?
|
||||
- Comment tester déterminisme, perte de paquets logique, reconnexion et resync ?
|
||||
- Quand introduire Redis/NATS/Kafka ou autre coordination, si jamais nécessaire ?
|
||||
|
||||
Ces choix appartiennent à la future planification/POC, pas à cette étude de réservation.
|
||||
Reference in New Issue
Block a user