MojangAPI: Implemented UUID shortening and dashing.
This commit is contained in:
parent
6476bd0e2e
commit
17a94b16ea
|
@ -233,13 +233,14 @@ AString cClientHandle::GenerateOfflineUUID(const AString & a_Username)
|
||||||
// This guarantees that they will never collide with an online UUID and can be distinguished.
|
// This guarantees that they will never collide with an online UUID and can be distinguished.
|
||||||
// Proper format for a version 3 UUID is:
|
// Proper format for a version 3 UUID is:
|
||||||
// xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B
|
// xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B
|
||||||
|
// Note that we generate a short UUID (without the dashes)
|
||||||
|
|
||||||
// Generate an md5 checksum, and use it as base for the ID:
|
// Generate an md5 checksum, and use it as base for the ID:
|
||||||
unsigned char MD5[16];
|
unsigned char MD5[16];
|
||||||
md5((const unsigned char *)a_Username.c_str(), a_Username.length(), MD5);
|
md5((const unsigned char *)a_Username.c_str(), a_Username.length(), MD5);
|
||||||
MD5[6] &= 0x0f; // Need to trim to 4 bits only...
|
MD5[6] &= 0x0f; // Need to trim to 4 bits only...
|
||||||
MD5[8] &= 0x0f; // ... otherwise %01x overflows into two chars
|
MD5[8] &= 0x0f; // ... otherwise %01x overflows into two chars
|
||||||
return Printf("%02x%02x%02x%02x-%02x%02x-3%01x%02x-8%01x%02x-%02x%02x%02x%02x%02x%02x",
|
return Printf("%02x%02x%02x%02x%02x%02x3%01x%02x8%01x%02x%02x%02x%02x%02x%02x%02x",
|
||||||
MD5[0], MD5[1], MD5[2], MD5[3],
|
MD5[0], MD5[1], MD5[2], MD5[3],
|
||||||
MD5[4], MD5[5], MD5[6], MD5[7],
|
MD5[4], MD5[5], MD5[6], MD5[7],
|
||||||
MD5[8], MD5[9], MD5[10], MD5[11],
|
MD5[8], MD5[9], MD5[10], MD5[11],
|
||||||
|
|
|
@ -66,7 +66,9 @@ public:
|
||||||
|
|
||||||
cPlayer * GetPlayer(void) { return m_Player; } // tolua_export
|
cPlayer * GetPlayer(void) { return m_Player; } // tolua_export
|
||||||
|
|
||||||
|
/** Returns the player's UUID, as used by the protocol, in the short form (no dashes) */
|
||||||
const AString & GetUUID(void) const { return m_UUID; } // tolua_export
|
const AString & GetUUID(void) const { return m_UUID; } // tolua_export
|
||||||
|
|
||||||
void SetUUID(const AString & a_UUID) { m_UUID = a_UUID; }
|
void SetUUID(const AString & a_UUID) { m_UUID = a_UUID; }
|
||||||
|
|
||||||
const Json::Value & GetProperties(void) const { return m_Properties; }
|
const Json::Value & GetProperties(void) const { return m_Properties; }
|
||||||
|
@ -80,7 +82,7 @@ public:
|
||||||
/** Generates an UUID based on the player name provided.
|
/** Generates an UUID based on the player name provided.
|
||||||
This is used for the offline (non-auth) mode, when there's no UUID source.
|
This is used for the offline (non-auth) mode, when there's no UUID source.
|
||||||
Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same.
|
Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same.
|
||||||
Returns a 36-char UUID (with dashes). */
|
Returns a 32-char UUID (no dashes). */
|
||||||
static AString GenerateOfflineUUID(const AString & a_Username); // tolua_export
|
static AString GenerateOfflineUUID(const AString & a_Username); // tolua_export
|
||||||
|
|
||||||
/** Returns true if the UUID is generated by online auth, false if it is an offline-generated UUID.
|
/** Returns true if the UUID is generated by online auth, false if it is an offline-generated UUID.
|
||||||
|
@ -360,7 +362,11 @@ private:
|
||||||
int m_NumBlockChangeInteractionsThisTick;
|
int m_NumBlockChangeInteractionsThisTick;
|
||||||
|
|
||||||
static int s_ClientCount;
|
static int s_ClientCount;
|
||||||
|
|
||||||
|
/** ID used for identification during authenticating. Assigned sequentially for each new instance. */
|
||||||
int m_UniqueID;
|
int m_UniqueID;
|
||||||
|
|
||||||
|
/** Contains the UUID used by Mojang to identify the player's account. Short UUID stored here (without dashes) */
|
||||||
AString m_UUID;
|
AString m_UUID;
|
||||||
|
|
||||||
/** Set to true when the chunk where the player is is sent to the client. Used for spawning the player */
|
/** Set to true when the chunk where the player is is sent to the client. Used for spawning the player */
|
||||||
|
|
|
@ -188,21 +188,12 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
a_UserName = root.get("name", "Unknown").asString();
|
a_UserName = root.get("name", "Unknown").asString();
|
||||||
a_UUID = root.get("id", "").asString();
|
a_UUID = cMojangAPI::MakeUUIDShort(root.get("id", "").asString());
|
||||||
a_Properties = root["properties"];
|
a_Properties = root["properties"];
|
||||||
|
|
||||||
// Store the player's UUID in the NameToUUID map in MojangAPI:
|
// Store the player's UUID in the NameToUUID map in MojangAPI:
|
||||||
cRoot::Get()->GetMojangAPI().AddPlayerNameToUUIDMapping(a_UserName, a_UUID);
|
cRoot::Get()->GetMojangAPI().AddPlayerNameToUUIDMapping(a_UserName, a_UUID);
|
||||||
|
|
||||||
// If the UUID doesn't contain the dashes, insert them at the proper places:
|
|
||||||
if (a_UUID.size() == 32)
|
|
||||||
{
|
|
||||||
a_UUID.insert(8, "-");
|
|
||||||
a_UUID.insert(13, "-");
|
|
||||||
a_UUID.insert(18, "-");
|
|
||||||
a_UUID.insert(23, "-");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
/** The maximum age for items to be kept in the cache. Any item older than this will be removed. */
|
/** The maximum age for items to be kept in the cache. Any item older than this will be removed. */
|
||||||
const Int64 MAX_AGE = 7 * 24 * 60 * 60; // 7 days ago
|
const Int64 MAX_AGE = 7 * 24 * 60 * 60; // 7 days ago
|
||||||
|
|
||||||
|
/** The maximum number of names to send in a single query */
|
||||||
|
const int MAX_PER_QUERY = 100;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +32,7 @@ const Int64 MAX_AGE = 7 * 24 * 60 * 60; // 7 days ago
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** This is the data of the root certs for Starfield Technologies, the CA that signed sessionserver.mojang.com's cert:
|
/** This is the data of the root certs for Starfield Technologies, the CA that signed sessionserver.mojang.com's cert:
|
||||||
Downloaded from http://certs.starfieldtech.com/repository/ */
|
Downloaded from http://certs.starfieldtech.com/repository/ */
|
||||||
static const AString & StarfieldCACert(void)
|
static const AString & StarfieldCACert(void)
|
||||||
|
@ -161,9 +165,10 @@ AStringVector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_Player
|
||||||
void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const AString & a_UUID)
|
void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const AString & a_UUID)
|
||||||
{
|
{
|
||||||
AString lcName(a_PlayerName);
|
AString lcName(a_PlayerName);
|
||||||
|
AString UUID = MakeUUIDShort(a_UUID);
|
||||||
Int64 Now = time(NULL);
|
Int64 Now = time(NULL);
|
||||||
cCSLock Lock(m_CSNameToUUID);
|
cCSLock Lock(m_CSNameToUUID);
|
||||||
m_NameToUUID[StrToLower(lcName)] = sUUIDRecord(a_PlayerName, a_UUID, Now);
|
m_NameToUUID[StrToLower(lcName)] = sUUIDRecord(a_PlayerName, UUID, Now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,8 +239,14 @@ AString cMojangAPI::MakeUUIDShort(const AString & a_UUID)
|
||||||
|
|
||||||
case 36:
|
case 36:
|
||||||
{
|
{
|
||||||
|
// Remove the dashes from the string:
|
||||||
AString res;
|
AString res;
|
||||||
// TODO
|
res.reserve(32);
|
||||||
|
res.append(a_UUID, 0, 8);
|
||||||
|
res.append(a_UUID, 9, 4);
|
||||||
|
res.append(a_UUID, 14, 4);
|
||||||
|
res.append(a_UUID, 19, 4);
|
||||||
|
res.append(a_UUID, 24, 12);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,7 +267,16 @@ AString cMojangAPI::MakeUUIDDashed(const AString & a_UUID)
|
||||||
case 32:
|
case 32:
|
||||||
{
|
{
|
||||||
AString res;
|
AString res;
|
||||||
// TODO
|
res.reserve(36);
|
||||||
|
res.append(a_UUID, 0, 8);
|
||||||
|
res.push_back('-');
|
||||||
|
res.append(a_UUID, 8, 4);
|
||||||
|
res.push_back('-');
|
||||||
|
res.append(a_UUID, 12, 4);
|
||||||
|
res.push_back('-');
|
||||||
|
res.append(a_UUID, 16, 4);
|
||||||
|
res.push_back('-');
|
||||||
|
res.append(a_UUID, 20, 12);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,11 +382,11 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
|
||||||
|
|
||||||
while (!NamesToQuery.empty())
|
while (!NamesToQuery.empty())
|
||||||
{
|
{
|
||||||
// Create the request body - a JSON containing up to 100 playernames:
|
// Create the request body - a JSON containing up to MAX_PER_QUERY playernames:
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
int Count = 0;
|
int Count = 0;
|
||||||
AStringVector::iterator itr = NamesToQuery.begin(), end = NamesToQuery.end();
|
AStringVector::iterator itr = NamesToQuery.begin(), end = NamesToQuery.end();
|
||||||
for (; (itr != end) && (Count < 100); ++itr, ++Count)
|
for (; (itr != end) && (Count < MAX_PER_QUERY); ++itr, ++Count)
|
||||||
{
|
{
|
||||||
Json::Value req(*itr);
|
Json::Value req(*itr);
|
||||||
root.append(req);
|
root.append(req);
|
||||||
|
@ -377,7 +397,7 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
|
||||||
|
|
||||||
// Create the HTTP request:
|
// Create the HTTP request:
|
||||||
AString Request;
|
AString Request;
|
||||||
Request += "POST " + m_NameToUUIDAddress + " HTTP/1.0\r\n";
|
Request += "POST " + m_NameToUUIDAddress + " HTTP/1.0\r\n"; // We need to use HTTP 1.0 because we don't handle Chunked transfer encoding
|
||||||
Request += "Host: " + m_NameToUUIDServer + "\r\n";
|
Request += "Host: " + m_NameToUUIDServer + "\r\n";
|
||||||
Request += "User-Agent: MCServer\r\n";
|
Request += "User-Agent: MCServer\r\n";
|
||||||
Request += "Connection: close\r\n";
|
Request += "Connection: close\r\n";
|
||||||
|
@ -430,7 +450,7 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
|
||||||
{
|
{
|
||||||
Json::Value & Val = root[idx];
|
Json::Value & Val = root[idx];
|
||||||
AString JsonName = Val.get("name", "").asString();
|
AString JsonName = Val.get("name", "").asString();
|
||||||
AString JsonUUID = Val.get("id", "").asString();
|
AString JsonUUID = MakeUUIDShort(Val.get("id", "").asString());
|
||||||
if (JsonUUID.empty())
|
if (JsonUUID.empty())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -680,7 +680,7 @@ void cProtocol172::SendLoginSuccess(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
cPacketizer Pkt(*this, 0x02); // Login success packet
|
cPacketizer Pkt(*this, 0x02); // Login success packet
|
||||||
Pkt.WriteString(m_Client->GetUUID());
|
Pkt.WriteString(cMojangAPI::MakeUUIDDashed(m_Client->GetUUID()));
|
||||||
Pkt.WriteString(m_Client->GetUsername());
|
Pkt.WriteString(m_Client->GetUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,7 +941,7 @@ void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player)
|
||||||
// Called to spawn another player for the client
|
// Called to spawn another player for the client
|
||||||
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
|
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
|
||||||
Pkt.WriteVarInt(a_Player.GetUniqueID());
|
Pkt.WriteVarInt(a_Player.GetUniqueID());
|
||||||
Pkt.WriteString(a_Player.GetClientHandle()->GetUUID());
|
Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID()));
|
||||||
Pkt.WriteString(a_Player.GetName());
|
Pkt.WriteString(a_Player.GetName());
|
||||||
Pkt.WriteFPInt(a_Player.GetPosX());
|
Pkt.WriteFPInt(a_Player.GetPosX());
|
||||||
Pkt.WriteFPInt(a_Player.GetPosY());
|
Pkt.WriteFPInt(a_Player.GetPosY());
|
||||||
|
@ -3014,7 +3014,7 @@ void cProtocol176::SendPlayerSpawn(const cPlayer & a_Player)
|
||||||
// Called to spawn another player for the client
|
// Called to spawn another player for the client
|
||||||
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
|
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
|
||||||
Pkt.WriteVarInt(a_Player.GetUniqueID());
|
Pkt.WriteVarInt(a_Player.GetUniqueID());
|
||||||
Pkt.WriteString(a_Player.GetClientHandle()->GetUUID());
|
Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID()));
|
||||||
Pkt.WriteString(a_Player.GetName());
|
Pkt.WriteString(a_Player.GetName());
|
||||||
|
|
||||||
const Json::Value & Properties = m_Client->GetProperties();
|
const Json::Value & Properties = m_Client->GetProperties();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user