TetriNET Us, Baby!
Submission  :  Advanced Search  :  Site Statistics  :  Archives  :  Contact  :  Links  :  Polls  :  Calendar  :  Downloads  :  Forum  
Welcome to TETRINET.US
Tuesday, February 09 2010 @ 03:51 PM CET

TetriNET Protocol

Tetrinet Protocol (v1.13)-
Section 1 - Tetrinet Port
Section 2 - Logging raw protocol messages
Section 3 - Terminator
Section 4 - Logging in
Section 5 - Entering a channel
Section 6 - Partyline chatting
Section 7 - To Start / Stop and Pause a game
Section 8 - Playing the game
Section 9 - Sending Winlist Data
Section 10 - TetriFast : Protocol differences

1. Tetrinet Port
First of all, the Tetrinet Client connects to port 31457 of your Tetrinet Server.

2. Logging raw protocol messages
Let's look at a bit of communication I logged between my Tetrinet client and TSRV.COM :
TETRINET: 2D97C40EB529A42F96C10CB7E211429030A32E45B8EE187197FCÿ
TSRV.COM: winlist tTourTheAbyss;922 pFregge;855 pelissa;475 pDeadFireZero;447 pO.o;431 pDieterDHoker;429 tjustwrong;356 tYES;271 tCøunterTerrørists;228 tf47h0b0;209ÿ
TSRV.COM: playernum 1ÿ
TETRINET: team 1 ÿ
TSRV.COM: pline 0 TSRV.COM - Advanced Tetrinet/Tetrifast TETRINET ÿpline 0 ÿpline 0 ADMIN's : Lieven, DieterDHoker ÿpline 0 Operators: Blownaparte, VoKaL.7, Woopyÿpline 0 ÿpline 0 Type /help to see the possible commandsÿpline 0 ÿpline 0 UPDATES :     *** HAPPY 2003 ***ÿpline 0  - #Attacks &#TFattacks added,TETRINET attackingÿpline 0  - TETRINET will announce several things during game nowÿpline 0  - Use /addinfo to add extra info to your Profile! (/info3)ÿpause 0ÿpline 0 DieterDH has joined channel #cookiesÿ
TETRINET: pline 1 I'm talking in the partylineÿ
TETRINET: pline 1 Going to start the game now ÿ
TETRINET: startgame 1 1ÿ
TSRV.COM: pline 0 Game start has been requested by DieterDHÿ
TSRV.COM: newgame 0 1 2 1 1 1 18 3333333333333355555555555555222222222222222444444444444446666666666666677777777777777111111111111111 1111111111111111111111111111111112222222222222222222234444444444444566666666666666678888889999999999 0 1ÿ
TETRINET: f 1 ÿ
TETRINET: f 1 $3G3H4H5Hÿ
TETRINET: f 1 %>GHÿ
TETRINET: f 1 "7H8H9H:Hÿ
TETRINET: f 1 # I'm Sending a gamemessageÿ
TSRV.COM: gmsg  I'm Sending a gamemessageÿpline 1 (gamemessage) I'm Sending a gamemessageÿ
TETRINET: f 1 #8F7G8G9Gÿ
TETRINET: f 1 "9C9D9E9Fÿ
TETRINET: f 1 #4F5F4G5Gÿ
TETRINET: f 1 TETRINET: f 1 #7D7E8E7Fÿ
TETRINET: f 1 ":B:C:D:Eÿ
TETRINET: f 1 %D8>7?8?ÿ
TETRINET: f 1 ">@>A>B>Cÿ
TETRINET: f 1 !7>8>6?;?4@5@9@@3A:A"=?=@;A=A#7A9ATETRINET: f 1 "9?9@:@:Aÿ
TETRINET: f 1 !7?8?9?=?6@:@;@4A5AA"3?3@3A9A'4Hÿ
TETRINET: gmsg  Stopping the game nowÿ
TSRV.COM: gmsg  Stopping the game nowÿpline 1 (gamemessage) Stopping the game nowÿ
TETRINET: startgame 0 1ÿ
TSRV.COM: endgameÿ
TSRV.COM: pline 0 Game has been stopped by DieterDHÿ
TETRINET: pline 1 good game !ÿ
TETRINET: pline 1 logging of nowÿ
TETRINET: pline 1 byeÿ

3. Terminator
The first thing you notice is that every line ends with " ÿ " , this is the Terminator of the protocol (xFF)

