Difference between revisions of "Network protocol (Worms Armageddon)"

From Worms Knowledge Base

Jump to: navigation, search
(Player list)
(General)
(5 intermediate revisions by the same user not shown)
Line 6: Line 6:
 
* DWord size = 4 bytes
 
* DWord size = 4 bytes
 
* Everything is LSB on the wire (Little Endian)
 
* Everything is LSB on the wire (Little Endian)
 +
 +
Is it possible to write a bot?
 +
 +
It surely is. However the bot doesn't have access to very much information. It cannot tell who won or lost for example. The game relies on all of the clients performing identical simulations. So nothing other than what you get in a replay file is transmitted for each turn. This excludes any win/or loss data or anything like that. Your bot could spectate games, chat, and perform all the lobby actions and that's about it.
 +
 +
A minimal client with a readline command interface is available here https://github.com/giannitedesco/wabs under the terms of the GPLv3.
  
 
== Message header ==
 
== Message header ==
Line 30: Line 36:
 
|}
 
|}
 
Length: 6
 
Length: 6
 +
 +
For in-game messages where the second byte is set to 2, the structure is slightly different.
 +
{| border="1"
 +
!Offset
 +
!Size
 +
!Value
 +
|-
 +
|00
 +
|Byte
 +
|2
 +
|-
 +
|01
 +
|Byte
 +
|(??) may be ignored
 +
|-
 +
|02
 +
|Word
 +
|Message size (max is 0x1414, if larger, the header(s) is(are) sent again)
 +
|-
 +
|04
 +
|Byte
 +
|Player ID
 +
|-
 +
|05
 +
|Word
 +
|Flags? Maybe a bitmap? Observed values of 1, 2 and 4.
 +
|-
 +
|07
 +
|Word
 +
|Frame sequence number. Incremented every time a message is sent.
 +
|}
 +
Length:9
  
 
== Packet Commands List ==
 
== Packet Commands List ==
Line 176: Line 214:
 
|35
 
|35
 
|The client sends this after the 0x22 , can't get it to work.
 
|The client sends this after the 0x22 , can't get it to work.
 +
|-
 +
|0x24
 +
|36
 +
|Server sends this when a game is over. It seems to be a sort of ping.
 +
|-
 +
|0x25
 +
|37
 +
|Client sends this in response to a 0x24. If not the server keeps resending the 0x24 packet and the player appears to have timed out in the post-game lobby area.
 +
|-
 +
|0x26
 +
|38
 +
|The client sends this after the 0x22 , can't get it to work. The server also sends this after a game has finished, and after sending the 0x24 packet.
 
|-
 
|-
 
|0x27
 
|0x27
Line 296: Line 346:
 
Figure out what the rest is.
 
Figure out what the rest is.
  
Considering there can be 7 players, the total length should be 840 bytes.
+
There are 6 bytes of unknown, followed by 7 player structs. The structure for each player is:
Array starts at 06.
+
{| border="1"
 +
!Offset
 +
!Size
 +
!Value
 +
|-
 +
|00
 +
|17
 +
|name
 +
|-
 +
|17
 +
|108
 +
|unknon
 +
|-
 +
|125
 +
|2
 +
|prev, signed integer pointing to previous player, set to -1 for first entry
 +
|-
 +
|127
 +
|2
 +
|unknown
 +
|-
 +
|129
 +
|1
 +
|country code (for flag)
 +
|-
 +
|130
 +
|7
 +
|unknown
 +
|}
  
Depending, that leaves 330, 328 or 324 trailing bytes.
+
After that, there is 520 bytes unknown, a 16 byte integer with the total number of valid players and then 2 bytes unknown.
Figure out what follows (or what is before the array).
+
 
+
The structure for each player is:
+
char name[17];
+
uint8_t unknown[17];
+
uint8_t unknown[14];
+
uint8_t unknown[60];
+
int16_t prev; // index of previous player struct? first player it's set to -1
+
uint16_t unknown;
+
uint8_t country;
+
uint8_t unknown[7];
+
  
 
== Team list ==
 
== Team list ==
Line 324: Line 391:
 
|}
 
|}
  
