Files
games/docs/studies/006-REALTIME_MULTIPLAYER_SERVER_STUDY.md

7.5 KiB

É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 :

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.