Protocole réseau

BZFlag utilise des protocoles réseau IP (Internet) standard. Le code est écrit sur l'interface du socket BSD, avec des ajustements pour Winsock sur les plates-formes Win32. Les révisions futures pourraient centraliser le code réseau dans un seul fichier, derrière une interface de classe unique, pour simplifier le portage vers des plates-formes sans l'API de socket BSD. La plupart des communications ne sont pas bloquantes. Autrement dit, les lectures et les envois reviennent immédiatement au lieu d'attendre que les données deviennent disponibles ou soient envoyées. C'est important puisque BZFlag est un jeu en temps réel. Il ne peut pas se permettre de rester bloqué en attendant l'arrivée d'un paquet. (La seule exception à cette règle est lorsque BZFlag se connecte à un serveur, et cela devrait être corrigé un jour.) La communication est multiplexée à l'aide de l'appel select(), qui informe l'appelant quelles sockets ont des données en attente de lecture et/ou sont prêtes à être envoyées. Au lieu de vérifier les données entrantes en essayant de lire chaque socket et de tester le succès, nous demandons simplement au système quelles sockets contiennent des données et lisons uniquement celles-ci. Cela signifie également que nous utilisons un seul thread pour la communication réseau. BZFlag utilise deux protocoles de transport distincts pour communiquer avec le serveur. La communication du serveur utilise TCP/IP pour plus de fiabilité. La communication des données de jeu en direct utilise UDP pour plus de rapidité et d'efficacité. Voir les autres pages pour plus de détails.

# Communication client/serveur

Le serveur BZFlag gère les jeux. Il est juge et arbitre entre les clients. Il gère les ressources et informations globales du jeu, telles que les drapeaux et les scores. Il n'applique pas les règles du jeu. On fait confiance aux clients pour suivre les règles, ce qui évite au serveur d'avoir à valider les kills et les manœuvres des clients. Par exemple, le serveur n'est pas informé des changements de position d'un client sur le plateau de jeu. Par conséquent, le serveur ne peut pas appliquer la règle selon laquelle les joueurs ne peuvent pas traverser les murs (sans les drapeaux OO ou PH). Cela permet à chaque client de s'exécuter librement. S'il fallait attendre que le serveur autorise chaque mouvement, il serait impossible de jouer à BZFlag sauf sur des réseaux rapides ou dédiés. De plus, les clients informent le serveur lorsqu'ils ont tué un autre joueur client. Le serveur ne vérifie pas que la mise à mort était légale, au-delà de vérifier si quelqu'un a déjà revendiqué une mise à mort sur le même joueur. Si plusieurs joueurs revendiquent une victoire ou tentent de récupérer un drapeau particulier, le serveur décide quel joueur remportera la victoire ou le drapeau. La communication client/serveur est principalement limitée aux messages qui doivent être transmis avec succès. Il s'agit notamment des notifications de joueurs vivant ou tués, de notifications de coups de feu, de drapeaux allant ou sortant, saisis ou lâchés. La communication client/serveur dans BZFlag se fait via TCP. TCP présente les avantages d’être bidirectionnel, fiable et séquentiel. Bidirectionnel signifie que chaque côté de la connexion peut envoyer vers l’autre. Fiable signifie que chaque message sera livré à la destination. Séquentiel signifie que les messages (sur une connexion particulière) seront reçus dans l'ordre dans lequel ils ont été envoyés. Le principal inconvénient de TCP est sa lenteur. La fiabilité peut nécessiter qu'un message donné soit envoyé plusieurs fois, jusqu'à ce que le destinataire accuse réception. Même si les retards peuvent causer des problèmes, il n’y a vraiment aucun moyen de les contourner. Les messages entre le client et le serveur sont spécifiquement les messages qui ne doivent pas être perdus. Si nous n'utilisions pas TCP, nous devrions simplement implémenter quelque chose qui ferait la même chose, et qui souffrirait nécessairement des mêmes inconvénients. Dans certains cas, la communication client/serveur n'utilise pas TCP. Un exemple est celui des tentatives du client pour localiser des serveurs sur le réseau. Les clients envoient des « pings » diffusés que les serveurs écoutent et auxquels ils répondent en nature. Ces messages ne font pas partie de la communication normale du jeu.

# Communication client/client

