Aller au contenu

Handshake

À la connexion, le serveur envoie immédiatement WELCOME\n à tout nouveau client (PendingClient, server/srcs/network/PendingClient.cpp). La première ligne renvoyée par le client détermine ensuite son type :

  • si c'est le mot-clé réservé GRAPHIC, le client devient un GUI ;
  • sinon, la ligne est interprétée comme un nom d'équipe : le client devient une IA s'il reste un œuf disponible dans cette équipe.

Tout l'aiguillage est réalisé par ClientSessionManager (server/srcs/core/ClientSessionManager.cpp).

Handshake IA

sequenceDiagram
    participant IA as zappy_ai
    participant S as Serveur
    S->>IA: WELCOME
    IA->>S: <nom-équipe>
    Note over S: éclosion d'un œuf de l'équipe
    S->>IA: <CLIENT-NUM>   (slots restants)
    S->>IA: <X> <Y>        (taille du monde)

Le client envoie son nom d'équipe. Si l'équipe existe et qu'il reste au moins un œuf libre, le serveur :

  1. fait éclore un œuf en un nouveau joueur (Player) ;
  2. renvoie <CLIENT-NUM>\n : le nombre de slots restants dans l'équipe, c'est-à-dire le nombre d'œufs encore disponibles après éclosion ;
  3. renvoie <X> <Y>\n : la largeur et la hauteur du monde.

(ClientSessionManager.cpp:123-127.)

Échec

Équipe inconnue ou aucun œuf disponible

Si le nom d'équipe est inconnu ou que l'équipe n'a plus d'œuf, le serveur répond ko\n puis ferme la connexion (ClientSessionManager.cpp).

Exemple (succès)

S -> C : WELCOME
C -> S : team1
S -> C : 5
S -> C : 10 10

Ici l'équipe team1 avait 6 œufs : après éclosion il en reste 5, et le monde mesure 10 × 10.

Côté IA

Le client IA attend la chaîne exacte WELCOME, envoie le nom d'équipe puis lit CLIENT-NUM et X Y. L'implémentation suppose que ces deux dernières lignes arrivent dans le même paquet (splitlines()), ce qui est fragile en cas de fragmentation TCP — voir Connexion IA et Limitations connues. Référence : ai/src/network/connection.py (do_handshake).

Handshake GUI

sequenceDiagram
    participant GUI as zappy_gui
    participant S as Serveur
    S->>GUI: WELCOME
    GUI->>S: GRAPHIC
    S->>GUI: msz X Y
    S->>GUI: sgt T
    loop pour chaque équipe
        S->>GUI: tna <nom-équipe>
    end
    loop pour chaque tuile (mct → bct)
        S->>GUI: bct X Y q0 q1 q2 q3 q4 q5 q6
    end
    loop pour chaque joueur
        S->>GUI: pnw #id X Y O L N
        S->>GUI: plv #id L
        S->>GUI: pin #id X Y q0..q6
    end
    loop pour chaque œuf
        S->>GUI: enw #œuf #joueur X Y
    end

Dès réception de GRAPHIC, le serveur réalise un dump initial complet de l'état du monde, dans cet ordre (ClientSessionManager.cpp:31-66) :

  1. msz X Y — taille de la carte ;
  2. sgt T — fréquence/unité de temps courante ;
  3. tna <nom> — un message par équipe ;
  4. la carte entière : sendMct parcourt toutes les tuiles et émet un bct par tuile (le GUI ne reçoit donc jamais de mct agrégé, voir l'avertissement plus bas) ;
  5. pour chaque joueur déjà présent : pnw, puis plv, puis pin ;
  6. pour chaque œuf existant : enw.

Exemple (extrait)

C -> S : GRAPHIC
S -> C : msz 10 10
S -> C : sgt 100
S -> C : tna team1
S -> C : tna team2
S -> C : bct 0 0 1 0 0 0 0 0 0
S -> C : bct 1 0 0 1 0 0 0 0 0
...
S -> C : bct 9 9 0 0 0 0 0 0 0
S -> C : pnw #1 4 5 2 1 team1
S -> C : plv #1 1
S -> C : pin #1 4 5 10 0 0 0 0 0 0
S -> C : enw #3 #-1 7 2

Dans pnw #1 4 5 2 1 team1, le joueur #1 est en (4,5), orienté 2 (Est), de niveau 1, équipe team1. Le format détaillé de chaque événement est donné dans GUI ↔ Serveur.

mct toujours détaillé en bct

Le serveur n'émet jamais d'événement mct consolidé : il l'« explose » en une série de bct (un par tuile). Côté GUI, le handler onMct existe mais est volontairement un no-op. Voir Limitations connues.