TODO
+
The structure here is subtly different to the WGT format. Furthermore the [[#Add Team]] message is completely different again. And reverse engineering that is complicated by the fact that the game doesn't appear to scrub the unused bytes in the structure to zero. So it leaks some random heap or stack that way.
 +
 
 +
{| border="1"
 +
!Offset
 +
!Size
 +
!Value
 +
|-
 +
|00
 +
|Word
 +
|Unknown
 +
|-
 +
|2
 +
|Word
 +
|Slot number in the teams-list
 +
|-
 +
|4
 +
|Word
 +
|Unknown
 +
|-
 +
|6
 +
|Byte
 +
|Player ID
 +
|-
 +
|7
 +
|Byte
 +
|Color
 +
|-
 +
|8
 +
|Byte
 +
|Unknown
 +
|-
 +
|9
 +
|17
 +
|Team name
 +
|-
 +
|26
 +
|32
 +
|Soundbankk name
 +
|-
 +
|58
 +
|word
 +
|Soundbank flags?
 +
|-
 +
|60
 +
|30
 +
|Fanfare
 +
|-
 +
|90
 +
|Byte
 +
|Unknown
 +
|-
 +
|91
 +
|30
 +
|Fanfare again, why?
 +
|-
 +
|121
 +
|41
 +
|Unknown
 +
|-
 +
|162
 +
|8 * 17
 +
|Worm names
 +
|-
 +
|298
 +
|3160
 +
|Unknown, but some similarities to the WGT file. There's certainly a flag bitmap in there among other things
 +
|}
  
 
== Custom Scheme data ==
 
== Custom Scheme data ==
Line 538: Line 671:
 
|Version of the Game (4C for the normal 3.6.28.0)
 
|Version of the Game (4C for the normal 3.6.28.0)
 
|}
 
|}
 +
 +
After this, we switch to type-2 packets documented above. All players send loading status reports up to frame number 0x1b. The report for 0x1b contains some sort of magic which is presumably a sort of checksum on the game logic such as worm placement and map generation. If it's not correct then the game notifies of invalid data and won't let the game start. Best bet is to listen for one player to finish and echo his magic number back.
 +
 +
Here is an example of what is received when 2 other players are in the game:
 +
 +
<tt>
 +
Frame: player=0 frame=0x00000001 len=4
 +
| 00000 : ....              c0 0a 00 00
 +
Frame: player=0 frame=0x00000002 len=4
 +
| 00000 : ....              c0 0a 04 00
 +
Frame: player=2 frame=0x00000001 len=4
 +
| 00000 : ....              c0 0a 00 00
 +
Frame: player=2 frame=0x00000002 len=4
 +
| 00000 : ....              c0 0a 04 00
 +
Frame: player=2 frame=0x00000003 len=4
 +
| 00000 : ....              c0 0a 08 00
 +
Frame: player=0 frame=0x00000003 len=4
 +
| 00000 : ....              c0 0a 08 00
 +
Frame: player=0 frame=0x00000004 len=4
 +
| 00000 : ....              c0 0a 0c 00
 +
 +
 +
snip ...
 +
 +
Frame: player=0 frame=0x0000001a len=4
 +
| 00000 : ..d.              c0 0a 64 00
 +
Frame: player=2 frame=0x0000001a len=4
 +
| 00000 : ..d.              c0 0a 64 00
 +
Frame: player=2 frame=0x0200001b len=7
 +
