Multiplayer protocol - Research

Research related to Arcanum and it's game engine.
Post Reply
User avatar
Crypton
Arronax's Best Friend
Arronax's Best Friend
Posts: 420
Joined: Wed Jul 08, 2009 5:04 am
Location: Abyss
Contact:

Multiplayer protocol - Research

Post by Crypton » Fri Jan 08, 2010 6:04 pm

Greetings,

I've been researching arcanum's multiplayer protocol some time ago, and the result was one reversed packet, which was broadcasted by Arcanum server via UDP, for more info check out:
viewtopic.php?f=6&t=14

This time, I've aimed my research to actual multiplayer protocol, because after understanding to this protocol, I'll be able to create my own server application, which I called before a GrandMaster.

To remind you, with GrandMaster you will be able:
-Create dedicated server.
-Increase maximum number of player (need also to patch executable).
-Play smoothly without lagging.
-Add anticheat, new game modes, bots, and other fancy stuff...

If you want to help me with research, please leave here a message.
PS: You can use tools for capturing packets, like Ethereal or Wireshark, so you don't need to reverse executable file...

--------------
A short intro :

First of all, you should be aware what is Arcanum server, and how its created, because you won't be able to understand to text below.

Arcanum server provides multiplayer game, and its created when you create a new multiplayer game, this can be done after you launch game, and clicking on buttons Multiplayer->Network->Host Game->Start.

After multiplayer game is started (LAN or Online), server is listening for incoming connections, via TCP on port 31435, plus its broadcasting UPD packet with server info (link above).

When client (player) wants to connect to server, it first sends a join request packet to server, and then server sends join reply packet to client, as reply for request.

This is a only a small part of way how server and client communicates, but its enough for begging...

--------------
All about Arcanum's packets:

There is some required macros, that will be used:

Code: Select all

#define TIG_NET_ERROR -1
#define TIG_NET_PROTOCOL_VERSION 25
#define TIG_NET_BUF_SIZE 8192
#define TIG_PLAYER_MAX_NAME_LENGTH 24
#define TIG_PLAYER_MAX_PLAYER_COUNT 8
As you know from intro above, server and clients sends to each other some packets, which are nothing more than blocks of data.

Every Arcanum's packet has a custom packet header, placed after TCP header, and structure of this header is:

Code: Select all

struct APacketHeader // 4 Bytes!
{
	AInt8u version; // Protocol version, always 25
	AInt8u type; // Header type, valid is only 0,1,2,3,4,5,7,8,10,11
	AInt16u size; // Size of packet, header + data, max is TIG_NET_BUF_SIZE
};
After packet header are actual data that server wanted to send to client (and back), so this is the actual part that we are interested in, to find out what data sends client to server (and back), so I'll try to research all packets.

Because Arcanum's internal receive buffer has fixed size, which size is TIG_NET_BUF_SIZE, we can declare a Arcanum's packet as type with fixed size.

Code: Select all


typedef AChar APacketData[TIG_NET_BUF_SIZE - sizeof(APacketHeader)];

struct APacket // 8192 bytes
{
	// header
	AInt8u version; // Protocol version, always 25
	AInt8u type; // Header type, valid is only 0,1,2,3,4,5,7,8,10,11
	AInt16u size; // Size of packet, header + data, max is TIG_NET_BUF_SIZE
	// data
	APacketData data;
}

Now when we know a generic packet structure, we may go to look at data that we receive.
At beginning, I said that client sends a join request when he wants to connect to server, so lets start with this packet:

Code: Select all

4 Bytes - Packet Header (type = 2)
4 Bytes - Action (0 = join request)
24 Bytes - Player name, type APlayerName
60 Bytes - Unknown...
4 Bytes - Size of player's mobile object
Variable - Mobile object
A player name is zero terminated string with fixed size, 24 bytes, so maximum length of player name is 23 letters, this could be also declared as fixed type:

Code: Select all

typedef AChar APlayerName[TIG_PLAYER_MAX_NAME_LENGTH];

After server receive join request packet, it replies to client with join reply packet which structure is:

Code: Select all

4 Bytes - Packet Header (type = 2)
4 Bytes - Action (3 = join reply)
4 Bytes - Unknown, probably slot index
24 Bytes - Player name, type APlayerName
4 Bytes - Unknown, probably true or false
Thats all for now... I will continue later.

Post Reply