Skip to content
Edward Vo edited this page Apr 8, 2019 · 26 revisions

#XMPP Documentation

This is a specification of the various nuances of the implementation in Riot's official client. For more information about the XMPP protocol as a whole, refer to the XMPP Standards Foundation and RFC6120, RFC6121 and RFC6122.

Logging in

When logging in to Riot's XMPP servers, SSL must be enabled, but the certificate that is sent is invalid. This is normal and should be accepted anyway.

Riot now uses SASL for authentication. To connect you will need the AccessToken from the TokenEndpoint (in OpenIDConfig)

Status

To set a status, when sending a presence you need to modify the show variable to indicate the status of the user.

The various types of statuses that are implemented are:

  • null (or anything not listed here) -> This will show your status with a yellow circle
  • chat -> This will show your status with a green circle
  • away, dnd, xa -> This will have a red status with the word "Away" and a yellow circle
  • chatMobile -> mobile chat application (mobile phone)

Presence

The general format of the presence status to be sent is:

<body>
    <profileIcon>1</profileIcon>
    <level>30</level>
    <wins>1</wins>

If the player is ranked then include this in the status:

    <queueType />
    <rankedLeagueName>Urgot's Patriots</rankedLeagueName>
    <rankedLeagueDivision>I</rankedLeagueDivision>
    <rankedLeagueTier>SILVER</rankedLeagueTier>
    <rankedLeagueQueue>RANKED_SOLO_5x5</rankedLeagueQueue>
    <rankedWins>999</rankedWins>

Then after:

    <gameStatus>outOfGame</gameStatus>
    <statusMsg>My Status</statusMsg>
</body>

You can fudge all the data here without any verification. Note fudging the League Name, Division or Tier to something non-standard will result in some rendering errors. Any non ascii characters or after a length of 28 characters will be stripped from the official client, but the entire presence will be sent.

Game status's include:

  • outOfGame -> When not doing any actions
  • inQueue -> While in queue
  • spectating -> Spectating
  • championSelect -> While in champion select
  • inGame -> While in-game
  • hostingPracticeGame -> While in a custom game

Some extra data will need to be included with different game statuses:

inQueue & championSelect:

    <timeStamp>1386460142847</timeStamp>

spectating:

    <dropInSpectateGameId>featured_game_23446097</dropInSpectateGameId>
    <featuredGameData>
        {
            "gameType" : "MATCHED_GAME",
            "encryptionKey" : "COrsDwe1UL91/PRvChtljDqnLdJtllil",
            "gameId" : 23446097,
            "mapId" : 1,
            "platformId" : "OC1"
        }
    </featuredGameData>

inGame:

    <skinname>Ziggs</skinname>
    <gameQueueType>NONE</gameQueueType>
    <isObservable>ALL</isObservable>
    <timeStamp>1386460142847</timeStamp>
  • Sometimes skinname will be transmitted even if they aren't in a game - this is rubbish data and can be ignored.
  • timestamp is JavaTimeStamp

Groups

On rostering a user to the client, reading the outerXml will give you the group name if they belong to one, otherwise it will return **Default

Chatroom name generation

Chatrooms have prefixes when generating (also known as Type). Some are not in use. They are 2-3 letter prefixes.

  • Arranging_Practice: ap
  • Ranked_Team: tm
  • Champion_Select1: c1
  • Champion_Select2: c2
  • Private: pr
  • Arranging_Game: ag
  • Global: gl
  • Public: pu
  • Cap: cp
  • Queued: aq
  • CTA: cta
  • Post_Game: pg

The most common one is ap.

Some chatrooms (not all!) are generated using SHA-1. The implementation in C# is:

internal static string GetObfuscatedChatroomName(string Subject, string Type)
{
    int bitHack = 0;
    byte[] data = System.Text.Encoding.UTF8.GetBytes(Subject);
    byte[] result;
    SHA1 sha = new SHA1CryptoServiceProvider();
    result = sha.ComputeHash(data);
    string obfuscatedName = "";
    int incrementValue = 0;
    while (incrementValue < result.Length)
    {
        bitHack = result[incrementValue];
        obfuscatedName = obfuscatedName + Convert.ToString(((uint)(bitHack & 240) >> 4), 16);
        obfuscatedName = obfuscatedName + Convert.ToString(bitHack & 15, 16);
        incrementValue = incrementValue + 1;
    }
    obfuscatedName = Regex.Replace(obfuscatedName, @"/\s+/gx", "");
    obfuscatedName = Regex.Replace(obfuscatedName, @"/[^a-zA-Z0-9_~]/gx", "");
    return Type + "~" + obfuscatedName;
}

They are postfixed with a domain at the end. The code in C# to append them:

internal static string GetChatroomJID(string ObfuscatedChatroomName, string password, bool IsTypePublic)
{
    if (!IsTypePublic)
        return ObfuscatedChatroomName + "@sec.pvp.net";

    if (String.IsNullOrEmpty(password))
        return ObfuscatedChatroomName + "@lvl.pvp.net";

    return ObfuscatedChatroomName + "@conference.pvp.net";
}

Team Builder Chatrooms

This section requires use of RTMPS to acquire the groupFinderId.

When creating a team builder lobby, RTMPS returns a com.riotgames.platform.gameinvite.contract.LobbyStatus item that contains a groupFinderId.