Les clients BZFlag envoient certaines informations à d'autres clients pendant une partie. Ces informations comprennent : l'état, la position, l'orientation et la vitesse linéaire et angulaire. Cet état peut changer rapidement et il n’est pas mieux de l’obtenir tard que de ne pas l’obtenir du tout. Les paquets client à client sont donc envoyés via UDP, un protocole de datagramme. UDP n'est pas fiable, ce qui signifie que la livraison des paquets n'est pas garantie. Il est également sans connexion, ce qui signifie que nous ne savons même pas si quelqu'un écoute le message. Cependant, c'est aussi rapide parce que c'est si simple. UDP répond à nos besoins car : nous avons besoin d’une livraison rapide ; peu nous importe qu'un message soit perdu car un autre arrivera peu de temps après ; et cela ne nous importe pas si le récepteur n'écoute pas. Les clients BZFlag doivent envoyer leurs informations à tous les autres clients. Il y a plusieurs moyens de le faire. Premièrement, chaque client peut envoyer chaque message à tous les autres clients. S'il y a N clients, chaque message est envoyé N-1 fois. Le trafic augmente à mesure que le carré des clients. C'est lent et inutile. Alternativement, chaque client peut envoyer tous les messages à un ordinateur spécial (par exemple, le serveur) et cet ordinateur peut transmettre les messages à tous les autres joueurs. Cela rend la vie plus facile pour les clients et beaucoup plus difficile pour le serveur. Cela retarde également la livraison de chaque message. Et le trafic provenant du serveur augmente toujours comme N au carré (bien que le trafic vers le serveur augmente de manière linéaire). Une autre possibilité est de diffuser des messages. Un message de diffusion est envoyé une fois et reçu par tous les ordinateurs d'un sous-réseau. Cela évolue de manière linéaire et minimise le trafic réseau, mais le trafic de diffusion n'est jamais acheminé en dehors du sous-réseau, ce qui signifie que seuls les clients du même sous-réseau du même réseau local peuvent jouer ensemble. BZFlag utilise la deuxième technique, en utilisant le serveur comme système de relais. Le serveur utilise la connexion client/serveur TCP pour envoyer le trafic client qui doit être fiable et UDP pour les informations qui doivent être opportunes mais qui n'ont pas besoin d'être fiables.

# Protocole

```
-> signifie du client au serveur
  <-- signifie du serveur au client

```

Toutes les données multi-octets sont classées dans l'ordre des octets du réseau (c'est-à-dire big endian) ; c'est-à-dire que l'octet le plus significatif vient en premier, suivi par les octets successivement moins significatifs. Tous les nombres sont des nombres entiers, sauf indication contraire. Les entiers peuvent être de 8, 16 ou 32 bits, signés en complément de 2 ou non signés (le codage est le même quel que soit le statut signé). Les valeurs dans ce document dans les zones d'octets sont données en hexadécimal. Les valeurs dans le texte sont données en décimal, sauf indication contraire. Les champs de bits sont codés sous forme d'entiers non signés. Tous les nombres à virgule flottante sont au format standard IEEE-754 simple précision. Les valeurs multi-octets ne sont \*pas\* nécessairement alignées sur des limites de 2 ou 4 octets. Un client suit normalement la séquence suivante pendant le jeu : se connecter au serveur obtenir la base de données mondiale rejoindre le jeu envoyer/recevoir des messages de jeu quitter le jeu se déconnecter du serveur structures de message courantes ------------------------- La plupart des messages commencent par la longueur du message en octets suivie d'un code de 16 bits. La longueur est de 16 bits et s'exclut elle-même ainsi que le code, c'est donc la longueur réelle du message moins 4.

Les identifiants des joueurs font 1 octet et sont utilisés dans de nombreux messages.

```
0 - 243 : Joueurs réguliers
        244 - 250 : identifiants des équipes spéciales
        251 - 252 : ID inutilisés
              253 : ServerPlayer (Armes mondiales, etc.)
              254 : Tous les joueurs
              255 : Aucun joueur (joueur invalide)

```

L'état des indicateurs est commun à quelques types de messages :

identifiant du drapeau U16 statut U16 type U16 identifiant du propriétaire u8 position flottante (x) position flottante (y) position flottante (z) lancement de flotteur (x) lancement de flotteur (y) lancement de flotteur (z) atterrissage sur flotteur (x) atterrissage sur flotteur (y) atterrissage sur flotteur (z) temps de vol du flotteur heure de fin du vol flottant vitesse initiale du flotteur

« Position », « lancement », « atterrissage », « temps de vol », « fin de vol » et « vitesse initiale » sont tous des nombres à virgule flottante. `Flag id' est le type de drapeau, énuméré dans FlagId.

`Status' donne l'emplacement actuel du drapeau :

```
FlagNoExist -- le drapeau n'est pas actif (c'est-à-dire pas dans le jeu)
  FlagOnGround : le drapeau est posé sur le sol, prêt à être ramassé
  FlagOnTank -- le drapeau est sur le tank d'un joueur
  FlagInAir -- le drapeau est en l'air et retombera
  FlagComing -- le drapeau vient d'apparaître et tombe au sol
  FlagGoing : le drapeau a été lancé en l'air et est en train de disparaître.

```

`Type' indique le comportement du drapeau : FlagNormal signifie que le drapeau est permanent et peut être abandonné normalement (par exemple un drapeau d'équipe) ; FlagUnstable signifie que le drapeau peut disparaître après utilisation (par exemple un bon super drapeau) ; FlagSticky signifie que le drapeau ne peut pas être abandonné normalement (par exemple un mauvais super drapeau). « ID du joueur » indique quel joueur possède le drapeau lorsque le « statut » est FlagOnTank. Il n’est utilisé pour aucun autre statut. La « Position » est l'emplacement du drapeau au sol. Cela n'a de sens que lorsque le « statut » est FlagOnGround. La position d'un drapeau sur un char est la position du char (centré sur et en haut du char) « Lancement » est l'endroit où le drapeau a été lancé en l'air. « Atterrissage » est l'endroit où le drapeau touchera le sol. Ceux-ci sont utilisés lorsque le « statut » est FlagInAir, FlagComing et FlagGoing. Le client doit faire en sorte que le drapeau suive une trajectoire de vol raisonnable (par exemple un arc parabolique) du « lancement » à « l'atterrissage ». Le « temps de vol » est le temps écoulé depuis que le drapeau a été lancé en l'air. « Fin du vol » : l'heure à laquelle le drapeau atteindra le sol. « Vitesse initiale » donne la vitesse verticale (z) du drapeau lors de son lancement. La position verticale du drapeau à l'instant t (allant de 0 à « fin du vol ») est : z = z0 + v \* t + 0,5 \* g \* t \* t. z0 = `lancer z;' v = « vitesse initiale ; » g = accélération due à la gravité.

