diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index db9c61082..d6066b38b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -52,6 +52,7 @@ SET (SRCS MonsterConfig.cpp Noise.cpp ProbabDistrib.cpp + RankManager.cpp RCONServer.cpp Root.cpp Scoreboard.cpp @@ -121,6 +122,7 @@ SET (HDRS MonsterConfig.h Noise.h ProbabDistrib.h + RankManager.h RCONServer.h Root.h Scoreboard.h diff --git a/src/RankManager.cpp b/src/RankManager.cpp new file mode 100644 index 000000000..954edd099 --- /dev/null +++ b/src/RankManager.cpp @@ -0,0 +1,153 @@ + +// RankManager.cpp + +// Implements the cRankManager class that represents the rank manager responsible for assigning permissions and message visuals to players + +#include "Globals.h" +#include "RankManager.h" +#include "Protocol/MojangAPI.h" +#include "inifile/iniFile.h" +#include + + + + + +/* +// This code is for internal testing while developing the cRankManager class +static class cRankMgrTest +{ +public: + cRankMgrTest(void) : + m_Mgr() + { + // Initialize the cMojangAPI so that it can convert playernames to UUIDs: + cIniFile Ini; + Ini.ReadFile("settings.ini"); + m_API.Start(Ini); + + // Test the cRankManager class: + ReportPlayer("xoft"); + } + + void ReportPlayer(const AString & a_PlayerName) + { + // Get the player's UUID and rank: + AString UUID = m_API.GetUUIDFromPlayerName(a_PlayerName); + std::cout << "Player " << a_PlayerName << " has UUID '" << UUID <<"'." << std::endl; + std::cout << " Rank: '" << m_Mgr.GetPlayerRankName(UUID) << "'." << std::endl; + + // List all the permission groups for the player: + AStringVector Groups = m_Mgr.GetPlayerPermissionGroups(UUID); + std::cout << " Groups(" << Groups.size() << "):" << std::endl; + for (AStringVector::const_iterator itr = Groups.begin(), end = Groups.end(); itr != end; ++itr) + { + std::cout << " '" << *itr << "'." << std::endl; + } // for itr - Groups[] + + // List all the permissions for the player: + AStringVector Permissions = m_Mgr.GetPlayerPermissions(UUID); + std::cout << " Permissions(" << Permissions.size() << "):" << std::endl; + for (AStringVector::const_iterator itr = Permissions.begin(), end = Permissions.end(); itr != end; ++itr) + { + std::cout << " '" << *itr << "'." << std::endl; + } // for itr - Groups[] + + std::cout << "Done." << std::endl; + } + +protected: + cRankManager m_Mgr; + cMojangAPI m_API; +} g_RankMgrTest; +//*/ + + + + + +cRankManager::cRankManager(void) : + m_DB("Ranks.sqlite", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) +{ + // Create the DB tables, if they don't exist: + m_DB.exec("CREATE TABLE IF NOT EXISTS Rank (RankID, Name, MsgPrefix, MsgPostfix, MsgNameColorCode)"); + m_DB.exec("CREATE TABLE IF NOT EXISTS PlayerRank (PlayerUUID, PlayerName, RankID)"); + m_DB.exec("CREATE TABLE IF NOT EXISTS PermissionGroup (GroupID, Name)"); + m_DB.exec("CREATE TABLE IF NOT EXISTS RankPermissionGroups (RankID, GroupID)"); + m_DB.exec("CREATE TABLE IF NOT EXISTS PermissionItem (GroupID, Permission)"); + + // TODO: Check if tables empty, add some defaults then +} + + + + + +AString cRankManager::GetPlayerRankName(const AString & a_PlayerUUID) +{ + SQLite::Statement stmt(m_DB, "SELECT Rank.Name FROM Rank LEFT JOIN PlayerRank ON Rank.RankID = PlayerRank.RankID WHERE PlayerRank.PlayerUUID = ?"); + stmt.bind(1, a_PlayerUUID); + stmt.executeStep(); + if (stmt.isDone()) + { + // No data returned from the DB + return AString(); + } + return stmt.getColumn(0).getText(); +} + + + + + +AStringVector cRankManager::GetPlayerPermissionGroups(const AString & a_PlayerUUID) +{ + // Prepare the DB statement: + SQLite::Statement stmt(m_DB, + "SELECT PermissionGroup.Name FROM PermissionGroup " + "LEFT JOIN RankPermissionGroups " + "ON PermissionGroup.GroupID = RankPermissionGroups.GroupID " + "LEFT JOIN PlayerRank " + "ON PlayerRank.RankID = RankPermissionGroups.RankID " + "WHERE PlayerRank.PlayerUUID = ?" + ); + stmt.bind(1, a_PlayerUUID); + + // Execute and get results: + AStringVector res; + while (stmt.executeStep()) + { + res.push_back(stmt.getColumn(0).getText()); + } + return res; +} + + + + + +AStringVector cRankManager::GetPlayerPermissions(const AString & a_PlayerUUID) +{ + // Prepare the DB statement: + SQLite::Statement stmt(m_DB, + "SELECT PermissionItem.Permission FROM PermissionItem " + "LEFT JOIN RankPermissionGroups " + "ON PermissionItem.GroupID = RankPermissionGroups.GroupID " + "LEFT JOIN PlayerRank " + "ON PlayerRank.RankID = RankPermissionGroups.RankID " + "WHERE PlayerRank.PlayerUUID = ?" + ); + stmt.bind(1, a_PlayerUUID); + + // Execute and get results: + AStringVector res; + while (stmt.executeStep()) + { + res.push_back(stmt.getColumn(0).getText()); + } + return res; +} + + + + diff --git a/src/RankManager.h b/src/RankManager.h new file mode 100644 index 000000000..cda6beee9 --- /dev/null +++ b/src/RankManager.h @@ -0,0 +1,103 @@ + +// RankManager.h + +// Declares the cRankManager class that represents the rank manager responsible for assigning permissions and message visuals to players + + + + +#pragma once + +#include "SQLiteCpp/Database.h" + + + + + +class cRankManager +{ +public: + cRankManager(void); + + /** Returns the name of the rank that the specified player has assigned to them. */ + AString GetPlayerRankName(const AString & a_PlayerUUID); + + /** Returns the names of PermissionGroups that the specified player has assigned to them. */ + AStringVector GetPlayerPermissionGroups(const AString & a_PlayerUUID); + + /** Returns the permissions that the specified player has assigned to them. */ + AStringVector GetPlayerPermissions(const AString & a_PlayerUUID); + + /** Returns the names of groups that the specified rank has assigned to it. */ + AStringVector GetRankPermissionGroups(const AString & a_RankName); + + /** Returns the permissions that the specified permission group has assigned to it. */ + AStringVector GetPermissionGroupPermissiont(const AString & a_GroupName); + + /** Returns the names of all defined ranks. */ + AStringVector GetAllRanks(void); + + /** Returns the names of all permission groups. */ + AStringVector GetAllPermissionGroups(void); + + /** Returns all the distinct permissions that are stored in the DB. */ + AStringVector GetAllPermissions(void); + + /** Returns the message visuals (prefix, postfix, color) for the specified player. */ + void GetPlayerMsgVisuals( + const AString & a_PlayerUUID, + AString & a_MsgPrefix, + AString & a_MsgPostfix, + AString & a_MsgNameColorCode + ); + + /** Adds a new rank. No action if the rank already exists. */ + void AddRank(const AString & a_RankName); + + /** Adds a new permission group. No action if such a group already exists. */ + void AddPermissionGroup(const AString & a_GroupName); + + /** Adds the specified permission group to the specified rank. + Fails if the rank or group names are not found. + Returns true if successful, false on error. */ + bool AddPermissionGroupToRank(const AString & a_RankName, const AString & a_GroupName); + + /** Adds the specified permission to the specified permission group. + Fails if the permission group name is not found. + Returns true if successful, false on error. */ + bool AddPermissionToPermissionGroup(const AString & a_Permission, const AString & a_GroupName); + + /** Removes the specified rank. + All players assigned to that rank will be re-assigned to a_ReplacementRankName, unless it is empty. */ + void RemoveRank(const AString & a_RankName, const AString & a_ReplacementRankName); + + /** Removes the specified permission group. */ + void RemovePermissionGroup(const AString & a_PermissionGroup); + + /** Removes the specified permission from the specified permission group. */ + void RemovePermission(const AString & a_Permission, const AString & a_PermissionGroup); + + /** Renames the specified rank. No action if the rank name is not found. + Fails if the new name is already used. + Returns true on success, false on failure. */ + bool RenameRank(const AString & a_OldName, const AString & a_NewName); + + /** Renames the specified permission group. No action if the rank name is not found. + Fails if the new name is already used. + Returns true on success, false on failure. */ + bool RenamePermissionGroup(const AString & a_OldName, const AString & a_NewName); + + /** Sets the specified player's rank. + If the player already had rank assigned to them, it is overwritten with the new rank. + Note that this doesn't change the cPlayer if the player is already connected, you need to update all the + cPlayer instances manually. */ + void SetPlayerRank(const AString & a_PlayerUUID, const AString & a_RankName); + +protected: + + SQLite::Database m_DB; +} ; + + + +