-
Notifications
You must be signed in to change notification settings - Fork 17
XMPP
#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.
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)
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)
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
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
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";
}
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]
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);
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
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
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
.
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
.
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>
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
XMPP/Lobby | Spectating | Data Structure |
---|---|---|
Chat - RTMPS Methods - REST Service | REST Service | Keyframe Specification - Chunk Specification |