From 4fbf04413d68446777832b6c980bfac7879903c1 Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Fri, 20 Jul 2018 00:30:09 +0100 Subject: Make offline UUIDs consistent with vanilla. (#4178) Fixes #4177 This is a breaking change to existing Cuberite permissions settings. --- src/ClientHandle.cpp | 6 ++--- src/Entities/Player.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++---- src/UUID.cpp | 6 ++--- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index ff649ea4d..bbcb64d33 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -273,11 +273,9 @@ cUUID cClientHandle::GenerateOfflineUUID(const AString & a_Username) // Online UUIDs are always version 4 (random) // We use Version 3 (MD5 hash) UUIDs for the offline UUIDs // This guarantees that they will never collide with an online UUID and can be distinguished. + // This is also consistent with the vanilla offline UUID scheme. - // First make the username lowercase: - AString lcUsername = StrToLower(a_Username); - - return cUUID::GenerateVersion3(lcUsername); + return cUUID::GenerateVersion3("OfflinePlayer:" + a_Username); } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index e984534a5..6ddfeb75c 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -36,6 +36,41 @@ // 1000 = once per second #define PLAYER_LIST_TIME_MS std::chrono::milliseconds(1000) +namespace +{ + +/** Returns the old Offline UUID generated before becoming vanilla compliant. */ +cUUID GetOldStyleOfflineUUID(const AString & a_PlayerName) +{ + // Use lowercase username + auto BaseUUID = cUUID::GenerateVersion3(StrToLower(a_PlayerName)).ToRaw(); + // Clobber a full nibble around the variant bits + BaseUUID[8] = (BaseUUID[8] & 0x0f) | 0x80; + + cUUID Ret; + Ret.FromRaw(BaseUUID); + return Ret; +} + + + + + +/** Returns the folder for the player data based on the UUID given. +This can be used both for online and offline UUIDs. */ +AString GetUUIDFolderName(const cUUID & a_Uuid) +{ + AString UUID = a_Uuid.ToShortString(); + + AString res(FILE_IO_PREFIX "players/"); + res.append(UUID, 0, 2); + res.push_back('/'); + return res; +} + +} // namespace (anonymous) + + @@ -2055,8 +2090,25 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World) return true; } - // Load from the offline UUID file, if allowed: + // Check for old offline UUID filename, if it exists migrate to new filename cUUID OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName()); + auto OldFilename = GetUUIDFileName(GetOldStyleOfflineUUID(GetName())); + auto NewFilename = GetUUIDFileName(m_UUID); + // Only move if there isn't already a new file + if (!cFile::IsFile(NewFilename) && cFile::IsFile(OldFilename)) + { + cFile::CreateFolderRecursive(GetUUIDFolderName(m_UUID)); // Ensure folder exists to move to + if ( + cFile::Rename(OldFilename, NewFilename) && + (m_UUID == OfflineUUID) && + LoadFromFile(NewFilename, a_World) + ) + { + return true; + } + } + + // Load from the offline UUID file, if allowed: const char * OfflineUsage = " (unused)"; if (cRoot::Get()->GetServer()->ShouldLoadOfflinePlayerData()) { @@ -2227,8 +2279,7 @@ void cPlayer::OpenHorseInventory() bool cPlayer::SaveToDisk() { - cFile::CreateFolder(FILE_IO_PREFIX + AString("players/")); // Create the "players" folder, if it doesn't exist yet (#1268) - cFile::CreateFolder(FILE_IO_PREFIX + AString("players/") + m_UUID.ToShortString().substr(0, 2)); + cFile::CreateFolderRecursive(GetUUIDFolderName(m_UUID)); // create the JSON data Json::Value JSON_PlayerPosition; @@ -2864,7 +2915,7 @@ AString cPlayer::GetUUIDFileName(const cUUID & a_UUID) { AString UUID = a_UUID.ToLongString(); - AString res("players/"); + AString res(FILE_IO_PREFIX "players/"); res.append(UUID, 0, 2); res.push_back('/'); res.append(UUID, 2, AString::npos); diff --git a/src/UUID.cpp b/src/UUID.cpp index c04e585d7..9ed7dc492 100644 --- a/src/UUID.cpp +++ b/src/UUID.cpp @@ -270,10 +270,8 @@ cUUID cUUID::GenerateVersion3(const AString & a_Name) // Insert version number UUID.m_UUID[6] = (UUID.m_UUID[6] & 0x0f) | 0x30; - /* Insert variant number - Note that by using 1000 instead of 10xx we are losing 2 bits - but this is needed for compatibility with the old string uuid generator */ - UUID.m_UUID[8] = (UUID.m_UUID[8] & 0x0f) | 0x80; + // Insert variant number + UUID.m_UUID[8] = (UUID.m_UUID[8] & 0x3f) | 0x80; return UUID; } -- cgit v1.2.3