diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/RankManager.cpp | 381 | ||||
-rw-r--r-- | src/RankManager.h | 4 |
2 files changed, 4 insertions, 381 deletions
diff --git a/src/RankManager.cpp b/src/RankManager.cpp index 87e538d28..f4f594c17 100644 --- a/src/RankManager.cpp +++ b/src/RankManager.cpp @@ -5,7 +5,6 @@ #include "Globals.h" #include "RankManager.h" -#include "IniFile.h" #include "Protocol/MojangAPI.h" #include "ClientHandle.h" @@ -14,371 +13,6 @@ //////////////////////////////////////////////////////////////////////////////// -// cRankManagerIniMigrator: - -/** Migrates from groups.ini and users.ini into the rankmanager DB */ -class cRankManagerIniMigrator -{ -public: - cRankManagerIniMigrator(cRankManager & a_RankManager, cMojangAPI & a_MojangAPI) : - m_RankManager(a_RankManager), - m_MojangAPI(a_MojangAPI) - { - } - - - - /** Performs the complete migration from INI files to DB. */ - bool Migrate(void) - { - cRankManager::cMassChangeLock Lock(m_RankManager); - - LOGD("Reading groups..."); - if (!ReadGroups()) - { - return false; - } - LOGD("Cleaning groups inheritance..."); - CleanGroupInheritance(); - LOGD("Creating groups..."); - CreateGroups(); - - LOGD("Reading users..."); - if (!ReadUsers()) - { - return false; - } - LOGD("Cleaning user groups..."); - CleanUserGroups(); - LOGD("Resolving user UUIDs..."); - ResolveUserUUIDs(); - - LOGD("Setting ranks..."); - SetRanks(); - - LOGD("Creating defaults..."); - CreateDefaults(); - - return true; - } - -protected: - - /** Container for a group read from an INI file. */ - struct sGroup - { - AString m_Name; - AString m_Color; - AStringVector m_Inherits; - AStringVector m_Permissions; - - sGroup(void) {} - - sGroup(const AString & a_Name, const AString & a_Color, const AStringVector & a_Inherits, const AStringVector & a_Permissions): - m_Name(a_Name), - m_Color(a_Color), - m_Inherits(a_Inherits), - m_Permissions(a_Permissions) - { - } - }; - typedef std::map<AString, sGroup> sGroupMap; - - - /** Container for a single user read from an INI file. */ - struct sUser - { - AString m_Name; - AStringVector m_Groups; - - /** Assigned by ResolveUserUUIDs(), contains the online (Mojang) UUID of the player. */ - cUUID m_UUID; - - /** Assigned by ResolveUserUUIDs(), contains the offline (generated) UUID of the player. */ - cUUID m_OfflineUUID; - - - sUser(void) {} - - sUser(const AString & a_Name, const AStringVector & a_Groups): - m_Name(a_Name), - m_Groups(a_Groups) - { - } - }; - typedef std::map<AString, sUser> sUserMap; - - typedef std::map<AString, AString> cStringMap; - - - /** The parent Rank manager where we will create the groups, ranks and players */ - cRankManager & m_RankManager; - - /** The player name to UUID resolver */ - cMojangAPI & m_MojangAPI; - - /** List of all groups read from the ini file */ - sGroupMap m_Groups; - - /** List of all players read from the ini file. */ - sUserMap m_Users; - - /** Maps lists of groups to rank names. - Each group list is either a simple "<Group>" if there's only one group, - or "<PrimaryGroup>, <FirstSecondaryGroup>, <SecondSecondaryGroup>...", where the secondary groups are - lowercased and alpha-sorted. This makes the group lists comparable for equivalence, simply by comparing - their string names. - The ranks are named "<Group>" for single-group players, and "AutoMigratedRank_N" for the composite ranks, - where N is a unique number. */ - cStringMap m_GroupsToRanks; - - - - /** Reads the groups from the "groups.ini" file into m_Groups */ - bool ReadGroups(void) - { - // Read the file: - cIniFile Groups; - if (!Groups.ReadFile("groups.ini")) - { - return false; - } - - // Read all the groups into a map: - int NumGroups = Groups.GetNumKeys(); - for (int i = 0; i < NumGroups; i++) - { - AString GroupName = Groups.GetKeyName(i); - AString lcGroupName = StrToLower(GroupName); - if (m_Groups.find(lcGroupName) != m_Groups.end()) - { - LOGINFO("groups.ini contains a duplicate definition of group %s, ignoring the latter.", GroupName.c_str()); - continue; - } - m_Groups[lcGroupName] = sGroup( - GroupName, - Groups.GetValue(GroupName, "Color", ""), - StringSplitAndTrim(Groups.GetValue(GroupName, "Inherits"), ","), - StringSplitAndTrim(Groups.GetValue(GroupName, "Permissions"), ",") - ); - } // for i - Groups' keys - return true; - } - - - - /** Removes non-existent groups from all the groups' inheritance */ - void CleanGroupInheritance(void) - { - for (sGroupMap::iterator itrG = m_Groups.begin(), endG = m_Groups.end(); itrG != endG; ++itrG) - { - AStringVector & Inherits = itrG->second.m_Inherits; - for (AStringVector::iterator itrI = Inherits.begin(); itrI != Inherits.end();) - { - AString lcInherits = StrToLower(*itrI); - if (m_Groups.find(lcInherits) != m_Groups.end()) - { - // Inherited group exists, continue checking the next one - ++itrI; - continue; - } - // Inherited group doesn't exist, remove it from the list: - LOGWARNING("RankMigrator: Group \"%s\" inherits from a non-existent group \"%s\", this inheritance will be ignored.", - itrG->second.m_Name.c_str(), itrI->c_str() - ); - AStringVector::iterator itrI2 = itrI; - ++itrI2; - Inherits.erase(itrI); - itrI = itrI2; - } // for itrI - Inherits[] - } // for itrG - m_Groups[] - } - - - - /** Reads the users from the "users.ini" file into m_Users */ - bool ReadUsers(void) - { - // Read the file: - cIniFile Users; - if (!Users.ReadFile("users.ini")) - { - return false; - } - - // Read all the users into a map: - int NumUsers = Users.GetNumKeys(); - for (int i = 0; i < NumUsers; i++) - { - AString UserName = Users.GetKeyName(i); - AString lcUserName = StrToLower(UserName); - if (m_Users.find(lcUserName) != m_Users.end()) - { - LOGINFO("users.ini contains a duplicate definition of user %s, ignoring the latter.", UserName.c_str()); - continue; - } - m_Users[lcUserName] = sUser( - UserName, - StringSplitAndTrim(Users.GetValue(UserName, "Groups", ""), ",") - ); - } // for i - Users' keys - return true; - } - - - - /** Removes non-existent groups from each user's definition. */ - void CleanUserGroups(void) - { - for (sUserMap::iterator itrU = m_Users.begin(), endU = m_Users.end(); itrU != endU; ++itrU) - { - AStringVector & Groups = itrU->second.m_Groups; - for (AStringVector::iterator itrG = Groups.begin(); itrG != Groups.end();) - { - AString lcGroup = StrToLower(*itrG); - if (m_Groups.find(lcGroup) != m_Groups.end()) - { - // Assigned group exists, continue checking the next one - ++itrG; - continue; - } - // Assigned group doesn't exist, remove it from the list: - LOGWARNING("RankMigrator: User \"%s\" is assigned a non-existent group \"%s\", this assignment will be ignored.", - itrU->second.m_Name.c_str(), itrG->c_str() - ); - AStringVector::iterator itrG2 = itrG; - ++itrG2; - Groups.erase(itrG); - itrG = itrG2; - } // for itrG - Groups[] - } // for itrU - m_Users[] - } - - - - /** Creates groups based on m_Groups. - Ignores group inheritance. */ - void CreateGroups(void) - { - // Create each group, with its permissions: - for (sGroupMap::const_iterator itr = m_Groups.begin(), end = m_Groups.end(); itr != end; ++itr) - { - m_RankManager.AddGroup(itr->second.m_Name); - m_RankManager.AddPermissionsToGroup(itr->second.m_Permissions, itr->second.m_Name); - } // for itr - m_Groups[] - } - - - /** Resolves the UUID of each user in m_Users. - If a user doesn't resolve, they are removed and logged in the console. */ - void ResolveUserUUIDs(void) - { - // Resolve all PlayerNames at once (the API doesn't like single-name queries): - AStringVector PlayerNames; - for (sUserMap::const_iterator itr = m_Users.begin(), end = m_Users.end(); itr != end; ++itr) - { - PlayerNames.push_back(itr->second.m_Name); - } - m_MojangAPI.GetUUIDsFromPlayerNames(PlayerNames); - - // Assign the UUIDs back to players, remove those not resolved: - for (auto & User : m_Users) - { - cUUID UUID = m_MojangAPI.GetUUIDFromPlayerName(User.second.m_Name); - if (UUID.IsNil()) - { - LOGWARNING("RankMigrator: Cannot resolve player %s to online UUID, player will be left unranked in online mode", User.second.m_Name.c_str()); - } - User.second.m_UUID = UUID; - User.second.m_OfflineUUID = cClientHandle::GenerateOfflineUUID(User.second.m_Name); - } - } - - - - /** Adds the specified groups to the specified ranks. Recurses on the groups' inheritance. */ - void AddGroupsToRank(const AStringVector & a_Groups, const AString & a_RankName) - { - for (AStringVector::const_iterator itr = a_Groups.begin(), end = a_Groups.end(); itr != end; ++itr) - { - // Normalize the group name: - sGroup & Group = m_Groups[StrToLower(*itr)]; - - // Avoid loops, check if the group is already added: - if (m_RankManager.IsGroupInRank(Group.m_Name, a_RankName)) - { - continue; - } - - // Add the group, and all the groups it inherits from recursively: - m_RankManager.AddGroupToRank(Group.m_Name, a_RankName); - AddGroupsToRank(Group.m_Inherits, a_RankName); - } // for itr - a_Groups[] - } - - - - /** Creates a rank for each player, based on the master groups they are assigned. */ - void SetRanks(void) - { - for (sUserMap::const_iterator itr = m_Users.begin(), end = m_Users.end(); itr != end; ++itr) - { - // Ignore users with no groups: - const AStringVector & Groups = itr->second.m_Groups; - if (Groups.empty()) - { - LOGWARNING("RankMigrator: Player %s has no groups assigned to them, skipping the player.", itr->second.m_Name.c_str()); - continue; - } - - // Compose the rank name out of group names: - AString RankName; - for (AStringVector::const_iterator itrG = Groups.begin(), endG = Groups.end(); itrG != endG; ++itrG) - { - AString GroupName = m_Groups[StrToLower(*itrG)].m_Name; // Normalize group name - if (!RankName.empty()) - { - RankName.push_back(','); - } - RankName.append(GroupName); - } // for itrG - Groups[] - - // Create the rank, with al its groups: - if (!m_RankManager.RankExists(RankName)) - { - m_RankManager.AddRank(RankName, "", "", m_Groups[StrToLower(Groups[0])].m_Color); - AddGroupsToRank(Groups, RankName); - } - - // Set the rank to the user, using both the online and offline UUIDs: - m_RankManager.SetPlayerRank(itr->second.m_UUID, itr->second.m_Name, RankName); - m_RankManager.SetPlayerRank(itr->second.m_OfflineUUID, itr->second.m_Name, RankName); - } // for itr - m_Users[] - } - - - - /** Creates the Default rank that contains the Default group, if it exists. - Sets the RankManager's default rank. */ - void CreateDefaults(void) - { - if (!m_RankManager.RankExists("Default")) - { - m_RankManager.AddRank("Default", "", "", ""); - if (!m_RankManager.IsGroupInRank("Default", "Default")) - { - m_RankManager.AddGroupToRank("Default", "Default"); - } - } - m_RankManager.SetDefaultRank("Default"); - } -}; - - - - - -//////////////////////////////////////////////////////////////////////////////// // cRankManager: cRankManager::cRankManager(void) : @@ -421,21 +55,10 @@ void cRankManager::Initialize(cMojangAPI & a_MojangAPI) a_MojangAPI.SetRankManager(this); - // Check if tables empty, migrate from ini files then + // If tables are empty, create default ranks if (AreDBTablesEmpty()) { - LOGINFO("There are no ranks, migrating old-style INI files to new DB ranks..."); - LOGINFO("(This might take a while)"); - cRankManagerIniMigrator Migrator(*this, a_MojangAPI); - if (Migrator.Migrate()) - { - LOGINFO("Ranks migrated."); - // The default rank has been set by the migrator - return; - } - - // Migration failed. Add some defaults - LOGINFO("Rank migration failed, creating default ranks..."); + LOGINFO("Creating default ranks..."); CreateDefaults(); LOGINFO("Default ranks created."); } diff --git a/src/RankManager.h b/src/RankManager.h index abe860b1c..e2600dde0 100644 --- a/src/RankManager.h +++ b/src/RankManager.h @@ -53,7 +53,7 @@ public: ~cRankManager(); /** Initializes the rank manager. Performs migration and default-setting if no data is found in the DB. - The a_MojangAPI param is used when migrating from old ini files, to look up player UUIDs. */ + The a_MojangAPI param is used to keep player names in sync with UUIDs, since Mojang allows username changes. */ void Initialize(cMojangAPI & a_MojangAPI); /** Returns the name of the rank that the specified player has assigned to them. @@ -273,7 +273,7 @@ protected: /** Set to true once the manager is initialized. */ bool m_IsInitialized; - /** The MojangAPI instance that is used for translating playernames to UUIDs. + /** The MojangAPI instance that is used for keeping player names and UUIDs in sync. Set in Initialize(), may be nullptr. */ cMojangAPI * m_MojangAPI; |