## Connexion à un serveur

Le script bzfquery.php est un bel exemple de comment se connecter à un serveur.

Au début, vous devez ouvrir un socket. À partir du protocole 0048, vous devez envoyer "BZFLAG\r\n\r\n" afin d'obtenir une réponse. À ce moment-là, vous ne connaissez malheureusement pas le protocole, alors envoyez-le par défaut ou votre client se bloquera probablement.

```
--> se connecter (port du serveur)
  --> +----+----+----+----+----+----+----+----+----+- ---+
	 +----+----+----+----+----+----+----+----+----+---- +
  <-- +----+----+----+----+----+----+----+----+----+
 	 +----+----+----+----+----+----+----+----+----+

```

Le client doit vérifier la version. Dans les anciennes versions, les quatre premiers octets indiquent un serveur BZFlag, l'octet suivant indique le numéro de version majeure (sous forme de chiffre ASCII), les deux octets suivants sont le numéro de version mineure (sous forme de chiffres ASCII) et le 7ème octet est la révision. . Les modifications majeures et mineures des numéros de version indiquent des modifications de protocole incompatibles. Différentes révisions d'une version donnée sont compatibles et indiquent généralement simplement les modifications de l'interface utilisateur client. Un FF suivant termine le paquet. Dans les nouvelles versions, le protocole est simplement un nombre augmenté de 1 lorsque le protocole change.

Si la réponse était un protocole antérieur à 0048, alors bzfs expulsera le client qui s'y connecte. Dans ce cas, nous recommandons une solution de secours, en n'envoyant pas BZFLAG\r\n\r\n lors de la connexion, essayez :

```
--> se connecter (port du serveur)
  <-- +----+----+----+----+----+----+----+----+----+
 	 +----+----+----+----+----+----+----+----+----+

```

Les propriétaires de serveurs verront quelque chose comme ce qui suit dans les journaux si leur(s) serveur(s) utilisent un protocole antérieur à 0048 :

```
Le joueur [0] a envoyé un paquet très long (len=16986), attaque possible
  Joueur [0] supprimé le 11/04/2007 à 15:52:55 : réception de gros paquets

```

## Types de messages

Lisez ceci avec prudence, car il s’agit d’informations très anciennes qui ne reflètent pas la situation actuelle.

### du monde

```
--> +----+----+----+----+----+----+----+----+----+- ---+
	 +----+----+----+----+----+----+----+----+----+---- + (Liste des identifiants d'indicateur client)
  <-- +----+----+----+----+----+----+----+----+----+- ---+
	 +----+----+----+----+----+----+----+----+----+---- + (Liste des identifiants d'indicateur de serveur, que le client ne connaît pas)

```

Le client envoie au serveur la représentation sur deux octets de tous les indicateurs connus du client. Dans le cas où un indicateur ne comporte qu'une seule lettre, (N) par exemple, le deuxième octet est nul. Sinon, l'octet nul est implicite en position 3. Le serveur, à la réception de cette liste, trouve tous les indicateurs utilisés par le serveur, mais non connus du client, et envoie cette liste au client. Le client, à la réception de la liste, soit interdit la lecture si des indicateurs existent, soit continue si la liste est vide.

### obtenir le hachage mondial

```
--> +----+----+----+----+
	 +----+----+----+----+
  <-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Pour améliorer les performances, les fichiers World (bzc) sont mis en cache sur le client. Le nom du fichier cache est un hachage md5 du fichier calculé sur le serveur. ce hachage est envoyé au client et celui-ci recherche un fichier portant ce nom dans le répertoire du cache mondial bz. Si le hachage commence par un « t », le monde est un monde aléatoire. Si le hachage commence par un « p », le monde provient d'un fichier mondial. Si le client peut trouver le fichier localement, il n'envoie pas le paquet MsgGetWorld suivant.

### obtenir la base de données mondiale

```
--> +----+----+----+----+----+----+
	 +----+----+----+----+----+----+
  <-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 ou
	 +----+----+----+----+
	 +----+----+----+----+