4. Logging in
Okay let's look at the first line the client sends to the server to login :
2D97C40EB529A42F96C10CB7E211429030A32E45B8EE187197FC
After decoding this string you will get "tetrisstart DieterDH 1.13"
or in general : "tetrisstart <nickname> <version>"
The following C code will decode this :
String decode(String encodedString) {
    // Convert hex string to an array of int's
    int[] dec = new int[encodedString.length() div 2];
    for (int i = 0; i < dec.length(); i++)
        dec[i] = hexToInt(encodedString[i*2], encodedString[i*2+1]);
    // Create a char array of the first token. This should be tetrisfaster for TetriFast clients    
    char[] data = toChars("tetrisstart");
    // Find h from the encoding algorithm
    int[] h = new int[data.length()];
    for (int i = 0; i < data.length(); i++)
        h[i] = ((data[i]+dec[i]) mod 255) xor dec[i+1];
    int hLength = 5;
    for (int i = 5; i == hLength and i > 0; i--)
        for (int j = 0; j < data.length()-hLength; j++)
            if (h[j] != h[j+hLength])
                hLength--;
    // Decode the encoded string
    String decodedString = "";
    for (int i = 1; i < dec.length(); i++)
        decodedString = decodedString+(char)(((dec[i] xor h[(i-1) mod hLength])+255-dec[i-1]) mod 255);
    return decodedString;
}

Important to note is that Tetrinet uses the server's IP to encode this string ,
The build in server willalso decode this IP and if it is different from his IP it won't let you connect
and will give you a "*** Server has shutdown"-message
That's why you won't be able to use the build in server behind a NAT-router , even if you forward ports
Other servers (like ours) do not look at this encoded IP so they won't have this problem

This C code will encode a login-string when given a nickname and Server-IP (like the client does) :

String encode(String nickname, int[] IP) {
    String s = "tetrisstart "+nickname+" 1.13";
    String h = toString(54*IP[0]+41*IP[1]+29*IP[2]+17*IP[3]);
    int dec = random(0, 255);
    String encodedString = toHex(dec);
 // toHex converts dec to hex with two characters
    for (int i = 0; i < s.length(); i++) {
        dec = ((dec + s[i]) mod 255) xor h[i mod h.length()];
        encodedString = encodedString+toHex(dec);
    }
    return encodedString;
}

If for some reason or other, the server won't let the client connect, it may send the client the following:
" noconnecting <message> "

5. Entering a channel

1) Server sends winlist
In the second line the server sends the winlist to the client :
" winlist tTourTheAbyss;922 pFregge;855 pelissa;475 pDeadFireZero;447 etc..."
This can done at any time , to update the winlist .
The general format is : " winlist entry1 entry2 entry3 entry4 etc... "
where an entry consists of : " <t|p><Teamname|Playername>;<points> "
<t|p> : t=team-entry and p=player-entry .

2) Server sends playernumber and playerjoin
In the 3rd line the server gives the client a playernumber of an open slot in the channel :
" playernum 1ÿ "
This is pretty much selfexplaining : " playernum X "
Where X is a number of an open slot in the channel between 1 and 6 .
This can also be done at any time , allowing the server to move users
When a new player joins the channel the other players get " playerjoin X <nickname> "
so they know who is in the channel , what slot they are in and what nickname they have.

3) Client sends his team, server other teams
Okay the next thing that happens , is that the clients sends the server his team :
format : " team X <teamname> "
Where X his the playernumber of the user
This exact same string will be send to the other users , so they know what team everbody is on
And ofcourse the client will receive this string for every other palyer in the channel .
This also can be send at any time , so you can change team names at any time .

4) Server sends fielddata and gamestate
If there are users currently in the channel the server will send the field data off those users.
" f X <fieldstring> "
Where X is the playernumber , <and fieldstring< a string of 264 chars representing the field.
The tetrinet field has 12 colums and 22 rows -> 12*22 = 264
The chars can be : 0,1,2,3,4,5,a,c,n,r,s,b,q,o

CharWhatHexPicture
0blank(30)
1blue block(31)
2yellow block(32)
3green block(33)
4purple block(34)
5red block(35)
aspecial a(61)
cspecial c(63)
nspecial n(6E)
rspecial r(72)
sspecial s(73)
bspecial b(62)
gspecial g(67)
qspecial q(71)
ospecial o(6F)

example of a fieldstring :
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005100000000555111010005555511010005555551010225525521010225222222

Those field messages can be send anytime during the game , allowing "switch field" ,
but this also allows the server to send custom made fields to the client after starting a new game
To draw your own fields and generate a fieldstings I made this little program : TetrinetFields15.zip

The next thing the server does is sending a playerlost for everyone that died , including our client :
" playerlost X "
and if the game is currently active it will send an "ingame" message and if it is paused or not :
" ingame "
" pause 0|1"
where 0 = no pause , 1 = pause

5) When a player leaves
Client/Server sends: playerleave <playernumber>

6. Partyline chatting
1) Players/Server talking
example :
" pline 0 Game has been stopped by DieterDHÿ "
" pline 1 good game !ÿ "
General format :
" pline 0|X <text> "
Where X is a playernumber between 1 and 6
0 means the server is talking in stead of a user

2) Color codes
In the text you send to the partyline can also be special ASCII-codes
these will change the color or style of the text that comes after the code .
This style or color will can be ended by the same code.
example :
" this text is black [CODERED] text will be red [CODERED] This text will be black again"

