Changes

Jump to navigation Jump to search
7,194 bytes added ,  13:24, 10 June 2019
→‎How to help: Added note regarding Maniaplanet
Line 1: Line 1: −
== Goal and how to help ==
+
The TrackMania Forever game client uses a {{wp|XML-RPC}} based '''web API''' to communicate with the master server. This article attempts to document the API with the potential goal of eventually having a fully functional custom master server.
 
  −
One day, eventually, Trackmania will reach his EoL. This is about documenting as much as possible to eventually get the point of having a fully functional custom authentication server. If you want to give help, go ahead. Just grab fiddler and start tweaking around with the game. You can check what has already been done on the [[Web_APIs/Progress|Progress]] page.
      
== Basic concepts ==
 
== Basic concepts ==
   −
TrackMania uses a XML-RPC-like API to authenticate players, load server lists, load rankings, etc... Here is some documentation about what has been reversed engineered. A lot is still left to be documented.
+
TrackMania uses a XML-RPC based protocol to authenticate players, load server lists, load rankings, etc. Below is some documentation about what has been reversed engineered. A lot is still left to be documented, as logged on the [[Web_API/Progress|Progress]] page.
   −
The game sends unencrypted POST requests to
+
The client sends HTTP(S) POST requests to
 
* [http://game.trackmaniaforever.com/online_game/request.php http://game.trackmaniaforever.com/online_game/request.php]
 
* [http://game.trackmaniaforever.com/online_game/request.php http://game.trackmaniaforever.com/online_game/request.php]
 
* [http://game2.trackmaniaforever.com/online_game/request.php http://game2.trackmaniaforever.com/online_game/request.php]
 
* [http://game2.trackmaniaforever.com/online_game/request.php http://game2.trackmaniaforever.com/online_game/request.php]
 
* [http://nations.trackmaniaforever.com/online_game/request.php http://nations.trackmaniaforever.com/online_game/request.php]
 
* [http://nations.trackmaniaforever.com/online_game/request.php http://nations.trackmaniaforever.com/online_game/request.php]
to communicate with the API.
+
to communicate with the master server, using the headers:
 
+
User-Agent: GameBox
It sets two headers: <code>User-Agent: GameBox</code> and <code>Accept: */*</code>, and uses the following format as request body :
+
Accept: */*
 +
Content-Type: application/binary
 +
Connection: Keep-Alive
 +
Pragma: no-cache
    +
=== Request body ===
 
<pre>
 
<pre>
 
<?xml version="1.0" encoding="UTF-8"?>
 
<?xml version="1.0" encoding="UTF-8"?>
Line 23: Line 25:  
     <distro>MOLUX</distro>
 
     <distro>MOLUX</distro>
 
     <lang>fr</lang>
 
     <lang>fr</lang>
 +
    <sd>2011-02-21</sd> <!-- Only sent by dedicated server, see below -->
 
   </game>
 
   </game>
 
   <author>
 
   <author>
     <login/>
+
     [...]
    <session/>
   
   </author>
 
   </author>
 
   <request>
 
   <request>
Line 40: Line 42:  
</pre>
 
</pre>
   −
Here is a description of the parameters :
+
Here is a description of the xml:
    
* '''root'''
 
* '''root'''
 
** '''game'''
 
** '''game'''
*** '''name''' the client you are using. Known values: TmForever
+
*** '''name''' The client you are using. Known values: TmForever
*** '''version''' Version of the client
+
*** '''version''' Version of the client.
*** '''distro''' Unknown. Set to MOLUX for TMNF or TAHOR for TMUF
+
*** '''distro''' Software distribution. E.g. MOLUX for TMNF or ORTIC for TMUF.
*** '''lang''' lang of the client, as ISO 639-1
+
*** '''lang''' Language of the client, as ISO 639-1. Dedicated server sets it to "xx".
** '''author'''
+
*** '''sd''' Dedicated Server release date as YYYY-MM-DD, only sent by server.
*** '''login''' is not set when calling GetConnectionAndGameParams
+
** '''author''' ''See [[#Author]]''.
*** '''session''' is not set when calling GetConnectionAndGameParams
   
** '''request'''
 
** '''request'''
*** '''name''' Name of the requested function.
+
*** '''name''' Name of the remote procedure.
 
*** '''param''' Parameters for the call.
 
*** '''param''' Parameters for the call.
** '''auth''' ''Optional. Only seen on Connect and Disconnect''
+
** '''auth''' ''Optional. Only seen on Connect and Disconnect''.
 
*** '''value''' Looks like an auth ticket.
 
*** '''value''' Looks like an auth ticket.
   −
The server responds with XML, which has obfurscated names:
+
==== Author ====
 +
The author tag identifies the user for whom the request is sent. In this documentation, three cases are possible for the author tag:
 +
 
 +
<ul>
 +
<li>The method doesn't require authentication (denoted as "No (Empty)"), the author tag is filled with following content:
 +
<pre>
 +
<login/>
 +
<session/>
 +
</pre>
 +
</li>
 +
<li>The method requires user name (denoted as "No (Set to 1)"), the author tag is filled with following content:
 +
<pre>
 +
<login>the user's login</login>
 +
<session>1</session>
 +
</pre>
 +
</li>
 +
<li>The method requires authentication (denoted as "Yes"), the author tag is filled with following content:
 +
<pre>
 +
<login>the user's login</login>
 +
<session>the session's id</session>
 +
</pre>
 +
</li>
 +
</ul>
    +
=== Response body ===
 
<pre>
 
<pre>
 
<?xml version="1.0" encoding="UTF-8"?>
 
<?xml version="1.0" encoding="UTF-8"?>
Line 72: Line 96:  
</pre>
 
</pre>
   −
Here is a description of the return:
+
Here is a description of the returned xml:
   −
* '''r'''
+
* '''r''' The [r]oot element
** '''r'''
+
** '''r''' The [r]esponse element
*** '''n''' The name of the called function
+
*** '''n''' The [n]ame of the called procedure.
*** '''c''' The return data
+
*** '''c''' The returned [c]ontent.
** '''e''' A string giving the execution time.
+
** '''e''' A string giving the [e]xecution time.
    
== Functions calls ==
 
== Functions calls ==
    
=== GetConnectionAndGameParams ===
 
=== GetConnectionAndGameParams ===
''First request sent by client.''
+
''Gets a lot of information. First request sent by client.''
 
{|class="wikitable"
 
{|class="wikitable"
 
  ! Session required?
 
  ! Session required?
Line 89: Line 113:  
  ! Response
 
  ! Response
 
  |-
 
  |-
  | No
+
  | No (Empty)
 
  |
 
  |
 
* '''dedicated''' Set to 0 with TMF. Purpose is unknown. Maybe for servers.
 
* '''dedicated''' Set to 0 with TMF. Purpose is unknown. Maybe for servers.
* '''download''' Max P2P download speed, as set in game config, in B/s
+
* '''download''' Max P2P download speed, as set in game config, in B/s.
* '''upload''' Max P2P upload speed, as set in game config, in B/s
+
* '''upload''' Max P2P upload speed, as set in game config, in B/s.
 
  |
 
  |
* '''a''' See [[#RedirectOnMasterServer]]
+
* '''a''' Same as '''a''' from [[#RedirectOnMasterServer]].
 +
|}
 +
 
 +
=== AddBuddy ===
 +
''Adds a player to the friends list.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''l''' Friend's login. Present if the "Add buddy" button is used.
 +
* '''e''' Friend's email. Present if the "share" button is used.
 +
|
 +
* '''c''' Is present but empty when ok.
 +
* '''v''' Error code, see below.
 +
|}
 +
 
 +
List of seen error codes:
 +
 
 +
{|class="wikitable"
 +
! ID
 +
! Meaning
 +
|-
 +
| 14
 +
| Unknown username
 +
|-
 +
| 143
 +
| You must wait before adding back a deleted friend
 
  |}
 
  |}
    
=== CheckLogin ===
 
=== CheckLogin ===
''Used to check if login is already used for account creation.''
+
''Checks if login is already used for account creation.''
 
{|class="wikitable"
 
{|class="wikitable"
 
  ! Session required?
 
  ! Session required?
Line 105: Line 158:  
  ! Response
 
  ! Response
 
  |-
 
  |-
  | No
+
  | No (Set to 1)
 
  |
 
  |
 
* '''l''' Player login.
 
* '''l''' Player login.
Line 114: Line 167:     
=== MailAccount ===
 
=== MailAccount ===
''Used to make the server send a password recovery email.''
+
''Requests the server to send a password recovery email.''
 
{|class="wikitable"
 
{|class="wikitable"
 
  ! Session required?
 
  ! Session required?
Line 120: Line 173:  
  ! Response
 
  ! Response
 
  |-
 
  |-
  | No
+
  | No (Empty)
 
  |
 
  |
* '''login''' Player login
+
* '''login''' Player login.
 
  |
 
  |
 
''Empty response''
 
''Empty response''
Line 128: Line 181:     
=== Disconnect ===
 
=== Disconnect ===
''Used to disconnect (Duh).''
+
''Closes connection.''
 
{|class="wikitable"
 
{|class="wikitable"
 
  ! Session required?
 
  ! Session required?
Line 139: Line 192:  
  |
 
  |
 
''Empty response''
 
''Empty response''
 +
|}
 +
 +
=== GetBuddies ===
 +
''Gets the friends list.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''u''' Current UTC timestamp, as YYYY:MM:DD:hh:mm:ss.
 +
|
 +
''Left to document''
 +
* '''c''' Current UTC timestamp, as YYYYMMDDhhmmss.
 +
* '''b''' ''Represents one friend, can have multiple of them:''
 +
** '''a''' Friend's login.
 +
** '''x''' Set to 1 when friend online, 0 when offline.
 +
** '''y''' Set to 1 wile waiting for confirmation, 0 when accepted.
 +
|}
 +
 +
=== GetManialinkInfos ===
 +
''Gets info about a manialink.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''manialink''' Name of the manialink
 +
|
 +
* '''c''' Price of the manialink.
 +
* '''l''' Player's coppers amount.
 +
* '''a''' ? Set to 1 or 0.
 +
* '''m''' Name of the manialink.
 +
* '''u''' URL of the page corresponding to the manialink.
 +
* '''t''' ? Maybe a {{wp|Time to live|TTL}}.
 +
* '''rl''' ''Represents distribution of amount in c. Only set when c is != 0:''
 +
** '''r''' ''Represents one player. At least two in rl:''
 +
*** '''l''' Player login (nadeo for the 5% tax).
 +
*** '''c''' Amount of coppers going to the player.
 +
|}
 +
 +
=== GetManialinkResource ===
 +
''Gets info about a maniacode.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''manialink''' Name of the maniacode.
 +
|
 +
* '''m''' Name of the maniacode.
 +
* '''u''' URL of the page corresponding to the maniacode.
 +
|}
 +
 +
=== GetOnlineProfile ===
 +
''Gets info about the player.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''dt''' ?
 +
* '''cor''' ?
 +
|
 +
''A lot is left to document here''
 +
* '''a''' ''General info about the player:''
 +
** '''a''' Player's login.
 +
** '''b''' Player's display name.
 +
** '''c''' Player's region.
 +
** '''d''' ? Set to 0.
 +
** '''e''' ? Set to 0.
 +
** '''j''' ?
 +
** '''k''' ?
 +
* '''b''' ?
 +
* '''h''' ''Describes the splash screen to display after login:''
 +
** '''a''' Unix timestamp, current date (unknown purpose).
 +
** '''c''' Full HTTP URL of the manialink to display.
 +
|}
 +
 +
=== GetLeagues ===
 +
''Gets the regions list.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| No (Set to 1)
 +
|
 +
''Empty parameters''
 +
|
 +
* '''l''' ''Multiple of them, one per region:''
 +
** '''a''' Region name.
 +
** '''b''' Parent regions (separated with "|", eg. "France|Alsace").
 +
** '''i''' An URL pointing to the region's flag (dds).
 +
|}
 +
 +
=== OpenSession ===
 +
''Gets a session ID.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| No (Set to 1)
 +
|
 +
* '''cr''' 8 characters random hex value.
 +
|
 +
* '''i''' Session ID.
 +
* '''s''' ?. Seems Hexadecimal.
 +
* '''k''' Base64 encoded, see below.
 +
|}
 +
 +
'''k''' is hard-coded in the game's binary. One value has been seen, both for United and Nations:
 +
MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCpBgX3c4ezM18RiGPlQiVKINu+JicxOd6yuHl5q30
 +
00CdTLu53A3ceuelum2+ui+MmASL3JjmVVOoNURvK7GCt79wLUUSbtTaZPXPr73TioZBCVkPd8chAb8
 +
EurZtlDp5QQvDCaoCfFJ4V8VJgM0IK0qVIHRP+D03tKgb2WOgK9QIBEQ==
 +
 +
=== RemoveBuddy ===
 +
''Removes a player from the friends list.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''b''' Friend's login.
 +
|
 +
''Empty response''
 +
|}
 +
 +
=== ReceiveMessages ===
 +
''Checks for messages.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''f''' Current UTC timestamp, as YYYY:MM:DD:hh:mm:ss.
 +
|
 +
* '''r''' ''Represents a message, can have multiple of them:''
 +
** '''s''' Sender's login.
 +
** '''d''' UTC timestamp of sending, as YYYYMMDDhhmmss.
 +
** '''u''' Subject.
 +
** '''t''' Content.
 +
** '''o''' Amount of coppers in the message.
 +
* '''l''' New coppers amount.
 +
* '''n''' Current UTC timestamp, as YYYYMMDDhhmmss.
 +
|}
 +
 +
=== RequestAllowed ===
 +
''Checks if a request is allowed.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''r''' Request type.
 +
* '''m''' Unknown. Set to 1.
 +
|
 +
* '''r''' Request type (same as r in parameters).
 +
* '''c''' Cost in coppers.
 +
* '''l''' Current coppers amount.
 +
* '''a''' 1 if allowed, 0 if not.
 +
|}
 +
 +
=== SendMessages ===
 +
''Sends a message to a player.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| Yes
 +
|
 +
* '''r1''' Destination's login.
 +
* '''s1''' Subject of the message.
 +
* '''m1''' Content of the message.
 +
* '''d1''' Amount of coppers attached to the message.
 +
|
 +
* '''c''' ?
 +
|}
 +
 +
=== Subscribe ===
 +
''Registers a new account. Warning: This is sent over HTTPS.''
 +
{|class="wikitable"
 +
! Session required?
 +
! Parameters
 +
! Response
 +
|-
 +
| No (Set to 1)
 +
|
 +
* '''pw''' Password for the account.
 +
* '''ik''' ?. Seems caps hexadecimal.
 +
* '''email''' Supplied email.
 +
* '''cp''' ?. Empty.
 +
* '''np''' Region.
 +
* '''an''' If the user accepts to receive Nadeo news on his email address.
 +
|
 +
* '''s''' Game key associated with the account.
 
  |}
 
  |}
    
== RedirectOnMasterServer ==
 
== RedirectOnMasterServer ==
   −
This response happens sometimes. It tells the client to switch auth server. When recieved, the client sends same request it just send, but to the other server specified.
+
This response happens sometimes. It tells the client to switch auth server. When received, the client sends same request it just sent, but to the other server specified.
    
Here is a description of the response:
 
Here is a description of the response:
    
* '''a'''
 
* '''a'''
** '''b''' Name of the game
+
** '''b''' Name of the game.
** '''c''' New server address to use
+
** '''c''' New server address to use.
** '''d''' Endpoint (generally online_game)
+
** '''d''' Endpoint (generally online_game).
** '''e''' HTTPS port
+
** '''e''' HTTPS port.
** '''f''' HTTP port
+
** '''f''' HTTP port.
** '''g''' Base region (World)
+
** '''g''' Base region (World).
 
** '''h''' ?. Set to 1
 
** '''h''' ?. Set to 1
 
** '''i''' ?. Set to 1
 
** '''i''' ?. Set to 1
** '''j''' List of authorized actions (described below)
+
** '''j''' (Maybe) List of authorized/available remote methods (described below), or permissions.
 +
*** '''k''' One remote call ''(multiple of them in the j tag)''
 +
**** '''l''' Method/Permission name.
 +
**** '''q''' Might be if authorized/available or not (seems always 1).
 +
 
 +
Here is a list of the methods that have been seen in '''k''':
 +
 
 +
* AddCustomChallenge
 +
* AddResults
 +
* CheckServerPassword
 +
* Connect
 +
* ConvertAccount
 +
* CreateGroup
 +
* Disconnect
 +
* GetChallenge
 +
* GetChallengeFromUId
 +
* GetManialinkResource
 +
* GetReplay
 +
* MoveFromLeague
 +
* PayCoppersTransaction
 +
* SLiveUpdate
 +
* SendMessages
 +
* ShareChallenge
 +
* StartOfficialRecord
 +
* StopOfficialRecord
 +
* Subscribe
 +
* SubscribeToGroup
 +
* UnsubscribeFromGroup
 +
* UpdateOnlineProfile
 +
* UploadOfficialRecord
 +
* ValidateSoloAccount
 +
 
 +
== How to help ==
 +
Use a {{wp|packet analyzer}} to see the game's communication while experimenting with client features, and describe requests and responses in as much detail as possible.
 +
 
 +
Note: For Maniaplanet it's required that the address of the debugging proxy is entered in the launcher (e.g. 127.0.0.1:8888 for Fiddler) and the proxy is configured to decrypt HTTPS traffic.
    
[[Category:Specifications]]
 
[[Category:Specifications]]

Navigation menu