```

Le client envoie des requêtes MsgGetWorld jusqu'à ce qu'il ait lu l'intégralité de la base de données mondiale. Les clients doivent envoyer un « offset » de 0 pour la première demande et augmenter le « offset » de la quantité de données envoyées en réponse. Chaque réponse MsgGetWorld inclut le nombre d'octets restants après le bloc de données renvoyé dans « restant ». Le serveur renvoie 0 dans « restant » lorsqu'il n'y a plus de données à lire. En aucun cas, le serveur ne retournera plus de MaxPacketLen - 6 octets de données dans une seule réponse (voir protocol.h pour la définition de MaxPacketLen). Le serveur peut renvoyer MsgSuperKill à tout moment pendant le téléchargement de la base de données mondiale. Le client doit immédiatement fermer la connexion au serveur. Aucun autre message ne doit être renvoyé par le serveur tant que le client envoie uniquement des requêtes MsgGetWorld.

Les « données » ont le codage suivant :

```
+----+----+----+----+
	 +----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Les valeurs sont :

```
version : version du format bzw
  worldsize : taille en mètres du monde
  style : champ de bits du style de jeu
  maxPlayrs : nombre maximum de joueurs
  maxShots : nombre maximum de tirs simultanés par joueur
  maxFlags : nombre maximum de drapeaux pouvant exister simultanément
  acc. linéaire : limite d'accélération linéaire (float)
  angulr acc. : limite d'accélération angulaire (float)
  shake t : il est temps de secouer un mauvais drapeau (1/10ème de seconde)
  shake w : nombre de victoires pour secouer un mauvais drapeau
  décalage d'époque : secondes depuis minuit le 1er janvier 1970 GMT sur le serveur, utilisé lorsque

```

synchronisation des heures entre les clients

La base de données du reste du monde est codée en blocs individuels décrivant chaque objet. Seuls les objets immobiliers permanents sont inclus. Les codages pour chaque type d'objet sont :

base d'équipe :

```
+----+----+----+----+
	 +----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+

```

mur:

```
+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

pyramide:

```
+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+

```

boîte:

```
+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+

```

téléporteur :

```
+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+

```

lien téléporteur :

```
+----+----+----+----+
	 +----+----+----+----+
 	 +----+----+----+----+

```

fin des données :

```
+----+----+----+----+
	 +----+----+----+----+

```

Les valeurs ci-dessus sont interprétées comme suit :

```
angle (float) : en radians à partir de l'axe x dans le plan xy
  largeur (flottant) : demi-largeur (en xy) mesurée à partir du centre
  profondeur (flotteur) : demi-profondeur (en xy) mesurée à partir du centre
  hauteur (flotteur) : hauteur totale (en z) mesurée à partir du bas
  bordure (flottant) : taille réelle de la bordure du téléporteur à section carrée
  centre (float) : centre en xy, bas en z
  sécurité (flotteur) : position de sécurité pour les drapeaux d'équipe, utilisée lorsque l'équipe A laisse tomber ceux de l'équipe B

```

drapeau sur la base de l'équipe C.

```
de & à : index du visage du téléporteur commençant à zéro ;  le Nième téléporteur

```

dans le monde, les données ont des indices de visage 2\*N et 2\*N+1. téléporteur les liens indiquent quel visage se téléporte vers quel visage ; les visages peuvent se téléporter vers eux-mêmes.

```
sdf (octet) : masque de bits :
                              le passage est le masque de bits 0x01
                              le tournage est un masque de bits 0x02

```

## rejoindre le jeu

Une fois connecté, un joueur demande normalement à rejoindre la partie. Le serveur répond avec MsgSuperKill, MsgReject ou MsgAccept.

```
--> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 ...
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 ...
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
  <-- +----+----+----+----+
	 +----+----+----+----+
	 ou
	 +----+----+----+----+----+----+
	 +----+----+----+----+----+----+
	 ou
	 +----+----+----+----+
	 +----+----+----+----+

```

« Type » est l'une des énumérations de PlayerType et « team » en est une de TeamColor. L'indicatif d'appel est le « pseudo » du joueur pendant la partie ; l'indicatif d'appel est utilisé pour identifier le joueur. Aucune tentative n'est faite par le serveur pour empêcher le duplication des indicatifs d'appel lors d'une partie. La devise peut être n'importe quoi, y compris l'adresse e-mail des joueurs humains (par exemple nom d'utilisateur @ nom d'hôte). Les joueurs de BZFlag peuvent choisir « anonyme » au lieu de leur devise. L'appel le signe et l'adresse e-mail doivent être des chaînes ASCII terminées par NUL, complétées par NUL à la longueur requise. La « longueur » est 12 + CallSignLen + EmailLen.

Si le serveur répond avec MsgSuperKill, le client doit fermer la connexion immédiatement. Si le serveur répond avec MsgReject, le client n'a pas rejoint le jeu mais peut garder la connexion au serveur ouverte et réessayer. Le motif du rejet est inclus avec le message MsgReject :

RejectBadRequest - fausses données dans MsgEnter RejectBadTeam -- identifiant d'équipe invalide RejectBadType -- type de client invalide RejectTeamFull -- plus aucun joueur autorisé dans l'équipe RejectServerFull -- plus aucun joueur autorisé dans aucune équipe

Si le serveur répond avec MsgAccept, le joueur a réussi à rejoindre la partie. Le serveur envoie ensuite automatiquement des mises à jour sur chaque drapeau, équipe et joueur. Le le client doit être prêt à accepter ces mises à jour dans n’importe quel ordre. Le drapeau et l'équipe les mises à jour sont envoyées respectivement sous forme de messages MsgFlagUpdate et MsgTeamUpdate. Joueur les mises à jour sont envoyées sous forme de messages MsgAddPlayer. Le client recevra un MsgAddPlayer pour le joueur qu'il vient d'ajouter, mais seulement après avoir reçu un MsgAddPlayer pour chaque des joueurs déjà inscrits.

Jusqu'à ce qu'il reçoive le MsgAddPlayer pour le lecteur qu'il vient d'ajouter, le client recevez uniquement les types de messages suivants :

MsgSuperKill MsgFlagMise à jour MsgTeamMise à jour MsgAddPlayer

Les joueurs de type ComputerPlayer ne reçoivent pas de mises à jour d'équipe ou de drapeau et reçoivent uniquement le MsgAddPlayer pour eux-mêmes. Ce n’était probablement pas une bonne idée, mais voilà.

## Quitter le jeu

Une fois inscrit, un joueur peut quitter le jeu à tout moment. Cela devrait être fait en envoyant le message suivant, puis fermeture de la connexion :

```
--> +----+----+----+----+
	 +----+----+----+----+

