Remove cRankManager migration code (#4714)
* Remove cRankManager migration code * Restore mistakenly removed code * Display log message when creating ranks
This commit is contained in:
parent
4e4ef9052e
commit
f4b5c4c341
@ -5,7 +5,6 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "RankManager.h"
|
||||
#include "IniFile.h"
|
||||
#include "Protocol/MojangAPI.h"
|
||||
#include "ClientHandle.h"
|
||||
|
||||
@ -13,371 +12,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:
|
||||
|
||||
@ -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.");
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user