~knarf

Description du protocole TetriNET

Suite à l’absence totale de documentation sur internet à ce sujet, j’ai télécharger le code sources de différents clients libres (gtetrinet et tetrinet-console) pour les étudier.

Ce document présente donc le protocole TetriNET. Il se veut suffisament exaustif pour pouvoir écrire un client/serveur, néamoins certaines choses ne sont pas tout à fait clair, si vous pouvez me corriger sur certains passages, n’hésitez pas à me le faire savoir.

Je suis joignable par mail à knarf2_AT_laposte_DOT_net et sur IRC à #diobla@Quakenet.org.


Introduction

TetriNET est un tetris multi-joueur en réseau avec quelques ajouts :

La dernière version officielle du client (et du protocole) est la 1.13 . Le port standart du serveur TetriNET est le port 31457.

Le protocole consiste en de simple commandes ASCII (ie. fait de caractère) d’une ligne dont le caractère final (le séparateur de ligne) a pour valeur 0xFF.

Déroulement d’une partie

La première chose que le client envoie lors de la connection est le hello message.
Le serveur lui envoie alors :

Le client renvoie ensuite son équipe.

Les joueurs peuvent discuter entre eux, avant qu’un joueur ayant le droit de lancer une partie (généralement celui à l’id-joueur 1 le fasse. Le serveur initialise la partie, en définissant certaines caractéristiques.

Durant la partie, les clients envoie l’état de leur jeu, reçoivent du serveur celui des autres, des spéciaux, des messages, etc.

Petit à petit les joueurs perdent, et le signale au serveur. Lorsqu’un gagnant est déclaré, le serveur le signale à tout le monde.

Le système de channel est géré par le serveur : /join #chan est envoyé tel quel au serveur. (Voir Commandes spécifiques au serveur) L’id-joueur change à chaque changement de channel et un joueur ne peut être que sur un seul channel à la fois. Il ne peut y avoir plus de 6 joueurs dans un channel et donc dans une partie.


Sommaire


Commande du client

Les commandes client, c’est-à-dire tout ce que le client envoie au serveur, sont listées ici.

Hello message

Le hello message est la première information envoyé au serveur lors de la connection. C’est une simple chaine de caractère encodé contenant l’ip du serveur, le nick du client et la version du protocole qu’il utilise. Voici le format de la chaine non-encodé :

tetrisstart <nick> 1.13

On peut rapidement trouver sur internet une implémentation de la fonction d’encodage.

Commencer/Arreter une partie

Permet au client de lancer/arreter une partie.
Necessite un id 1 ou 2. (dépend manifestement de l’implémentation)

startgame <etat> <id>
etat
1 ou 0, respectivement commencer et arreter la partie.
id
id-joueur du client.

Activer/Désactiver la pause

Permet au client de mettre/enlever la pause lors d’une partie.
Necessite un id 1 ou 2.

pause <etat> <id>
etat
1 ou 0, respectivement mettre et enlever la pause.
id
id-joueur du client.

Changement d’équipe

Permet de définir l’équipe du client. Généralement envoyé lorsque l’équipe change, ou lorsque que l’on rejoint un channel.

team <id>
team <id> <team>
id
id-joueur du client.
team
Nom de l’équipe. Facultatif

Lorsque team n’est pas fourni, le joueur n’a pas d’équipe. (Il est seul)

Messages et actions

Les différentes façons de recevoir des messages et action (à la IRC).

pline et plineact

Message hors-partie.

pline <id> <msg>
plineact <id> <msg>
id
id-joueur du client qui parle.
msg
message ou action.

gmsg

Message de jeu.

gmsg <nick> <msg>
nick
pseudo du joueur qui parle entre chevron.
msg
message.

Level du joueur

Envoi d’un spécial sb <to> <type> <from>

to
id-joueur du destinaitaire.
type
Le type de spécial envoyé.
from
id-joueur de l’envoyeur.

Voici un tableau de correspondance :

Type Effet
cs1 1 Line Added
cs2 2 Lines Added
cs4 4 Lines Added
a Add Line
c Clear Line
n Nuke Field
r Clear Random
s Switch Field
b Clear Specials
g Block Gravity
q Blockquake
o Block Bomb

Voir les règles de TetriNET pour une description plus précise.

Field du joueur

Reçut et envoyé au cours d’une partie, représente la totalité ou une partie du jeu d’un joueur.

  f <id> <field>
id
Id-joueur du field
field
2 solutions possibles :
  • Le field donné est donné en intégralité : field est alors une suite de 264 caractères (12x22) représentant le field du joueur, en partant du coin haut gauche.
    • le 0 représente un espace vide.
    • [1-5] correspond aux différents blocs.
    • [abcgnoqrs] correspond aux spéciaux.
  • Seulement une partie du field (si la majorité n’a pas changé) est donné, field est alors une suite de caractères de nombre variable :
    • On a un caractère A au code ASCII inférieur à '0' (48) représentant l’état du bloc suivit de N paires de caractère B au code ASCII supérieur ou égale à '0' correspondant respectivement au coordonnées x et y du bloc.
    • Tant que l’on ne recontre pas de caractère remplissant les conditions du caractère A, on traite les caractères comme des coordonnées de blocs, dont l’état correspondra au dernier caractère A rencontré.
    • Le tout premier caractère de la description du bloc est donc de type A, c’est ainsi que l’on reconnait la méthode d’envoie de field.

    • Les caractères A ne représentent pas directement l’état du bloc.
      Une manière pratique de l’obtenir consiste à soustraire la valeur ASCII de ! à celle de l’état pour obtenir un entier dont la valeur indique :
      • Pour les bloc vide, 0.
      • Pour les blocs normaux, [1-5].
      • Pour les spéciaux, [6-14], correspondant respectivement aux spéciaux a, b, c, g, n, o, q, r, s.
    • Un exemple vaut mieux qu’un long discours, voici une implémentation en C où s correspond un pointeur de caractère sur la chaîne à décoder, bloc un entier représentant l’état d’un bloc et field un tableau de caractère représentant le field.

      while (*s) {
          if (*s < '0') {
              bloc = *s - '!';
              else {
                  x = *s - '3';
                  y = (*++s) - '3';
                  field[y][x] = bloc;
              }
              s++;
          }
      }
      

On preferera envoyer le field avec la deuxième méthode lorsque les changements sont minimes (ajout d’une pièce, etc) et avec la première pour l’envoi du tout premier field ou pour le remplissage du field lorsque que le joueur perd.

Changement de niveau

Envoyé lorsque que le joueur change de niveau.

lvl <id> <lvl>
id
id-joueur du client.
lvl
Nouveau niveau.

Perte de la partie

Envoyé lorsque le client perd.

playerlost <id>
id

id-joueur du client.

Commandes spécifiques au serveur

Toute les commandes supplémentaire sont gérées de cette manière.

pline <id> /<cmd>
cmd

Commande

Cela va du /join #chan à /help, etc. Les commandes sont propres au serveur.


Commande du serveur

Les commandes serveurs, c’est-à-dire tout ce que le serveur envoie aux clients, sont listées ici.

Erreur de connection

Erreur envoyé par le serveur lors de la connection

noconnecting <err>
err

Raison de la déconnection.

Top score

Liste des meilleurs joueurs/équipe du serveur.

winlist <entry1> <entry2> <...>
entry
Entrée dans le top score du channel.
Chaque entrée est composé de 3 partie :
  • un caractère p ou t, designant respectivement player ou
team, indique si l’entrée correspond au nick d’un joueur ou au nom d’une équipe.
  • le nick/équipe
  • un point virgule, suivit du score.

Le nombre d’entrée peut varier de aucune à beaucoup.

Id-joueur

Donne l’id-joueur du client. Est envoyé à chaque chagement de channel (et à la connection).

playernum <id>
id

Nouvel id-joueur du client.

Arrivée/Départ d’un joueur

playerjoin

Envoyé lorsqu’un joueur rejoin la partie.

playerjoin <id> <nick>
id
id-joueur de l’arrivant sur le chan.
nick
nick de l’arrivant sur le chan.

playerleave

Envoyé lorsqu’un joueur quitte le chan.

playerleave <id>

Voir playerjoin.

Changement d’équipe

Lorsqu’un client change d’équipe, il envoit un (team). Le serveur envoie par la suite l’information à tous les joueurs du channel.

team <id>
team <id> <team>

Voir team (client).

Victoire d’un joueur

Lorsque qu’il ne reste plus que des joueurs de la même équipe en jeu, (ou qu’il ne reste plus qu’un joueur, dans le cas de joueurs sans équipe) ces derniers sont déclarés vainqueur. La commande suivante est envoyée à chacun des joueurs du channel.

playerwon <id>
id
id-joueur gagnant.

L’équipe du joueur est considérée gagnante (si le joueur en à une).

Messages et actions

Lorsqu’un joueur émet un message/action, le serveur fait passer le message à tous les autre joueurs du channel.

Note: L’id-joueur du serveur est 0.

Voir Messages et actions (client).

Nouvelle Partie

Après avoir reçut un startgame d’un joueur authorisé, le serveur envoie une commande spécifiant les caractéristique de la partie :

newgame <s> <inlvl> <lpl> <iclvl> <sl> <sco> <sca> <bf> <sf> <alvl> <old>
s
Hauteur de la pile (?). Semble inutilisé et toujours égal à 0.
inlvl
Level initial de chaque joueur.
lpl
Nombre de ligne par gain de level.
iclvl
Nombre de level à augmenter à chaque gain de level.
sl
Nombre de ligne nécessaire pour un spécial.
sco
Nombre de spécial ajouté à chaque fois.
sca

Nombre maximum de spéciaux dans l’inventaire.

bf
Fréquence d’apparition des différents blocs basique :
  • Composé de 100 caractères.
  • Chaque caractère représente le numéro d’un des pièces de Tetris (voir Pièces), permettant de constituer un pourcentage de bloc.
  • Ex:3333333333333355555555555555222222222222222444444444444446666666666666677777777777777111111111111111
    14% de bloc 3, 14% de bloc 5, 15% de bloc 2, 14% de bloc 4, 14% de bloc 6, 14% de bloc 7, 15% de bloc 1.
sf
Fréquence d’apparition des différents spéciaux :
  • Composé de 100 caractères.
  • Chaque caractère représente le numéro d’un des spéciaux ([1-9] respectivement [abcgnoqrs]), permettant de constituder un pourcentage de spécial.
  • Ex: même principe que bf.
alvl

Lorsque il est à 1, le gain de niveau d’un joueur est valable pour tous les joueurs. (ie. les joueurs ont tous le même niveau au tout au long de la partie.)

old

Lorsqu’il est à 1, un joueur faisant N lignes avec N > 1, ajoutera N lignes (ou N-1 lignes si N < 4) du serveur (id-joueur 0) à lui même.

Arrivée en cours de partie

Cette commande est envoyé au joueur qui rejoint un channel dans lequel une partie est déjà en cours.

  ingame

Active/désactive la pause

  pause <etat>
etat

Vaut 1 ou 0, correspond respectivement à mettre en pause, et l’enlever.

Fin de partie

Indique la fin de la partie en cours. Cette commande est envoyé lorsqu’un joueur remporte la partie ou quand il ne reste plus d’adversaires (s’il se sont déconnecté par exemple), etc.

  endgame

Field du joueur

Après avoir reçut un field d’un joueur, le serveur fait passer le message aux autre joueurs.

Voir Field du joueur (client).

Level du joueur

Après avoir reçut un changment de niveau d’un joueur, le serveur fait passer le message aux autre joueurs.

Voir Level du joueur (client).


Annexe

Le field

Le terrain de jeu (ou field) de chaque joueurs fait 12 blocs de larges pour 22 blocs de hauteur. Un joueur a perdu lorsque l’une de ses pièces dépasse la 22eme ligne de son jeu.

Les pièces

Les pièces sont les groupements de blocs qui tombent lors d’une partie de TetriNET. Chaque pièce possède un numéro [1-7]), et chaque bloc qui la composent porte tous un même numéro, ([1-5]) correspondant à la couleur.

La pièce 1 : la barre

####

La pièce 2 : le carré

##
##

La pièce 3 : le J

 #
 #
##

La pièce 4 : le L

#
#
##

La pièce 5 : le Z

##
 ##

La pièce 6 : le S

 ##
##

La pièce 7 : le T

 #
###

La sélection des pièces est aléotoire, mais essaye de respecter la fréquence imposé par le serveur.