```

Il n'y a pas de réponse. Les clients peuvent également quitter en fermant simplement la connexion, mais il est recommandé d'envoyer MsgExit en premier.

un
--

Il existe plusieurs types de messages qui sont délivrés à tout moment après qu'un joueur entre dans un jeu. Les clients doivent être prêts à les traiter dans n'importe quel ordre.

MsgSuperKill

```
<-- +----+----+----+----+
	 +----+----+----+----+

```

Le client doit immédiatement se déconnecter du serveur.

MsgTimeLeft

```
<-- +----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Donne le temps restant dans la partie. Ce message n'est envoyé que lorsque le le serveur a une limite de temps configurée. Si le temps restant est nul, le client doit indiquer au joueur que la partie est terminée. Le « temps restant » est en secondes. Il n'est pas envoyé toutes les secondes, les clients auront donc besoin faire leur propre compte à rebours entre les messages.

MsgScoreOver

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Donne le joueur ou l'équipe qui a gagné la partie en atteignant le score cible. Ce message n'est envoyé que lorsque le serveur a un score cible configuré. Le client doit indiquer quelle équipe ou quel joueur a gagné et que le jeu est sur.

Si « ID d'équipe » est NoTeam, alors « ID de joueur » indique quel joueur a gagné. Sinon, « identifiant d'équipe » indique quelle équipe a gagné.

MsgAddPlayer

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé lorsqu'un autre joueur entre dans le jeu et lorsqu'il rejoint une partie si un autre joueur les joueurs sont déjà rejoints. `Type' est énuméré dans PlayerType, `team' est énuméré dans TeamColor. Les « victoires » et les « défaites » donnent le score du joueur. Ce sont des entiers non signés ; le score du joueur est égal aux victoires moins les pertes. « Indicatif d'appel » et « Adresse e-mail » sont des chaînes ASCII terminées par NUL. 'Longueur' est 16 + CallSignLen + EmailLen.

MsgSupprimer le lecteur

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+

```

Envoyé lorsqu'un autre joueur quitte la partie.

MsgFlagMise à jour

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+

```

Envoyé lorsque l'état d'un drapeau change. Également envoyé à un client lors de son entrée un jeu. `Flag num' est l'index du drapeau. Les drapeaux sont indexés à partir de zéro jusqu'au nombre maximum d'indicateurs moins un.

Les clients doivent mettre à jour les positions du drapeau pendant que le drapeau est en vol (c'est-à-dire « statut » est FlagInAir, FlagComing ou FlagGoing. Si FlagInAir ou FlagComing, le client doit changer le statut du drapeau en FlagOnGround lorsque le temps de vol du drapeau est égal ou supérieur à la « fin du vol ». La position doit être réglée exactement sur « atterrissage ». Si FlagGoing, le le client doit changer le statut du drapeau en FlagNoExist lorsque le vol le temps est égal ou supérieur à la « fin du vol ».

BZFlag utilise la première moitié du temps de vol pour FlagComing et le dernière moitié du temps de vol pour que FlagGoing fasse apparaître le drapeau ou disparaître de/vers rien. Cela permet aux joueurs de s'adapter au apparition/disparition d'un drapeau.

MsgTeamMise à jour

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Donne l'état actuel de l'équipe « équipe ». « Taille » est le nombre de joueurs de l'équipe. « Actif » est le nombre de joueurs actifs sur le équipe. Un joueur actif est celui qui peut participer au jeu (par exemple saisir des drapeaux, tirer sur des adversaires, etc.) ; un joueur non actif ne peut que observer le jeu. Seuls les joueurs actifs sont pris en compte pour décider s'il y a des joueurs dans une équipe (pour décider si le drapeau de l'équipe doit être inséré ou retiré du jeu). Les « victoires » et les « défaites » donnent le score de l'équipe (victoires moins défaites).

MsgAlive

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+

```

Envoyé lorsqu'un joueur prend vie. Un joueur qui a rejoint n'est pas sur le plateau de jeu jusqu'à ce qu'il envoie ce message, qui déclare qu'il est en jeu et donne la position de départ et l'orientation. Les joueurs sont supprimés du plateau de jeu lorsqu'il est tué et ne réapparaît pas avant d'envoyer ce message à nouveau.

