diff --git a/dDatabase/GameDatabase/ITables/IAccounts.h b/dDatabase/GameDatabase/ITables/IAccounts.h index 13ecf29b..a58f3a25 100644 --- a/dDatabase/GameDatabase/ITables/IAccounts.h +++ b/dDatabase/GameDatabase/ITables/IAccounts.h @@ -14,6 +14,7 @@ public: std::string bcryptPassword; uint32_t id{}; uint32_t playKeyId{}; + uint64_t muteExpire{}; bool banned{}; bool locked{}; eGameMasterLevel maxGmLevel{}; diff --git a/dDatabase/GameDatabase/MySQL/Tables/Accounts.cpp b/dDatabase/GameDatabase/MySQL/Tables/Accounts.cpp index f4310dd8..b96c9c48 100644 --- a/dDatabase/GameDatabase/MySQL/Tables/Accounts.cpp +++ b/dDatabase/GameDatabase/MySQL/Tables/Accounts.cpp @@ -3,7 +3,7 @@ #include "eGameMasterLevel.h" std::optional MySQLDatabase::GetAccountInfo(const std::string_view username) { - auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level FROM accounts WHERE name = ? LIMIT 1;", username); + auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level, mute_expire FROM accounts WHERE name = ? LIMIT 1;", username); if (!result->next()) { return std::nullopt; @@ -16,6 +16,7 @@ std::optional MySQLDatabase::GetAccountInfo(const std::string_v toReturn.banned = result->getBoolean("banned"); toReturn.locked = result->getBoolean("locked"); toReturn.playKeyId = result->getUInt("play_key_id"); + toReturn.muteExpire = result->getUInt64("mute_expire"); return toReturn; } diff --git a/dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp b/dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp index 9431d407..72572f89 100644 --- a/dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp +++ b/dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp @@ -17,6 +17,7 @@ std::optional SQLiteDatabase::GetAccountInfo(const std::string_ toReturn.banned = result.getIntField("banned"); toReturn.locked = result.getIntField("locked"); toReturn.playKeyId = result.getIntField("play_key_id"); + toReturn.muteExpire = static_cast(result.getInt64Field("mute_expire")); return toReturn; } diff --git a/dGame/User.cpp b/dGame/User.cpp index 806d4611..7c03daa8 100644 --- a/dGame/User.cpp +++ b/dGame/User.cpp @@ -7,6 +7,10 @@ #include "dZoneManager.h" #include "eServerDisconnectIdentifiers.h" #include "eGameMasterLevel.h" +#include "BitStreamUtils.h" +#include "MessageType/Chat.h" +#include +#include User::User(const SystemAddress& sysAddr, const std::string& username, const std::string& sessionKey) { m_AccountID = 0; @@ -28,7 +32,7 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std: if (userInfo) { m_AccountID = userInfo->id; m_MaxGMLevel = userInfo->maxGmLevel; - m_MuteExpire = 0; //res->getUInt64(3); + m_MuteExpire = userInfo->muteExpire; } //If we're loading a zone, we'll load the last used (aka current) character: @@ -91,8 +95,28 @@ Character* User::GetLastUsedChar() { } } -bool User::GetIsMuted() const { - return m_MuteExpire == 1 || m_MuteExpire > time(NULL); +bool User::GetIsMuted() { + using namespace std::chrono; + constexpr auto refreshInterval = seconds{ 60 }; + const auto now = steady_clock::now(); + if (now - m_LastMuteCheck >= refreshInterval) { + m_LastMuteCheck = now; + if (const auto info = Database::Get()->GetAccountInfo(m_Username)) { + const auto expire = static_cast(info->muteExpire); + if (expire != m_MuteExpire) { + m_MuteExpire = expire; + + if (Game::chatServer && m_LoggedInCharID != 0) { + RakNet::BitStream bitStream; + BitStreamUtils::WriteHeader(bitStream, ServiceType::CHAT, MessageType::Chat::GM_MUTE); + bitStream.Write(m_LoggedInCharID); + bitStream.Write(m_MuteExpire); + Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); + } + } + } + } + return m_MuteExpire == 1 || m_MuteExpire > std::time(nullptr); } time_t User::GetMuteExpire() const { diff --git a/dGame/User.h b/dGame/User.h index 662842a8..7fe8d335 100644 --- a/dGame/User.h +++ b/dGame/User.h @@ -3,6 +3,7 @@ #include #include +#include #include "RakNetTypes.h" #include "dCommonVars.h" @@ -46,7 +47,7 @@ public: const std::unordered_map& GetIsBestFriendMap() { return m_IsBestFriendMap; } void UpdateBestFriendValue(const std::string_view playerName, const bool newValue); - bool GetIsMuted() const; + bool GetIsMuted(); time_t GetMuteExpire() const; void SetMuteExpire(time_t value); @@ -72,7 +73,8 @@ private: bool m_LastChatMessageApproved = false; int m_AmountOfTimesOutOfSync = 0; const int m_MaxDesyncAllowed = 12; - time_t m_MuteExpire; + uint64_t m_MuteExpire; + std::chrono::steady_clock::time_point m_LastMuteCheck{}; }; #endif // USER_H