Déplacements et combat
Endpoint proposé : /ws/game. Les messages respectent les conventions communes.
Chaque commande entrante ci-dessous exige un joueur authentifié appartenant à la partie, le bon round en ROUND_ONGOING et un émetteur avec hp > 0. Le client ne peut pas imposer de HP au backend.
| Événement | Direction | Fonction, comportement serveur et restrictions |
|---|---|---|
player.move | Client → Serveur | Recevoir position, rotation et séquence ; vérifier nombres finis et séquence récente, remplacer l’état et diffuser, sans simuler collisions ni déplacement. |
player.moved | Serveur → Clients | Diffuser username, position et rotation acceptés avec le même seq. |
player.shoot | Client → Serveur | Signaler un tir calculé dans Unity ; aucun calcul de trajectoire ni modification de HP. |
player.shot | Serveur → Clients | Relayer le username du tireur pour les effets visuels et sonores. |
player.hit | Client → Serveur | Recevoir identifiant de touche, cible et dégâts calculés par Unity ; vérifier cible adverse vivante dans la même partie, dégâts finis strictement positifs et absence de doublon, puis appliquer. |
player.damaged | Serveur → Clients | Diffuser attaquant, cible, dégâts effectivement appliqués et HP restants ; actualiser les interfaces. |
player.died | Serveur → Clients | Annoncer la première transition de la cible vers hp <= 0, compter mort et kill, puis vérifier les survivants pour décider d’une fin de round. |
L’attaquant est toujours l’identité authentifiée de la connexion. Les HP sont bornés à 0 : une touche de 60 sur une cible à 40 HP applique 40 dégâts. MatchPlayerStats.damage et player.damaged.data.damage utilisent ce dégât effectif. Une cible déjà éliminée, alliée ou identique à l’attaquant produit INVALID_TARGET. Proposition : pas de tir allié.
player.hit déclare un résultat Unity ; le backend ne refait pas le calcul de touche. player.shoot relaie les effets et ne nécessite pas d’historique de tirs pour accepter une touche. Un tir produisant plusieurs touches utilise un eventId distinct pour chaque touche.
Charges utiles
Mouvement, puis diffusion :
{
"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 } }
}
{
"type": "player.moved",
"matchUid": "match_123",
"roundNumber": 2,
"seq": 152,
"data": {
"username": "alice",
"position": { "x": 12.5, "y": 0, "z": 8.2 },
"rotation": { "x": 0, "y": 90, "z": 0 }
}
}
Tir, puis diffusion :
{ "type": "player.shoot", "matchUid": "match_123", "roundNumber": 2, "data": {} }
{ "type": "player.shot", "matchUid": "match_123", "roundNumber": 2, "data": { "username": "alice" } }
Touche, dégâts et élimination (dans cet exemple, chloe avait 40 HP avant la touche) :
{
"type": "player.hit",
"matchUid": "match_123",
"roundNumber": 2,
"data": { "eventId": "alice-r2-hit17", "targetUsername": "chloe", "damage": 60 }
}
{
"type": "player.damaged",
"matchUid": "match_123",
"roundNumber": 2,
"data": {
"eventId": "alice-r2-hit17",
"attackerUsername": "alice",
"targetUsername": "chloe",
"damage": 40,
"hp": 0
}
}
{
"type": "player.died",
"matchUid": "match_123",
"roundNumber": 2,
"data": { "username": "chloe", "attackerUsername": "alice", "hp": 0 }
}
Séquence — tir et élimination
La machine à états définit les phases autorisées. Les notifications de rounds décrivent la fin d’un round et la réinitialisation des joueurs.