```
--> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+

```

Un joueur envoie ce message pour entrer sur le plateau de jeu. Notez que ceci La version du message diffère de celle envoyée par le serveur en ce sens il lui manque l'identifiant du joueur (qui est implicite dans la connexion au serveur). Les joueurs doivent envoyer ce message pour changer leur état de mort à vivant. Les joueurs ne doivent pas envoyer MsgAlive pendant une certaine période de pénalité après être tué (mais le serveur n'impose pas de temps minimum). Le actuellement, la pénalité est ExplodeTime.

« Position » donne l'emplacement du joueur et « forward » donne l'emplacement du joueur. vecteur de direction avant du joueur.

MsgKilled

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Envoyé par le serveur lorsqu'un joueur est tué par lui-même ou par un autre joueur. L'identifiant de la victime est le joueur qui a été détruit et l'identifiant du tueur est le joueur crédité du meurtre. L'identifiant du tir identifie lequel des tueurs des coups de feu ont touché la victime ; si le tir n'est pas un laser ou une onde de choc, autre les joueurs peuvent supposer que le tir s'est arrêté et n'ont pas besoin de vérifier eux-mêmes contre le tir (ou ils peuvent attendre que le message MsgShotEnd arrive).

```
--> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Envoyé par la victime lorsqu'elle détecte qu'elle a été touchée, en désignant le tueur et lequel des tirs du tueur est celui qui a touché. Notez que le le serveur ne vérifie en aucun cas les kills, il est donc trivial de « tricher » en prétendre que vous avez été tué ; c'est généralement improductif. C'est aussi facile de tricher en n'envoyant jamais de MsgKilled, ce qui vous rend presque immortel. Ne fais pas ça.

MsgGrabFlag

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+

```

Envoyé par le serveur lorsqu'un joueur est autorisé à récupérer un drapeau. C'est à la fois l'avis au joueur essayant de saisir le drapeau qu'il a réussi et l'avis à tous les autres joueurs que le drapeau a été saisi. Note cet « identifiant de grabber » est redondant ; il est toujours égal à « identifiant du propriétaire ».

`Flag num' est l'index du drapeau. Les drapeaux sont indexés de zéro jusqu'à le nombre maximum de drapeaux moins un.

```
--> +----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Envoyé par un joueur lorsqu'il veut s'emparer d'un drapeau. Les joueurs devraient seulement envoyer ce message lorsque leur char est dans FlagRadius d'un drapeau (c'est-à-dire n'importe quelle partie du char, pas seulement le centre) et au sol. Le le serveur ne vérifiera pas cela, mais il vérifiera d'autres éléments. Le le joueur ne doit pas supposer qu'il sera capable de saisir le drapeau. Au lieu de cela, il a pour attendre une réponse MsgGrabFlag.

MsgDropFlag

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+

```

Envoyé par le serveur lorsqu'un joueur est autorisé à lâcher un drapeau. C'est à la fois l'avis au joueur essayant de laisser tomber le drapeau qu'il a réussi et l'avis à tous les autres joueurs que le drapeau a été abandonné. `Propriétaire id' n'a aucun sens dans ce message.

`Flag num' est l'index du drapeau. Les drapeaux sont indexés de zéro jusqu'à le nombre maximum de drapeaux moins un.

```
--> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par un joueur lorsqu'il veut lâcher un drapeau. Les joueurs devraient seulement envoyer ce message quand ils ont un drapeau et seulement quand le drapeau tombe les contraintes ont été respectées (c'est-à-dire que le drapeau peut être abandonné à tout moment, ou le joueur a obtenu le drapeau antidote, etc.) Le joueur ne doit pas l'assumer a abandonné le drapeau jusqu'à ce qu'il reçoive un MsgDropFlag en réponse.

La « Position » est en virgule flottante et correspond à la position du réservoir qui a laissé tomber le drapeau quand il a été abandonné.

MsgCaptureFlag

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par le serveur lorsque le drapeau d'une équipe a été capturé. `Identifiant du capteur' est le joueur qui a capturé le drapeau. `Flag num' est l'index du drapeau capturé. Les drapeaux sont indexés de zéro jusqu'au nombre maximum de drapeaux moins un. « Identifiant de l'équipe » est l'identifiant de l'équipe dont le drapeau était capturé. Notez que le joueur qui capture le drapeau peut faire partie de l'équipe qui a été capturé.

Le serveur fait mourir tous les joueurs de l’équipe capturée. Ce message est le seul avis indiquant que les joueurs sont maintenant morts, les clients doivent donc agir par conséquent. C'est aussi le seul avis indiquant que le capteur n'est plus portant un drapeau.

```
--> +----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Envoyé par un joueur lorsqu'il capture un drapeau d'équipe. « Identifiant de l'équipe » est l'identifiant de l'équipe dont le drapeau a été capturée. Le joueur doit attendre que le Le serveur renvoie la réponse MsgCaptureFlag avant de supposer que la capture a réussi. Un joueur ne doit envoyer ce message que lorsque 1) son char est au moins à mi-chemin à l'intérieur d'une base d'équipe, 2) le char est allumé le sol, et 3) le joueur a son propre drapeau d'équipe dans une base ennemie ou le joueur a le drapeau d'une autre équipe dans sa propre base. Notez que le le serveur n’appliquera aucune de ces exigences.