To generate a Team Builder Chatroom, use the groupFinderId as the name of the lobby, the type CAP and the extension conference.pvp.net.

An example chatroom JID for the groupFinderId e4bee347-c536-4ca7-a758-f47fef771708 is [email protected]

Game Lobby Chatrooms

This section requires use of RTMPS to acquire the invitationId and chatKey

When creating a game lobby, RTMPS returns a com.riotgames.platform.gameinvite.contract.LobbyStatus item that contains a chatKey and invitationId.

The Game Lobby Chatroom is created by converting the invitationId's INVID to invid and Obfuscating it and adding the prefix ag~ and the sufix @sec.pvp.net. The chatKey, is the room's password

For example, with the chatKey h0HrnkNvAm and invitationId INVID2137627, the room would be [email protected].

Example code in c#:

string ObfuscatedName = GetObfuscatedChatroomName(invitationId.ToLower(), "ag");
string JID = GetChatroomJID(ObfuscatedName, chatKey, false);

Custom Game Chatrooms

This section requires use of RTMPS to acquire the game name and ID

Upon receiving a lobby status or game info for a custom game, you can construct the (unhashed) game name by concatenating the game name and the game id. Note that game names with more than 50 chars are shortened to 50 chars and three periods are appended

fn room_name(game_name, game_id):
   if game_name.len() > 50:
        return game_name[:50] + "..." + game_id
   return game_name + game_id

Chat Subjects

Some special messages are given a ChatSubject so the client knows what to do with the message.

A list of subjects are:

  • PRACTICE_GAME_OWNER_CHANGE
  • GAME_INVITE_REJECT
  • NORMAL_GAME_USER_QUIT
  • VERIFY_INVITEE
  • GAME_INVITE_ACCEPT_ACK
  • PRACTICE_GAME_INVITE_ACCEPT_ACK
  • GAME_INVITE_SUGGEST
  • RANKED_GAME_USER_QUIT
  • SYSTEM_ALERT
  • GAME_INVITE_ALLOW_SUGGESTIONS
  • GAME_INVITE_DISALLOW_SUGGESTIONS
  • VERIFY_INVITEE_ACK
  • GAME_INVITE_REJECT_GAME_FULL
  • GAME_MSG_OUT_OF_SYNC
  • VERIFY_INVITEE_RESET
  • GAME_INVITE_OWNER_CANCEL
  • PRACTICE_GAME_JOIN
  • VERIFY_INVITEE_NAK
  • GAME_INVITE_CANCEL
  • GAME_INVITE_ACCEPT
  • PRACTICE_GAME_INVITE
  • CHAMPION_SELECTION_TRADE
  • PRACTICE_GAME_INVITE_ACCEPT
  • GAME_INVITE
  • AAS_NOTIFICATION
  • GAME_INVITE_LIST_STATUS
  • PRACTICE_GAME_JOIN_ACK
  • RANKED_TEAM_UPDATE
  • INVITE_STATUS_CHANGED

Game Invitations

Note that this information is for pre-4.3. With 4.3, Riot has moved the invitation system from XMPP to RTMPS. However, some parts are still reliant on XMPP and may be needed to be implemented.

All game messages are accompanied with invitation data.

<body>
    <inviteId>0</inviteId>
    <userName>Snowl</userName>
    <profileIconId>1</profileIconId>
    <gameType>NORMAL_GAME</gameType>
    <groupId></groupId>
    <seasonRewards>-1</seasonRewards>
    <mapId>14</mapId>
    <queueId>1</queueId>
    <gameMode>Normal<gameMode>
    <gameDifficulty></gameDifficulty>
</body>

The inviteId is a random int from 0 ... 2^32 - 1.

To send (and accept a invite) to a game the message structure goes something like this:

  • H -> I GAME_INVITE
  • I -> H GAME_INVITE_ACCEPT
  • H -> I GAME_INVITE_ACCEPT_ACK

To start a game it goes:

  • H -> I VERIFY_INVITEE
  • I -> H VERIFY_INVITEE_ACK

If the game is not verified, official clients will hang on a Waiting from information from server and will not proceed.

Notes:

  • "H" stands for "host"
  • "I" stands for "invitee"
  • The chatroom for a invite is ag, with no password, but the postfix @conference.pvp.net.

Any Queue Information

Note that this information is for pre-4.3. With 4.3, Riot has moved the invitation system from XMPP to RTMPS

To change queues/maps on the fly, first send a GAME_INVITE_ACCEPT_ACK (with all the new queue changes) to all clients with a queueId of 0 (since this is unused) and then send a GAME_INVITE_ACCEPT_ACK with the proper queueId.

Invitation Status

Note that this information is for pre-4.3. With 4.3, Riot has moved the invitation system from XMPP to RTMPS

The format for a GAME_INVITE_LIST_STATUS is:

<body>
    <invitelist>
        <invitee status=\"ACCEPTED\" name=\"Snowl\" />
        <invitee status=\"DECLINED\" name=\"Amec\" />
    </invitelist>
</body>

Server names

The server for each chat realm is in the following format. You must resolve the host and connect through IP, not hostname:

chat.<server>.lol.riotgames.com:5223

  • BR: br
  • EUN: eun1
  • EUW: euw1
  • NA: na2
  • KR: kr
  • OCE: oc1
  • RU: ru
  • TR: tr
  • LAN: la1
  • LAS: la2