CodeStyleSampleHex
3Cyan
03
4Black
04
5Blue
05
6,11Gray
06
8Magenta
08
12Green
17
14Lime
0E
15,21Silver
0F
16Maroon
10
17Dark Blue
11
18Olive
12
19Purple
13
20Red
14
23Teal
0C
24White
18
25Yellow
19
31Boldtext19
11Italictext19
21Underlinetext19

3) Action Messages

Like on IRC you can also use " /me text " to type an action-message.
This will result in " * Nickname text "
The client will send this format to the server which the server will pass on:

" plineact X <text> "

7. To Start / Stop and Pause a game

1) Client will request a game start / stop
The Client will request a game start / stop by sending:
" startgame 1|0 X "
where 1=Start game; 0=Stop game and X=playernumber

2) Server will start the game and send game settings
example:

newgame 0 1 2 1 1 1 18 33333333333333555555555555552222222222222224444444444444466666666666666777777777777771111111111111111111111111111111111111111111111112222222222222222222234444444444444566666666666666678888889999999999 0 1ÿ

General:

" newgame stack startinglevel linesperlevel levelincrease linesperspecial specialadded specialcapacity blockstring specialstring averagelevels classicrules "

The blockstring will consist of 100 chars (100%).
Each char can represent a certain block, so you can define the occurancy of each block in the game

CharWhatPicture
1line/stick
2square
3leftL
4rightL
5leftZ
6rightZ
7halfcross/triada

The same principle is used for the specialstring:

CharWhatPicture
1addline (a)
2clearline (c)
3nukefield (n)
4randomclear (r)
5switchfield (s)
6clearspecials (b)
7gravity (g)
8quakefield (q)
9blockbomb (o)

8. Playing the game
1) Sending field updates
we have already discussed a first way of sending field updates by sending a whole fieldstring.
Another way is by sending just partial filed updates
Let's look at an example :
" f 1 $3G3H4H5Hÿ "
in general : " f X partialupdatestring "
where X is a playernumber .
The partialupdatestring begins with defining the type of block .
In the example this $ represents a Green block
The total list :

CharTypeHexPicture
!blank/empty21
"blue block22
#yellow block22
$green block22
%purple block22
&red block22
'special a22
(special c22
)special n22
*special r22
+special s22
,special b22
-special g22
.special q22
/special o22

the following pairs of two chars are coordinates of where that block must be added :
The field has 22 rows , starting at the bottom with char H , then G , then F , ...
The field has 12 columns starting rigth with char 3 , char 4 , char 5 , char 6 , ...
So how do you know the difference between a total and a partial field update ?
0x21 <= $firstchar and $firstchar <= 0x2F

Then it is a partial field update , otherwise a total field update
For the following chars in a patialupdatestring the same rule can be applied to see wheter it is a Block Type or a Coordinate.

2) Using special blocks and classic style adds
Cookies and Classic style adds are send by this string :
" sb X type Y "
- X: the slotnumber to who you send it (0 = to all )
- type: "a","c","n",... for a cookie. "cs1","cs2","cs4" for classic style adds
- Y: the slotnumber where the special came from
Tclone (a program used to cheat with tetrinet) also sends "cs3" (=3 add lines to all)
but the normal tetrinet client doesn't , this is a way to detect cheaters .
Also if the "Y" doens't match the slotnumber of who send the string you also caught a possible cheater .

3) Sending game-messages
game-messages are send by the string :
" gmsg <nick> <message> "
But tetrinet doesn't check the nick it just displays it so you can just use :
" gmsg <message> " to send anything to the partyline ...

4) Level updates
Client sends level updates to the server in the following format, which the server sends to all to for the client to compute averaged levels:
" lvl <playernum> <level> "
where level is the current level for playernum

5) Player lost
Client sends to the server when they lose, which the server then sends to everyone else.
Format is seen here

6) Player won
When there are no more players/teams in the game, the client sends the following to the server, which the server then sends to everyone else:
" playerwon <playernum> "

9. Sending Winlist Data
(See here)

10. TetriFast : Protocol differences
The Tetrifast-game is the same as tetrinet except it has no delay between blocks .
(There is a 1 second delay with regular tetrinet)
The TetriFast Protocol is exactly the same as the tetrinet protocol ,
except these differences :
The decoded connection-string contains " tetrifaster " instead of " tetrisstart "
The command " playernum " has been changed to " )#)(!@(*3 "
The command " newgame " has been changed to " ******* "
so it is very easy to change tetrinet software to tetrifast software ,
if you don't have the source you could look for these strings with an hexeditor and change them ...


Sources:
DieterDH (TSRV.com) - Original full outline
Pihvi - Encoding/Decoding snippets


Last Updated Sunday, September 28 2008 @ 09:06 AM CEST; 1,622 Hits View Printable Version