MsgShotBegin

```
<--
  --> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	     (x) |  poste (y) |  position
	 +----+----+----+----+----+----+----+----+
	     (z) |  vitesse (x) |  rapidité
	 +----+----+----+----+----+----+----+----+
	     (o) |  vitesse (z) |  temps
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par le serveur lorsqu'un joueur a tiré. Le même message est envoyé par un joueur lorsqu'il tire un coup. Le serveur ne vérifie pas que le joueur est autorisé à tirer un coup de feu.

« Shooter id » identifie le joueur qui a tiré. « Shot id » est un numéro qui identifie de manière unique le tireur qui a tiré. « Position », « vitesse », « temps » et « durée de vie » sont à virgule flottante Nombres. « Position » est la position de départ du tir. « Vitesse » est la vitesse de départ du tir. « Temps » est le temps dont dispose le tir existait (probablement 0,0). La « durée de vie » correspond à la durée pendant laquelle le plan existe. `Drapeau type' est un FlagId et est le type de drapeau que le tireur avait au moment du tir. a été congédié.

Les clients doivent calculer la trajectoire de vol des tirs (sauf les tirs guidés). Missiles) étant donné les informations contenues dans MsgShotBegin. Cela inclut la manipulation les ricochets, les impacts de bâtiments et la téléportation, mais pas les impacts de chars. Chaque joueur décide s'il a lui-même été touché par un tir à chaque pas de temps basé sur cette trajectoire de vol. Puisque la trajectoire d'un missile guidé ne peut pas être prévu, des mises à jour de la trajectoire d'un missile guidé sont envoyées tout au long de sa trajectoire. vol par le tireur via les messages MsgGMUpdate.

Un joueur doit se tester contre un tir en utilisant n'importe quel algorithme. aime, mais devrait au minimum tester les segments de ligne sur lesquels le tir se déplace pendant le pas de temps par rapport à une boîte englobante alignée sur le réservoir. La prise en compte du mouvement linéaire du réservoir au cours du pas de temps est mieux et il est préférable de prendre en compte à la fois le mouvement linéaire et angulaire toujours. Notez que le tir a un certain rayon qui devrait être pris en compte lors des tests d’intersection. C'est particulièrement important lors des tests contre un char avec le drapeau étroit. Idéalement, le tir serait exactement testé par rapport à la géométrie du char. Cependant, c'est plus de travail que ce qui est réalistement nécessaire.

MsgShotEnd

```
<--
  --> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par le serveur lorsqu'un tir a été terminé avant sa durée de vie a expiré. Le message identique est envoyé par le joueur qui termine le tir. Il s'agit normalement du joueur qui vient d'être touché par le coup de feu. Le serveur ne vérifie pas que le joueur a ou n'a pas été touché. Ce message est également envoyé par le joueur qui a tiré un missile guidé lorsque le tir touche le sol ou un bâtiment (à noter que les missiles guidés ne ricochent pas).

« Shooter id » identifie le joueur qui a tiré le coup et « shot id » est le même que dans le message MsgShotBegin pour la prise de vue. La « raison » est un si les autres joueurs doivent montrer une explosion pour le tir et zéro sinon.

MsgScore

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par le serveur lorsque le score d'un joueur change. « ID du joueur » est le joueur avec le nouveau score, et les « victoires » et les « défaites » sont les nouveaux scores.

```
--> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par un joueur lorsque son score change.

MsgTéléport

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par le serveur lorsqu'un joueur se téléporte. `From' est l'index du téléporteur face au joueur entré et `to' est l'index du visage le joueur est sorti.

```
--> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par un joueur lorsqu'il passe par un téléporteur.

MessageMessage

```
<-- +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 ...(MessageLen octets)...
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par le serveur lorsqu'un joueur envoie un message à d'autres. 'Longueur' est la longueur du message (18 + MessageLen octets). 'Depuis l'identifiant du joueur' est le joueur qui envoie le message, « à l'identifiant du joueur » est le joueur à qui recevoir le message, et « équipe » est l'équipe qui recevra le message. Si « l'identifiant du joueur » est composé uniquement de zéros, alors le message est envoyé à tout le monde dans «l'équipe». Si « identifiant du joueur » est composé uniquement de zéros et « équipe » est RogueTeam, le message est alors envoyé à tous les joueurs. Si `au joueur id' n'est pas que des zéros alors 'team' est ignoré et le message est uniquement destiné à le joueur identifié.

```
--> +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 ...(MessageLen octets)...
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+

```

Envoyé par le joueur pour envoyer un message aux autres joueurs. La « longueur » est la longueur du message (10 + MessageLen octets). « ID du joueur » est le joueur pour recevoir le message (ou tous les zéros pour tous les joueurs sur le équipe donnée) et `team' est l'équipe qui recevra le message (ou RogueTeam pour toutes les équipes).

MsgPlayerMise à jour

```
+----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	     (x) |  poste (y) |  position
	 +----+----+----+----+----+----+----+----+
	     (z) |  vitesse (x) |  rapidité
	 +----+----+----+----+----+----+----+----+
	     (o) |  vitesse (z) |  azimut
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Envoyé par les joueurs pour informer les autres joueurs des changements de son statut, position ou vitesse.

