1
0

RankMgr: Implemented default rank, added defaults.

This commit is contained in:
Mattes D 2014-08-23 03:44:04 +02:00
parent e034b64a5b
commit 0daacd14d9
3 changed files with 199 additions and 25 deletions

@ -1 +1 @@
Subproject commit 6627e570a5265ae270aae978a1cad80dfb8a2b18 Subproject commit 7cc99285ae5117418f657c3b295ca71f2b75b4f4

View File

@ -7,6 +7,7 @@
#include "RankManager.h" #include "RankManager.h"
#include "inifile/iniFile.h" #include "inifile/iniFile.h"
#include "Protocol/MojangAPI.h" #include "Protocol/MojangAPI.h"
#include "ClientHandle.h"
@ -55,6 +56,9 @@ public:
LOGD("Setting ranks..."); LOGD("Setting ranks...");
SetRanks(); SetRanks();
LOGD("Creating defaults...");
CreateDefaults();
return true; return true;
} }
@ -87,9 +91,12 @@ protected:
AString m_Name; AString m_Name;
AStringVector m_Groups; AStringVector m_Groups;
/** Assigned by ResolveUserUUIDs() */ /** Assigned by ResolveUserUUIDs(), contains the online (Mojang) UUID of the player. */
AString m_UUID; AString m_UUID;
/** Assigned by ResolveUserUUIDs(), contains the offline (generated) UUID of the player. */
AString m_OfflineUUID;
sUser(void) {} sUser(void) {}
@ -275,22 +282,15 @@ protected:
m_MojangAPI.GetUUIDsFromPlayerNames(PlayerNames); m_MojangAPI.GetUUIDsFromPlayerNames(PlayerNames);
// Assign the UUIDs back to players, remove those not resolved: // Assign the UUIDs back to players, remove those not resolved:
for (sUserMap::iterator itr = m_Users.begin(); itr != m_Users.end(); ) for (sUserMap::iterator itr = m_Users.begin(); itr != m_Users.end(); ++itr)
{ {
AString UUID = m_MojangAPI.GetUUIDFromPlayerName(itr->second.m_Name); AString UUID = m_MojangAPI.GetUUIDFromPlayerName(itr->second.m_Name);
if (UUID.empty()) if (UUID.empty())
{ {
LOGWARNING("RankMigrator: Cannot resolve player %s to UUID, player will be left unranked", itr->second.m_Name.c_str()); LOGWARNING("RankMigrator: Cannot resolve player %s to online UUID, player will be left unranked in online mode", itr->second.m_Name.c_str());
sUserMap::iterator itr2 = itr;
++itr2;
m_Users.erase(itr);
itr = itr2;
} }
else
{
itr->second.m_UUID = UUID; itr->second.m_UUID = UUID;
++itr; itr->second.m_OfflineUUID = cClientHandle::GenerateOfflineUUID(itr->second.m_Name);
}
} }
} }
@ -350,10 +350,28 @@ protected:
AddGroupsToRank(Groups, RankName); AddGroupsToRank(Groups, RankName);
} }
// Set the rank to the user: // 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_UUID, itr->second.m_Name, RankName);
m_RankManager.SetPlayerRank(itr->second.m_OfflineUUID, itr->second.m_Name, RankName);
} // for itr - m_Users[] } // 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");
}
}; };
@ -396,6 +414,7 @@ void cRankManager::Initialize(cMojangAPI & a_MojangAPI)
m_DB.exec("CREATE TABLE IF NOT EXISTS PermGroup (PermGroupID INTEGER PRIMARY KEY, Name)"); m_DB.exec("CREATE TABLE IF NOT EXISTS PermGroup (PermGroupID INTEGER PRIMARY KEY, Name)");
m_DB.exec("CREATE TABLE IF NOT EXISTS RankPermGroup (RankID INTEGER, PermGroupID INTEGER)"); m_DB.exec("CREATE TABLE IF NOT EXISTS RankPermGroup (RankID INTEGER, PermGroupID INTEGER)");
m_DB.exec("CREATE TABLE IF NOT EXISTS PermissionItem (PermGroupID INTEGER, Permission)"); m_DB.exec("CREATE TABLE IF NOT EXISTS PermissionItem (PermGroupID INTEGER, Permission)");
m_DB.exec("CREATE TABLE IF NOT EXISTS DefaultRank (RankID INTEGER)");
m_IsInitialized = true; m_IsInitialized = true;
@ -410,12 +429,39 @@ void cRankManager::Initialize(cMojangAPI & a_MojangAPI)
if (Migrator.Migrate()) if (Migrator.Migrate())
{ {
LOGINFO("Ranks migrated."); LOGINFO("Ranks migrated.");
// The default rank has been set by the migrator
return; return;
} }
// Migration failed. Add some defaults
LOGINFO("Rank migration failed, creating default ranks...");
CreateDefaults();
LOGINFO("Default ranks created.");
} }
// Migration failed. // Load the default rank:
// TODO: Check if tables empty, add some defaults then try
{
SQLite::Statement stmt(m_DB,
"SELECT Rank.Name FROM Rank "
"LEFT JOIN DefaultRank ON Rank.RankID = DefaultRank.RankID"
);
if (stmt.executeStep())
{
m_DefaultRank = stmt.getColumn(0).getText();
}
}
catch (const SQLite::Exception & ex)
{
LOGWARNING("%s: Cannot load default rank: %s", __FUNCTION__, ex.what());
return;
}
// If the default rank cannot be loaded, use the first rank:
if (m_DefaultRank.empty())
{
SetDefaultRank(GetAllRanks()[0]);
}
} }
@ -1086,6 +1132,13 @@ void cRankManager::RemoveRank(const AString & a_RankName, const AString & a_Repl
ASSERT(m_IsInitialized); ASSERT(m_IsInitialized);
cCSLock Lock(m_CS); cCSLock Lock(m_CS);
// Check if the default rank is being removed with a proper replacement:
if ((a_RankName == m_DefaultRank) && !RankExists(a_ReplacementRankName))
{
LOGWARNING("%s: Cannot remove rank %s, it is the default rank and the replacement rank doesn't exist.", __FUNCTION__, a_RankName.c_str());
return;
}
AStringVector res; AStringVector res;
try try
{ {
@ -1143,6 +1196,12 @@ void cRankManager::RemoveRank(const AString & a_RankName, const AString & a_Repl
stmt.bind(1, RemoveRankID); stmt.bind(1, RemoveRankID);
stmt.exec(); stmt.exec();
} }
// Update the default rank, if it was the one being removed:
if (a_RankName == m_DefaultRank)
{
m_DefaultRank = a_RankName;
}
} }
catch (const SQLite::Exception & ex) catch (const SQLite::Exception & ex)
{ {
@ -1310,21 +1369,30 @@ bool cRankManager::RenameRank(const AString & a_OldName, const AString & a_NewNa
stmt.bind(1, a_NewName); stmt.bind(1, a_NewName);
if (stmt.executeStep()) if (stmt.executeStep())
{ {
LOGD("%s: Rank %s is already present, cannot rename %s", __FUNCTION__, a_NewName.c_str(), a_OldName.c_str()); LOGINFO("%s: Rank %s is already present, cannot rename %s", __FUNCTION__, a_NewName.c_str(), a_OldName.c_str());
return false; return false;
} }
} }
// Rename: // Rename:
bool res;
{ {
SQLite::Statement stmt(m_DB, "UPDATE Rank SET Name = ? WHERE Name = ?"); SQLite::Statement stmt(m_DB, "UPDATE Rank SET Name = ? WHERE Name = ?");
stmt.bind(1, a_NewName); stmt.bind(1, a_NewName);
stmt.bind(2, a_OldName); stmt.bind(2, a_OldName);
res = (stmt.exec() > 0); if (stmt.exec() <= 0)
{
LOGINFO("%s: There is no rank %s, cannot rename to %s.", __FUNCTION__, a_OldName.c_str(), a_NewName.c_str());
return false;
}
} }
return res; // Update the default rank, if it was the one being renamed:
if (a_OldName == m_DefaultRank)
{
m_DefaultRank = a_NewName;
}
return true;
} }
catch (const SQLite::Exception & ex) catch (const SQLite::Exception & ex)
{ {
@ -1692,6 +1760,57 @@ void cRankManager::NotifyNameUUID(const AString & a_PlayerName, const AString &
bool cRankManager::SetDefaultRank(const AString & a_RankName)
{
ASSERT(m_IsInitialized);
cCSLock Lock(m_CS);
try
{
// Find the rank's ID:
int RankID = 0;
{
SQLite::Statement stmt(m_DB, "SELECT RankID FROM Rank WHERE Name = ?");
stmt.bind(1, a_RankName);
if (!stmt.executeStep())
{
LOGINFO("%s: Cannot set rank %s as the default, it does not exist.", __FUNCTION__, a_RankName.c_str());
return false;
}
}
// Set the rank as the default:
{
SQLite::Statement stmt(m_DB, "UPDATE DefaultRank SET RankID = ?");
stmt.bind(1, RankID);
if (stmt.exec() < 1)
{
// Failed to update, there might be none in the DB, try inserting:
SQLite::Statement stmt2(m_DB, "INSERT INTO DefaultRank (RankID) VALUES (?)");
stmt2.bind(1, RankID);
if (stmt2.exec() < 1)
{
LOGINFO("%s: Cannot update the default rank in the DB to %s.", __FUNCTION__, a_RankName.c_str());
return false;
}
}
}
// Set the internal cache:
m_DefaultRank = a_RankName;
return true;
}
catch (const SQLite::Exception & ex)
{
LOGWARNING("%s: Failed to update DB: %s", __FUNCTION__, ex.what());
return false;
}
}
bool cRankManager::AreDBTablesEmpty(void) bool cRankManager::AreDBTablesEmpty(void)
{ {
return ( return (
@ -1699,7 +1818,8 @@ bool cRankManager::AreDBTablesEmpty(void)
IsDBTableEmpty("PlayerRank") && IsDBTableEmpty("PlayerRank") &&
IsDBTableEmpty("PermGroup") && IsDBTableEmpty("PermGroup") &&
IsDBTableEmpty("RankPermGroup") && IsDBTableEmpty("RankPermGroup") &&
IsDBTableEmpty("PermissionItem") IsDBTableEmpty("PermissionItem") &&
IsDBTableEmpty("DefaultRank")
); );
} }
@ -1724,3 +1844,41 @@ bool cRankManager::IsDBTableEmpty(const AString & a_TableName)
void cRankManager::CreateDefaults(void)
{
// Wrap everything in a big transaction to speed things up:
cMassChangeLock Lock(*this);
// Create ranks:
AddRank("Default", "", "", "");
AddRank("VIP", "", "", "");
AddRank("Operator", "", "", "");
AddRank("Admin", "", "", "");
// Create groups:
AddGroup("Default");
AddGroup("Kick");
AddGroup("Teleport");
AddGroup("Everything");
// Add groups to ranks:
AddGroupToRank("Default", "Default");
AddGroupToRank("Teleport", "VIP");
AddGroupToRank("Teleport", "Operator");
AddGroupToRank("Kick", "Operator");
AddGroupToRank("Everything", "Admin");
// Add permissions to groups:
AddPermissionToGroup("core.build", "Default");
AddPermissionToGroup("core.tp", "Teleport");
AddPermissionToGroup("core.kick", "Kick");
AddPermissionToGroup("*", "Everything");
// Set the default rank:
SetDefaultRank("Default");
}

View File

@ -127,7 +127,9 @@ public:
/** Removes the specified rank. /** Removes the specified rank.
All players assigned to that rank will be re-assigned to a_ReplacementRankName. All players assigned to that rank will be re-assigned to a_ReplacementRankName.
If a_ReplacementRankName is empty or not a valid rank, the player will be removed from the DB, If a_ReplacementRankName is empty or not a valid rank, the player will be removed from the DB,
which means they will receive the default rank the next time they are queried. */ which means they will receive the default rank the next time they are queried.
If the rank being removed is the default rank, the default will be changed to the replacement
rank; the operation fails if there's no replacement. */
void RemoveRank(const AString & a_RankName, const AString & a_ReplacementRankName); void RemoveRank(const AString & a_RankName, const AString & a_ReplacementRankName);
/** Removes the specified group completely. /** Removes the specified group completely.
@ -143,6 +145,7 @@ public:
/** Renames the specified rank. No action if the rank name is not found. /** Renames the specified rank. No action if the rank name is not found.
Fails if the new name is already used. Fails if the new name is already used.
Updates the cached m_DefaultRank if the default rank is being renamed.
Returns true on success, false on failure. */ Returns true on success, false on failure. */
bool RenameRank(const AString & a_OldName, const AString & a_NewName); bool RenameRank(const AString & a_OldName, const AString & a_NewName);
@ -199,12 +202,22 @@ public:
/** Called by cMojangAPI whenever the playername-uuid pairing is discovered. Updates the DB. */ /** Called by cMojangAPI whenever the playername-uuid pairing is discovered. Updates the DB. */
void NotifyNameUUID(const AString & a_PlayerName, const AString & a_UUID); void NotifyNameUUID(const AString & a_PlayerName, const AString & a_UUID);
/** Sets the specified rank as the default rank.
Returns true on success, false on failure (rank not found). */
bool SetDefaultRank(const AString & a_RankName);
/** Returns the name of the default rank. */
const AString & GetDefaultRank(void) const { return m_DefaultRank; }
protected: protected:
/** The database storage for all the data. Protected by m_CS. */ /** The database storage for all the data. Protected by m_CS. */
SQLite::Database m_DB; SQLite::Database m_DB;
/** The mutex protecting m_DB against multi-threaded access. */ /** The name of the default rank. Kept as a cache so that queries for it don't need to go through the DB. */
AString m_DefaultRank;
/** The mutex protecting m_DB and m_DefaultRank against multi-threaded access. */
cCriticalSection m_CS; cCriticalSection m_CS;
/** Set to true once the manager is initialized. */ /** Set to true once the manager is initialized. */
@ -221,6 +234,9 @@ protected:
/** Returns true iff the specified DB table is empty. /** Returns true iff the specified DB table is empty.
If there's an error while querying, returns false. */ If there's an error while querying, returns false. */
bool IsDBTableEmpty(const AString & a_TableName); bool IsDBTableEmpty(const AString & a_TableName);
/** Creates a default set of ranks / groups / permissions. */
void CreateDefaults(void);
} ; } ;