Skip to main content

Conventions communes

Les canaux joueurs et spectateurs partagent les conventions suivantes. Les données utilisent le modèle public ; les refus suivent le format commun des erreurs.

Connexion et enveloppe​

/ws/game exige le token dans l’en-tête Authorization de la négociation WebSocket Unity. Une négociation non authentifiée est refusée avec HTTP 401. Le backend lie la connexion au username vérifié : les commandes ne peuvent pas usurper un autre joueur. /ws/spectate est anonyme.

Chaque trame texte contient un objet JSON :

{
"type": "player.move",
"matchUid": "match_123",
"roundNumber": 2,
"seq": 152,
"data": {
"position": { "x": 12.5, "y": 0, "z": 8.2 },
"rotation": { "x": 0, "y": 90, "z": 0 }
}
}
ChampSignification et présence
typeIdentifiant exact de l’événement ; toujours requis
matchUidIdentifiant public de partie ; requis pour les événements d’une partie, absent de match.create, facultatif pour error
roundNumberRound concerné ; requis pour le gameplay et les notifications de rounds, facultatif pour le lobby et l’abonnement
seqEntier croissant pour synchroniser les mouvements ; requis dans player.move, repris dans player.moved et spectate.playerMoved
dataObjet spécifique à l’événement, éventuellement {}

Convention proposée : roundNumber: 0 dans le lobby, puis 1 au premier round. Cela ne fixe pas le nombre total de rounds. Un nouvel événement de gameplay portant un ancien round est refusé avec INVALID_MATCH_STATE.

Le compteur de mouvement seq est propre au joueur et au round. Il commence à 1. Le backend garde la dernière valeur acceptée, ignore les valeurs plus anciennes et renvoie DUPLICATE_EVENT pour une valeur déjà acceptée. Les destinataires n’appliquent que les mouvements plus récents du même username dans le même round. Le compteur repart au nouveau round ; après reconnexion, il reprend après la dernière valeur acceptée.

Pour les touches, utiliser data.eventId, unique par touche et par émetteur dans le round. Le backend mémorise (username authentifié, roundNumber, eventId) dans la partie avant d’appliquer les dégâts. Une retransmission garde ce même identifiant : elle ne doit jamais modifier une seconde fois HP et statistiques. seq ne remplace pas cet identifiant. Les autres événements n’exigent pas de séquence.

Diffusion et instantanés​

« Serveur → Clients » désigne tous les participants connectés, émetteur compris. match.created et les erreurs sont ciblés au demandeur. Les événements spectate.* sont réservés aux abonnés web.

match.stateChanged.data contient state, players et teams : les mêmes objets publics que l’instantané REST, sans son matchUid et son roundNumber, déjà présents dans l’enveloppe. Cet instantané complet est envoyé à chaque transition et au joueur qui rejoint ou se reconnecte. Il inclut tous les usernames, positions, rotations, HP, affectations et scores. Pour une reconnexion ciblée, l’enveloppe seq indique le dernier mouvement accepté du destinataire dans le round, ou 0 en l’absence de mouvement.

Le backend envoie l’instantané avant les mises à jour suivantes, dans l’ordre de traitement de la partie. Il ne doit pas perdre une mise à jour entre l’abonnement et la lecture de cet état.