« Statut » est l'état actuel du char. Voir PlayerStatus pour le signification des bits du champ de bits. Le bit FlagActive indique si les pouvoirs spéciaux du drapeau du joueur sont actifs ou non. Le fantôme L'indicateur de zone est un exemple d'indicateur qui n'est actif que de temps en temps. Le bit CrossingWall indique si le tank du joueur est traversé par un mur ou un téléporteur ; d'autres joueurs peuvent l'utiliser pour dessiner le joueur d'une manière particulière. CrossingWall pourrait être calculé par chaque joueur à partir d'autres informations ; c'est uniquement prévu pour sauver les autres joueurs le problème.

"Position", "vitesse", "azimut" et "vitesse angulaire" flottent numéros de points. «Azimut» est l'orientation du char en radians (l'axe +x est 0,0, +y est pi/2). La « vitesse angulaire » est le changement de azimut par seconde. « Position » est la position du réservoir et « vitesse » est le changement de position du réservoir par seconde.

Un joueur n'envoie normalement une mise à jour que lorsque sa position ou son orientation comme pourraient le prédire les autres joueurs, diffère de sa véritable position ou orientation par une certaine tolérance. D'autres joueurs devraient utiliser les dernières données connues du joueur pour extrapoler la position actuelle et orientation. Cette technique est connue sous le nom d'estime et comporte deux principaux avantages : le trafic réseau est réduit puisque les mises à jour ne sont pas nécessaires être envoyé en continu et les joueurs sur des systèmes avec des fréquences d'images plus lentes semblent se déplacer en douceur vers les joueurs sur des systèmes avec des fréquences d'images plus rapides.

Les joueurs qui n'envoient pas de mises à jour assez souvent devraient être pris en compte ne pas répondre. Les joueurs qui ne répondent pas doivent être ignorés jusqu'à ce que ils recommencent à répondre.

MsgGMUpdate

```
+----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	     (x) |  poste (y) |  position
	 +----+----+----+----+----+----+----+----+
	     (z) |  vitesse (x) |  rapidité
	 +----+----+----+----+----+----+----+----+
	     (o) |  vitesse (z) |  temps
	 +----+----+----+----+----+----+----+----+
	 +----+----+----+----+----+----+----+----+
	 +----+----+

```

Envoyé par les joueurs équipés de missiles guidés actifs pour avertir les autres joueurs des changements apportés au mouvement du missile guidé.

Voir MsgShotBegin pour la signification de la plupart des éléments. 'Heure' est l'heure actuelle l'âge du coup (le temps écoulé depuis le tir). « Identifiant cible » est le cible actuelle du missile guidé ou tous les zéros s'il n'y a pas de cible.

Les joueurs doivent utiliser l'estime pour mettre à jour leur position et vitesse des missiles guidés entre les messages MsgGMUpdate. Depuis les missiles guidés ne s'écartent de leur trajectoire prévue que lorsque le changements de cible, ces messages seront assez rares. Notez que différent les joueurs peuvent avoir des idées différentes sur l'endroit où se trouve la cible et sur le fait que cela peut provoquer des parcours légèrement différents. Ce n'est généralement pas un problème.

MsgLagPing

```
+----+----+----+----+----+----+
	 +----+----+----+----+----+----+

```

Envoyé par le serveur aux joueurs actifs toutes les 10 secondes pour mesurer le décalage. Le le client renvoie simplement le message au serveur. Le temps entre l'envoi et la réception du message sur le serveur est considéré comme le décalage actuel du joueur concerné.

Le numéro de séquence à deux octets est inclus pour pouvoir gérer messages perdus ou fortement retardés. A chaque ping envoyé par le serveur, le numéro de séquence est incrémenté (modulo 10000). Le serveur gère ce nombre par joueur.

MsgReplayRéinitialiser

```
+----+----+----+----+----+
	 +----+----+----+----+----+

```

Envoyé par le serveur aux observateurs de relecture actifs pour supprimer l'état informations qu'ils pourraient avoir concernant les joueurs et les drapeaux. La valeur 'lp' est le dernier joueur à être supprimé. PlayerId est ci-dessus 'lp' sont des observateurs de relecture et ne sont pas supprimés.

## Négociation UDP

* les robots solo ne font pas cela, ils doivent utiliser la connexion du joueur existant

* MsgUDPLinkRequest = 0x6f66 ; // 'de'

* MsgUDPLinkEstablished = 0x6f67 ; // 'et'

* si le client a activé udp, le joueur envoie MsgUDPLinkRequest avec le numéro de joueur via udp

* si la demande a un numéro de joueur valide et provient de la même adresse, le serveur envoie MsgUDPLinkEstablished via TCP pour confirmer le serveur entrant, renvoie MsgUDPLinkRequest via UDP pour tester le trafic sortant

* le joueur obtient MsgUDPLinkEstablished et commence à envoyer udp

* le joueur obtient MsgUDPLinkRequest et envoie MsgUDPLinkEstablished via udp

* le serveur obtient MsgUDPLinkEstablished

le serveur peut maintenant envoyer via UDP