| 00000 : @.GQ{7.          40 09 47 51 7b 37 00
 +
Frame: player=0 frame=0x0200001b len=7
 +
| 00000 : @.GQ{7.          40 09 47 51 7b 37 00
 +
</tt>
  
 
== Map ==
 
== Map ==

Revision as of 08:57, 6 July 2014

(Up to Game logic)

General

  • Sizes and offsets are in bytes
  • All offsets are from the start of the packet's data
  • Word size = 2 bytes
  • DWord size = 4 bytes
  • Everything is LSB on the wire (Little Endian)

Is it possible to write a bot?

It surely is. However the bot doesn't have access to very much information. It cannot tell who won or lost for example. The game relies on all of the clients performing identical simulations. So nothing other than what you get in a replay file is transmitted for each turn. This excludes any win/or loss data or anything like that. Your bot could spectate games, chat, and perform all the lobby actions and that's about it.

A minimal client with a readline command interface is available here https://github.com/giannitedesco/wabs under the terms of the GPLv3.

Message header

Offset Size Value
00 Byte 1 for frontend messages, 2 for ingame (compression ?)
01 Byte (??) may be ignored
02 Word Message size (max is 0x1414, if larger, the header(s) is(are) sent again)
04 Word Command

Length: 6

For in-game messages where the second byte is set to 2, the structure is slightly different.

Offset Size Value
00 Byte 2
01 Byte (??) may be ignored
02 Word Message size (max is 0x1414, if larger, the header(s) is(are) sent again)
04 Byte Player ID
05 Word Flags? Maybe a bitmap? Observed values of 1, 2 and 4.
07 Word Frame sequence number. Incremented every time a message is sent.

Length:9

Packet Commands List

Hex Dec Description
0x00 00 #Chat Message
0x01 01 ???????
0x02 02 ???????
0x03 03 ???????
0x04 04 Login from client (completeme)
0x05 05 Another login from client (completeme)
0x06 06 Client sends password (completeme)
0x07 07 Password Required (no data)
0x08 08 Sucessfully joined (or password ok) need to figure out what the data means (version of the host ??)
0x09 09 Wrong password (no data)
0x0A 10 Error joining (nickname already used, or missing, or flag missing/incorrect) < need to figure out exact symptoms
0x0B 11 #Player list
0x0C 12 #Team list
0x0D 13 #Custom Scheme data
0x0E 14 Player joined (sent to already connected players)
0x0F 15 #Ready signal
0x10 16 #Remove Team
0x11 17 #Changing Scheme data Round Time
0x12 18 #Changing Scheme data Turn Time
0x13 19 #Changing Scheme data Victories needed
0x14 20 #Changing Scheme data Worm Selection
0x15 21 #Changing Scheme data Worms HP
0x16 22 #Change Team - team color
0x17 23 #Change Team - team handicap
0x18 24 #Change Team - number of worms
0x19 25 Player left the game (sent to connected players)
0x1A 26 #Add Team
0x1B 27 You have been Kicked (no data)
0x1C 28 #Starting Game
0x1D 29 #Changing Scheme data Worm Placment
0x1E 30 ?????????
0x1F 31 #Default Scheme data
0x20 32 Default Maps (like ArtClass) just a String with the map name, 40 bytes long
0x22 34 This packet is sent from server when version = 0, very weird.
0x23 35 The client sends this after the 0x22 , can't get it to work.
0x24 36 Server sends this when a game is over. It seems to be a sort of ping.
0x25 37 Client sends this in response to a 0x24. If not the server keeps resending the 0x24 packet and the player appears to have timed out in the post-game lobby area.
0x26 38 The client sends this after the 0x22 , can't get it to work. The server also sends this after a game has finished, and after sending the 0x24 packet.
0x27 39 Gameid incorrect (or no more place ?)
0x2B 43 #Map

Chat Message

Command: 0x0000
Direction: Both
Size: Variable

Just a String, 00 Terminated.

Type:FromNick:ToNick:Text

Differents Types

Normal Message : GLB

Private Message : PRV

System Message : SYS

Notes :

- ToNick is often set to "ALL" to be sent to everyone (doesn't work for whispers)

- When X types /me Text, it sends this : SYS:X:ALL:X Text

- For systems messages, FromNick can be null, since it's not shown

Join

Joining consists of several steps:

Step 1

Command: 0x0004
Direction: From client
Size: 128
  • Nick at 06, null terminated, ends (last place the null could be) at 22.
  • Gameid (ascii) at 23, null string for IP games.
  • Version at 64, composed of 30 24 F4 (hex)

NB : these 3 parameters are sufficient to enter a game. Everything else can be 0 and it's ok. Figure out what follows.

Step 2

Command: 0x0008
Direction: To client
Size: 6

Acknowledgement. Empty message. Figure out error messages. (different commands?)

Step 3

Command: 0x0005
Direction: From client
Size: 114
  • Nick at 06, null terminated.
  • Flag (+1) at 72 (if 13 is France, then to put French flag, you have to put 13+1 = 0x0E)

Figure out what follows.

Step 4

Server sends:

  • Player list, see below.
  • Team list (when not empty), see below.
  • Map data, see below. (Map is not sent when we rejoin?)
  • A message with command 0x001f? What is it?

Figure out how the scheme is sent here when it's not the default Intermediate

Player list

Command: 0x000b
Direction: To client
Size: 1176

This looks like it's sending a raw array of player structures. Each player structure is 120 bytes in size.

Names are limited to 17 characters, and are padded with 0 bytes. (If a name is exactly 17 characters, there will NOT be a null-terminator) Figure out what the rest is.

There are 6 bytes of unknown, followed by 7 player structs. The structure for each player is:

Offset Size Value
00 17 name
17 108 unknon
125 2 prev, signed integer pointing to previous player, set to -1 for first entry
127 2 unknown
129 1 country code (for flag)
130 7 unknown

After that, there is 520 bytes unknown, a 16 byte integer with the total number of valid players and then 2 bytes unknown.

Team list

Command: 0x000c
Direction: To client
Size: ??

The structure here is subtly different to the WGT format. Furthermore the #Add Team message is completely different again. And reverse engineering that is complicated by the fact that the game doesn't appear to scrub the unused bytes in the structure to zero. So it leaks some random heap or stack that way.

Offset Size Value
00 Word Unknown
2 Word Slot number in the teams-list
4 Word Unknown
6 Byte Player ID
7 Byte Color
8 Byte Unknown
9 17 Team name
26 32 Soundbankk name
58 word Soundbank flags?
60 30 Fanfare
90 Byte Unknown
91 30 Fanfare again, why?
121 41 Unknown
162 8 * 17 Worm names
298 3160 Unknown, but some similarities to the WGT file. There's certainly a flag bitmap in there among other things

Custom Scheme data

Command: 0x000d (13dec)
Direction: To client
Size: 308
Offset Size Value
00 Word (??)
02 DWord An identifier for the scheme. (-1 for custom, scheme, 1-13 for default (edited) scheme)
06 292 bytes Scheme file withouth "SCHM" header
298 DWORD (?)

Default Scheme data

Command: 0x001f (31dec)
Direction: To client
Size: 12
Offset Size Value
00 Word (??)
02 DWord An identifier for the scheme.
Identifier Scheme
1 Beginner
2 Intermediate
3 Pro
6 Artillery
7 Classic
8 Armageddon
9 The Darkside
11 Retro
13 Strategic
14 Sudden Sinking
15 Tournament
16 Blast Zone
17 The Full Wormage

If you put 0 as Scheme Identifier, it will crash the game. Any other number that doesn't appear in the list will put Intermediate.

Changing Scheme data

Command: Depends
Direction: To client
Size: 12
Offset Size Value
00 Word Always 0x3E (62dec) ?
02 DWord Value
Command Description
0x11 (17dec) Round Time (Positive = Minutes, Negative = Seconds)
0x12 (18dec) Turn Time (FFFFFFFF = Infinite)
0x13 (19dec) Victories needed
0x14 (20dec) Worm Selection (0 = Disabled ; 1 = Enabled)
0x15 (21dec) Worms HP
0x1D (29dec) Worm Placment (0 = Disabled ; 1 = Enabled)

Ready signal

Command: 0x000f
Direction: Both ways
Size: 16
Offset Size Value
08 DWord on/off
0B DWord Player number

Starting Game

Command: 0x001c
Direction: To client
Size: 20
Offset Size Value
06 Word I guess this is only not important junk and can be anything (need verification)
08 DWord HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Data\LogicSeed
0C DWord "GSAW" (this is hardcoded, but i think it can be anything, not important)
10 DWord Version of the Game (4C for the normal 3.6.28.0)

After this, we switch to type-2 packets documented above. All players send loading status reports up to frame number 0x1b. The report for 0x1b contains some sort of magic which is presumably a sort of checksum on the game logic such as worm placement and map generation. If it's not correct then the game notifies of invalid data and won't let the game start. Best bet is to listen for one player to finish and echo his magic number back.

Here is an example of what is received when 2 other players are in the game:

Frame: player=0 frame=0x00000001 len=4
| 00000 : ....              c0 0a 00 00
Frame: player=0 frame=0x00000002 len=4
| 00000 : ....              c0 0a 04 00
Frame: player=2 frame=0x00000001 len=4
| 00000 : ....              c0 0a 00 00
Frame: player=2 frame=0x00000002 len=4
| 00000 : ....              c0 0a 04 00
Frame: player=2 frame=0x00000003 len=4
| 00000 : ....              c0 0a 08 00
Frame: player=0 frame=0x00000003 len=4
| 00000 : ....              c0 0a 08 00
Frame: player=0 frame=0x00000004 len=4
| 00000 : ....              c0 0a 0c 00


snip ...

Frame: player=0 frame=0x0000001a len=4
| 00000 : ..d.              c0 0a 64 00
Frame: player=2 frame=0x0000001a len=4
| 00000 : ..d.              c0 0a 64 00
Frame: player=2 frame=0x0200001b len=7
| 00000 : @.GQ{7.           40 09 47 51 7b 37 00
Frame: player=0 frame=0x0200001b len=7
| 00000 : @.GQ{7.           40 09 47 51 7b 37 00

Map

Command: 0x002b
Direction: To client
Size: 64
Offset Size Value
06 Byte (??)
07 Byte Always 01 ?
08 DWord File Lenght
0C DWord Data Offset
10 DWord Data Lenght
14 Data Lenght Data

Note : A DWord is put at the beginning of the File to tell what type of Map is sent.

1 = .BIT Monochrome map (.bit, .lev)

2 = .LEV Monochrome map (.bit, .lev)

3 = .PNG Colour map

Exemple of a multi-packeted BIT-file (135434(0x34DE)bytes file):

<01 48 1414 2B00> <A2 01 [E2 34 00 00] [00 00 00 00] [00 14 00 00]> [ 01 00 00 00 { .BIT file DATA } ]

<01 48 1414 2B00> <A2 01 [E2 34 00 00] [00 14 00 00] [00 14 00 00]> [ { .BIT file DATA } ]

<01 9C F60C 2B00> <A5 01 [E2 34 00 00] [00 28 00 00] [E2 0C 00 00]> [ { .BIT file DATA } ]

Personal tools