RankMgr: Implemented default rank, added defaults.
This commit is contained in:
parent
e034b64a5b
commit
0daacd14d9
@ -1 +1 @@
|
||||
Subproject commit 6627e570a5265ae270aae978a1cad80dfb8a2b18
|
||||
Subproject commit 7cc99285ae5117418f657c3b295ca71f2b75b4f4
|
@ -7,6 +7,7 @@
|
||||
#include "RankManager.h"
|
||||
#include "inifile/iniFile.h"
|
||||
#include "Protocol/MojangAPI.h"
|
||||
#include "ClientHandle.h"
|
||||
|
||||
|
||||
|
||||
@ -55,6 +56,9 @@ public:
|
||||
LOGD("Setting ranks...");
|
||||
SetRanks();
|
||||
|
||||
LOGD("Creating defaults...");
|
||||
CreateDefaults();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -87,9 +91,12 @@ protected:
|
||||
AString m_Name;
|
||||
AStringVector m_Groups;
|
||||
|
||||
/** Assigned by ResolveUserUUIDs() */
|
||||
/** Assigned by ResolveUserUUIDs(), contains the online (Mojang) UUID of the player. */
|
||||
AString m_UUID;
|
||||
|
||||
/** Assigned by ResolveUserUUIDs(), contains the offline (generated) UUID of the player. */
|
||||
AString m_OfflineUUID;
|
||||
|
||||
|
||||
sUser(void) {}
|
||||
|
||||
@ -275,22 +282,15 @@ protected:
|
||||
m_MojangAPI.GetUUIDsFromPlayerNames(PlayerNames);
|
||||
|
||||
// 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);
|
||||
if (UUID.empty())
|
||||
{
|
||||
LOGWARNING("RankMigrator: Cannot resolve player %s to UUID, player will be left unranked", itr->second.m_Name.c_str());
|
||||
sUserMap::iterator itr2 = itr;
|
||||
++itr2;
|
||||
m_Users.erase(itr);
|
||||
itr = itr2;
|
||||
}
|
||||
else
|
||||
{
|
||||
itr->second.m_UUID = UUID;
|
||||
++itr;
|
||||
LOGWARNING("RankMigrator: Cannot resolve player %s to online UUID, player will be left unranked in online mode", itr->second.m_Name.c_str());
|
||||
}
|
||||
itr->second.m_UUID = UUID;
|
||||
itr->second.m_OfflineUUID = cClientHandle::GenerateOfflineUUID(itr->second.m_Name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,10 +350,28 @@ protected:
|
||||
AddGroupsToRank(Groups, RankName);
|
||||
}
|
||||
|
||||
// Set the rank to the user:
|
||||
m_RankManager.SetPlayerRank(itr->second.m_UUID, itr->second.m_Name, 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");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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 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 DefaultRank (RankID INTEGER)");
|
||||
|
||||
m_IsInitialized = true;
|
||||
|
||||
@ -410,12 +429,39 @@ void cRankManager::Initialize(cMojangAPI & 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...");
|
||||
CreateDefaults();
|
||||
LOGINFO("Default ranks created.");
|
||||
}
|
||||
|
||||
// Migration failed.
|
||||
// TODO: Check if tables empty, add some defaults then
|
||||
// Load the default rank:
|
||||
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);
|
||||
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;
|
||||
try
|
||||
{
|
||||
@ -1143,6 +1196,12 @@ void cRankManager::RemoveRank(const AString & a_RankName, const AString & a_Repl
|
||||
stmt.bind(1, RemoveRankID);
|
||||
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)
|
||||
{
|
||||
@ -1310,21 +1369,30 @@ bool cRankManager::RenameRank(const AString & a_OldName, const AString & a_NewNa
|
||||
stmt.bind(1, a_NewName);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Rename:
|
||||
bool res;
|
||||
{
|
||||
SQLite::Statement stmt(m_DB, "UPDATE Rank SET Name = ? WHERE Name = ?");
|
||||
stmt.bind(1, a_NewName);
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
return (
|
||||
@ -1699,7 +1818,8 @@ bool cRankManager::AreDBTablesEmpty(void)
|
||||
IsDBTableEmpty("PlayerRank") &&
|
||||
IsDBTableEmpty("PermGroup") &&
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -127,7 +127,9 @@ public:
|
||||
/** Removes the specified rank.
|
||||
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,
|
||||
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);
|
||||
|
||||
/** Removes the specified group completely.
|
||||
@ -143,6 +145,7 @@ public:
|
||||
|
||||
/** Renames the specified rank. No action if the rank name is not found.
|
||||
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. */
|
||||
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. */
|
||||
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:
|
||||
|
||||
/** The database storage for all the data. Protected by m_CS. */
|
||||
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;
|
||||
|
||||
/** Set to true once the manager is initialized. */
|
||||
@ -221,6 +234,9 @@ protected:
|
||||
/** Returns true iff the specified DB table is empty.
|
||||
If there's an error while querying, returns false. */
|
||||
bool IsDBTableEmpty(const AString & a_TableName);
|
||||
|
||||
/** Creates a default set of ranks / groups / permissions. */
|
||||
void CreateDefaults(void);
|
||||
} ;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user