From 99e2d21147815820575c21f9a1f2346e222db985 Mon Sep 17 00:00:00 2001 From: Tracer <43095317+TracerDS@users.noreply.github.com> Date: Sat, 20 May 2023 22:18:25 +0200 Subject: [PATCH 1/6] Created new events New events: - `onAccountCreate` - `onAccountRemove` --- .../mods/deathmatch/logic/CAccountManager.cpp | 20 +++++++++++++++++-- Server/mods/deathmatch/logic/CGame.cpp | 3 +++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Server/mods/deathmatch/logic/CAccountManager.cpp b/Server/mods/deathmatch/logic/CAccountManager.cpp index 99037771a0..dfbf167473 100644 --- a/Server/mods/deathmatch/logic/CAccountManager.cpp +++ b/Server/mods/deathmatch/logic/CAccountManager.cpp @@ -18,6 +18,7 @@ #include "CIdArray.h" #include "CAccessControlListManager.h" #include "Utils.h" +#include "CMapManager.h" CAccountManager::CAccountManager(const SString& strDbPathFilename) : m_AccountProtect(6, 30000, 60000 * 1) // Max of 6 attempts per 30 seconds, then 1 minute ignore @@ -1000,13 +1001,19 @@ void CAccountManager::GetAccountsByData(const SString& dataName, const SString& CAccount* CAccountManager::AddGuestAccount(const SString& strName) { - CAccount* pAccount = new CAccount(this, EAccountType::Guest, strName); + CAccount* pAccount = new CAccount(this, EAccountType::Guest, strName); + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments); return pAccount; } CAccount* CAccountManager::AddConsoleAccount(const SString& strName) { - CAccount* pAccount = new CAccount(this, EAccountType::Console, strName); + CAccount* pAccount = new CAccount(this, EAccountType::Console, strName); + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments); return pAccount; } @@ -1014,6 +1021,9 @@ CAccount* CAccountManager::AddPlayerAccount(const SString& strName, const SStrin const SString& strHttpPassAppend) { CAccount* pAccount = new CAccount(this, EAccountType::Player, strName, strPassword, iUserID, strIP, strSerial, strHttpPassAppend); + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments); return pAccount; } @@ -1021,6 +1031,9 @@ CAccount* CAccountManager::AddNewPlayerAccount(const SString& strName, const SSt { CAccount* pAccount = new CAccount(this, EAccountType::Player, strName, strPassword, ++m_iAccounts); Save(pAccount); + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments); return pAccount; } @@ -1035,6 +1048,9 @@ bool CAccountManager::RemoveAccount(CAccount* pAccount) m_pDatabaseManager->Execf(m_hDbConnection, "DELETE FROM userdata WHERE userid=?", SQLITE_INTEGER, iUserID); m_pDatabaseManager->Execf(m_hDbConnection, "DELETE FROM serialusage WHERE userid=?", SQLITE_INTEGER, iUserID); } + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountRemove", Arguments); delete pAccount; return true; } diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index c41c5a90f9..6884c8735d 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -1624,6 +1624,9 @@ void CGame::AddBuiltInEvents() // Account events m_Events.AddEvent("onAccountDataChange", "account, key, value", NULL, false); + m_Events.AddEvent("onAccountCreate", "account", NULL, false); + m_Events.AddEvent("onAccountRemove", "account", NULL, false); + // Other events m_Events.AddEvent("onSettingChange", "setting, oldValue, newValue", NULL, false); m_Events.AddEvent("onChatMessage", "message, element", NULL, false); From 457f469f85be578f8a9fc8187483778a288108ef Mon Sep 17 00:00:00 2001 From: Tracer <43095317+TracerDS@users.noreply.github.com> Date: Tue, 25 Jul 2023 10:29:10 +0200 Subject: [PATCH 2/6] Refactored CAccountManager a little --- .../mods/deathmatch/logic/CAccountManager.cpp | 136 ++++++++---------- 1 file changed, 60 insertions(+), 76 deletions(-) diff --git a/Server/mods/deathmatch/logic/CAccountManager.cpp b/Server/mods/deathmatch/logic/CAccountManager.cpp index dfbf167473..46a092c563 100644 --- a/Server/mods/deathmatch/logic/CAccountManager.cpp +++ b/Server/mods/deathmatch/logic/CAccountManager.cpp @@ -863,7 +863,7 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) if (iter->second.GetType() == LUA_TBOOLEAN) { lua_pushstring(pLua, iter->second.GetKey().c_str()); - lua_pushboolean(pLua, iter->second.GetStrValue() == "true" ? true : false); + lua_pushboolean(pLua, iter->second.GetStrValue() == "true"); lua_settable(pLua, -3); } if (iter->second.GetType() == LUA_TNUMBER) @@ -892,46 +892,44 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT key,value,type from userdata where userid=?", SQLITE_INTEGER, iUserID); // Do we have any results? - if (result->nRows > 0) + if (result->nRows <= 0) + return false; + + // Loop through until i is the same as the number of rows + for (const auto& row : *result.operator->()) { - // Loop through until i is the same as the number of rows - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + // Get our key + strKey = reinterpret_cast(row[0].pVal); + // Get our type + int iType = static_cast(row[2].nVal); + // Account data is stored as text so we don't need to check what type it is just return it + if (iType == LUA_TNIL) { - const CRegistryResultRow& row = *iter; - // Get our key - strKey = (const char*)row[0].pVal; - // Get our type - int iType = static_cast(row[2].nVal); - // Account data is stored as text so we don't need to check what type it is just return it - if (iType == LUA_TNIL) - { - lua_pushstring(pLua, strKey); - lua_pushnil(pLua); - lua_settable(pLua, -3); - } - if (iType == LUA_TBOOLEAN) - { - SString strResult = (const char*)row[1].pVal; - lua_pushstring(pLua, strKey); - lua_pushboolean(pLua, strResult == "true" ? true : false); - lua_settable(pLua, -3); - } - if (iType == LUA_TNUMBER) - { - lua_pushstring(pLua, strKey); - lua_pushnumber(pLua, strtod((const char*)row[1].pVal, NULL)); - lua_settable(pLua, -3); - } - else - { - lua_pushstring(pLua, strKey); - lua_pushstring(pLua, ((const char*)row[1].pVal)); - lua_settable(pLua, -3); - } + lua_pushstring(pLua, strKey); + lua_pushnil(pLua); + lua_settable(pLua, -3); + } + if (iType == LUA_TBOOLEAN) + { + SString strResult = (const char*)row[1].pVal; + lua_pushstring(pLua, strKey); + lua_pushboolean(pLua, strResult == "true"); + lua_settable(pLua, -3); + } + if (iType == LUA_TNUMBER) + { + lua_pushstring(pLua, strKey); + lua_pushnumber(pLua, strtod((const char*)row[1].pVal, NULL)); + lua_settable(pLua, -3); + } + else + { + lua_pushstring(pLua, strKey); + lua_pushstring(pLua, ((const char*)row[1].pVal)); + lua_settable(pLua, -3); } - return true; } - return false; + return true; } void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector& outAccounts) @@ -940,10 +938,8 @@ void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector< CRegistryResult result; m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE serial = ?", SQLITE_TEXT, strSerial.c_str()); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : *result.operator->()) { - const CRegistryResultRow& row = *iter; - CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); @@ -956,10 +952,8 @@ void CAccountManager::GetAccountsByIP(const SString& strIP, std::vectorQueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE ip = ?", SQLITE_TEXT, strIP.c_str()); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : *result.operator->()) { - const CRegistryResultRow& row = *iter; - CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); @@ -971,10 +965,8 @@ CAccount* CAccountManager::GetAccountByID(int ID) CRegistryResult result; m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE id = ?", SQLITE_INTEGER, ID); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : *result.operator->()) { - const auto& row = *iter; - return Get(reinterpret_cast(row[0].pVal)); } @@ -989,16 +981,15 @@ void CAccountManager::GetAccountsByData(const SString& dataName, const SString& "SELECT acc.name FROM accounts acc, userdata dat WHERE dat.key = ? AND dat.value = ? AND dat.userid = acc.id", SQLITE_TEXT, dataName.c_str(), SQLITE_TEXT, value.c_str()); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : *result.operator->()) { - const CRegistryResultRow& row = *iter; - CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); } } +// Fires for all joining players CAccount* CAccountManager::AddGuestAccount(const SString& strName) { CAccount* pAccount = new CAccount(this, EAccountType::Guest, strName); @@ -1008,6 +999,7 @@ CAccount* CAccountManager::AddGuestAccount(const SString& strName) return pAccount; } +// Fires only when console is created CAccount* CAccountManager::AddConsoleAccount(const SString& strName) { CAccount* pAccount = new CAccount(this, EAccountType::Console, strName); @@ -1017,6 +1009,7 @@ CAccount* CAccountManager::AddConsoleAccount(const SString& strName) return pAccount; } +// Fires for all created player accounts CAccount* CAccountManager::AddPlayerAccount(const SString& strName, const SString& strPassword, int iUserID, const SString& strIP, const SString& strSerial, const SString& strHttpPassAppend) { @@ -1027,6 +1020,7 @@ CAccount* CAccountManager::AddPlayerAccount(const SString& strName, const SStrin return pAccount; } +// Fires whenever "addaccount" or "addAccount" was executed CAccount* CAccountManager::AddNewPlayerAccount(const SString& strName, const SString& strPassword) { CAccount* pAccount = new CAccount(this, EAccountType::Player, strName, strPassword, ++m_iAccounts); @@ -1071,22 +1065,21 @@ void CAccountManager::StaticDbCallback(CDbJobData* pJobData, void* pContext) void CAccountManager::DbCallback(CDbJobData* pJobData) { - if (m_pDatabaseManager->QueryPoll(pJobData, 0)) + if (!m_pDatabaseManager->QueryPoll(pJobData, 0)) { - if (pJobData->result.status == EJobResult::FAIL) - { - CLogger::LogPrintf("ERROR: While updating account with '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason); - if (pJobData->result.strReason.ContainsI("missing database")) - { - // Try reconnection - CLogger::LogPrintf("INFO: Reconnecting to accounts database\n"); - ReconnectToDatabase(); - } - } + CLogger::LogPrintf("ERROR: Something worrying happened in DbCallback '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason); + return; } - else + + if (pJobData->result.status != EJobResult::FAIL) + return; + + CLogger::LogPrintf("ERROR: While updating account with '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason); + if (pJobData->result.strReason.ContainsI("missing database")) { - CLogger::LogPrintf("ERROR: Something worrying happened in DbCallback '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason); + // Try reconnection + CLogger::LogPrintf("INFO: Reconnecting to accounts database\n"); + ReconnectToDatabase(); } } @@ -1095,9 +1088,7 @@ void CAccountManager::DbCallback(CDbJobData* pJobData) // bool CAccountManager::IsValidAccountName(const SString& strName) { - if (strName.length() < MIN_USERNAME_LENGTH) - return false; - return true; + return strName.length() >= MIN_USERNAME_LENGTH; } // @@ -1105,9 +1096,7 @@ bool CAccountManager::IsValidAccountName(const SString& strName) // bool CAccountManager::IsValidPassword(const SString& strPassword) { - if (strPassword.length() < MIN_PASSWORD_LENGTH) - return false; - return true; + return strPassword.length() >= MIN_PASSWORD_LENGTH; } // @@ -1158,12 +1147,8 @@ bool CAccountManager::IsAuthorizedSerialRequired(CAccount* pAccount) // bool CAccountManager::IsHttpLoginAllowed(CAccount* pAccount, const SString& strIp) { - if (!g_pGame->GetConfig()->GetAuthSerialHttpEnabled() || g_pGame->GetConfig()->IsAuthSerialHttpIpException(strIp) || - !IsAuthorizedSerialRequired(pAccount) || pAccount->IsIpAuthorized(strIp)) - { - return true; - } - return false; + return !g_pGame->GetConfig()->GetAuthSerialHttpEnabled() || g_pGame->GetConfig()->IsAuthSerialHttpIpException(strIp) || + !IsAuthorizedSerialRequired(pAccount) || pAccount->IsIpAuthorized(strIp); } // @@ -1189,9 +1174,8 @@ void CAccountManager::LoadAccountSerialUsage(CAccount* pAccount) " WHERE userid=?", SQLITE_INTEGER, pAccount->GetID()); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : *result.operator->()) { - const CRegistryResultRow& row = *iter; outSerialUsageList.push_back(CAccount::SSerialUsage()); CAccount::SSerialUsage& info = outSerialUsageList.back(); info.strSerial = (const char*)row[0].pVal; From 926d5fc5d5e57b50366a2e3cebd621b5978f8a04 Mon Sep 17 00:00:00 2001 From: Tracer <43095317+TracerDS@users.noreply.github.com> Date: Tue, 25 Jul 2023 10:46:13 +0200 Subject: [PATCH 3/6] Added `getAccountType` function Probably not useful but its better to have that than to check if it belongs to console or to a guest --- Server/mods/deathmatch/logic/CAccount.h | 2 ++ .../deathmatch/logic/luadefs/CLuaAccountDefs.cpp | 16 ++++++++++++++++ .../deathmatch/logic/luadefs/CLuaAccountDefs.h | 3 +++ 3 files changed, 21 insertions(+) diff --git a/Server/mods/deathmatch/logic/CAccount.h b/Server/mods/deathmatch/logic/CAccount.h index b2ea2f58e9..ab5ed88eba 100644 --- a/Server/mods/deathmatch/logic/CAccount.h +++ b/Server/mods/deathmatch/logic/CAccount.h @@ -79,6 +79,8 @@ class CAccount const SString& GetName() { return m_strName; } void SetName(const std::string& strName); + EAccountType GetType() { return m_AccountType; } + void SetPassword(const SString& strPassword); bool IsPassword(const SString& strPassword, bool* pbUsedHttpPassAppend = nullptr); SString GetPasswordHash(); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp index 22e24c73e8..339fde0449 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp @@ -23,6 +23,7 @@ void CLuaAccountDefs::LoadFunctions() // Account get functions {"getAccountName", GetAccountName}, + {"getAccountType", ArgumentParser}, {"getAccountPlayer", GetAccountPlayer}, {"isGuestAccount", IsGuestAccount}, {"getAccountData", GetAccountData}, @@ -77,6 +78,7 @@ void CLuaAccountDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getData", "getAccountData"); lua_classfunction(luaVM, "getAllData", "getAllAccountData"); lua_classfunction(luaVM, "getName", "getAccountName"); + lua_classfunction(luaVM, "getType", "getAccountType"); lua_classfunction(luaVM, "getPlayer", "getAccountPlayer"); lua_classfunction(luaVM, "isGuest", "isGuestAccount"); @@ -116,6 +118,20 @@ int CLuaAccountDefs::GetAccountName(lua_State* luaVM) return 1; } +std::optional CLuaAccountDefs::GetAccountType(CAccount* pAccount) +{ + switch (pAccount->GetType()) + { + case EAccountType::Guest: + return "guest"; + case EAccountType::Console: + return "console"; + case EAccountType::Player: + return "player"; + } + return {}; +} + int CLuaAccountDefs::GetAccountPlayer(lua_State* luaVM) { // player getAccountPlayer ( account theAccount ) diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h index dead6074fa..e1e2e82340 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h @@ -26,6 +26,9 @@ class CLuaAccountDefs : public CLuaDefs LUA_DECLARE(GetAccount); LUA_DECLARE(GetAccounts); LUA_DECLARE(GetAccountName); + + static std::optional GetAccountType(CAccount* pAccount); + LUA_DECLARE(GetAccountPlayer); LUA_DECLARE(IsGuestAccount); LUA_DECLARE(GetAccountData); From 49a6e314ed6e934b6f90341a07a103126e0c5a7c Mon Sep 17 00:00:00 2001 From: Tracer <43095317+TracerDS@users.noreply.github.com> Date: Tue, 25 Jul 2023 11:16:56 +0200 Subject: [PATCH 4/6] Refactored CAccount a little Added const qualifiers, reformatted everything in general --- Server/mods/deathmatch/logic/CAccount.cpp | 75 ++++++++----------- Server/mods/deathmatch/logic/CAccount.h | 32 ++++---- .../mods/deathmatch/logic/CAccountManager.cpp | 40 +++++----- 3 files changed, 68 insertions(+), 79 deletions(-) diff --git a/Server/mods/deathmatch/logic/CAccount.cpp b/Server/mods/deathmatch/logic/CAccount.cpp index 90e52e5696..73934a9f8b 100644 --- a/Server/mods/deathmatch/logic/CAccount.cpp +++ b/Server/mods/deathmatch/logic/CAccount.cpp @@ -210,7 +210,7 @@ void CAccount::EnsureLoadedSerialUsage() } } -bool CAccount::HasLoadedSerialUsage() +bool CAccount::HasLoadedSerialUsage() const { return m_bLoadedSerialUsage; } @@ -238,11 +238,7 @@ CAccount::SSerialUsage* CAccount::GetSerialUsage(const SString& strSerial) bool CAccount::IsSerialAuthorized(const SString& strSerial) { SSerialUsage* pInfo = GetSerialUsage(strSerial); - if (pInfo) - { - return pInfo->IsAuthorized(); - } - return false; + return pInfo ? pInfo->IsAuthorized() : false; } // @@ -265,17 +261,13 @@ bool CAccount::IsIpAuthorized(const SString& strIp) bool CAccount::AuthorizeSerial(const SString& strSerial, const SString& strWho) { SSerialUsage* pInfo = GetSerialUsage(strSerial); - if (pInfo) - { - if (!pInfo->IsAuthorized()) - { - pInfo->tAuthDate = time(nullptr); - pInfo->strAuthWho = strWho; - m_pManager->MarkAsChanged(this); - return true; - } - } - return false; + if (!pInfo || pInfo->IsAuthorized()) + return false; + + pInfo->tAuthDate = time(nullptr); + pInfo->strAuthWho = strWho; + m_pManager->MarkAsChanged(this); + return true; } // @@ -320,29 +312,28 @@ void CAccount::RemoveUnauthorizedSerials() bool CAccount::AddSerialForAuthorization(const SString& strSerial, const SString& strIp) { SSerialUsage* pInfo = GetSerialUsage(strSerial); - if (!pInfo) - { - // Only one new serial at a time, so remove all other unauthorized serials for this account - RemoveUnauthorizedSerials(); + if (pInfo) + return false; - SSerialUsage info; - info.strSerial = strSerial; - info.strAddedIp = strIp; - info.tAddedDate = time(nullptr); - info.tAuthDate = 0; - info.tLastLoginDate = 0; - info.tLastLoginHttpDate = 0; + // Only one new serial at a time, so remove all other unauthorized serials for this account + RemoveUnauthorizedSerials(); - // First one doesn't require authorization - if (m_SerialUsageList.size() == 0) - { - info.tAuthDate = time(nullptr); - } - m_SerialUsageList.push_back(info); - m_pManager->MarkAsChanged(this); - return true; + SSerialUsage info; + info.strSerial = strSerial; + info.strAddedIp = strIp; + info.tAddedDate = time(nullptr); + info.tAuthDate = 0; + info.tLastLoginDate = 0; + info.tLastLoginHttpDate = 0; + + // First one doesn't require authorization + if (m_SerialUsageList.size() == 0) + { + info.tAuthDate = time(nullptr); } - return false; + m_SerialUsageList.push_back(info); + m_pManager->MarkAsChanged(this); + return true; } // @@ -372,10 +363,10 @@ void CAccount::OnLoginHttpSuccess(const SString& strIp) EnsureLoadedSerialUsage(); for (auto& info : m_SerialUsageList) { - if (info.strLastLoginIp == strIp && info.IsAuthorized()) - { - info.tLastLoginHttpDate = time(nullptr); - m_pManager->MarkAsChanged(this); - } + if (info.strLastLoginIp != strIp || !info.IsAuthorized()) + continue; + + info.tLastLoginHttpDate = time(nullptr); + m_pManager->MarkAsChanged(this); } } diff --git a/Server/mods/deathmatch/logic/CAccount.h b/Server/mods/deathmatch/logic/CAccount.h index ab5ed88eba..363dd57d98 100644 --- a/Server/mods/deathmatch/logic/CAccount.h +++ b/Server/mods/deathmatch/logic/CAccount.h @@ -71,27 +71,27 @@ class CAccount const std::string& strIP = "", const std::string& strSerial = "", const SString& strHttpPassAppend = ""); ~CAccount(); - bool IsRegistered() { return m_AccountType != EAccountType::Guest; } - bool IsConsoleAccount() { return m_AccountType == EAccountType::Console; } + bool IsRegistered() const { return m_AccountType != EAccountType::Guest; } + bool IsConsoleAccount() const { return m_AccountType == EAccountType::Console; } void OnLoginSuccess(const SString& strSerial, const SString& strIp); void OnLoginHttpSuccess(const SString& strIp); - const SString& GetName() { return m_strName; } + const SString& GetName() const { return m_strName; } void SetName(const std::string& strName); - EAccountType GetType() { return m_AccountType; } + const EAccountType GetType() const { return m_AccountType; } void SetPassword(const SString& strPassword); bool IsPassword(const SString& strPassword, bool* pbUsedHttpPassAppend = nullptr); SString GetPasswordHash(); - const SString& GetHttpPassAppend() { return m_strHttpPassAppend; } + const SString& GetHttpPassAppend() const { return m_strHttpPassAppend; } void SetHttpPassAppend(const SString& strHttpPassAppend); - const std::string& GetIP() { return m_strIP; } - const std::string& GetSerial() { return m_strSerial; } - int GetID() { return m_iUserID; } + const std::string& GetIP() const { return m_strIP; } + const std::string& GetSerial() const { return m_strSerial; } + const int GetID() const { return m_iUserID; } - bool HasLoadedSerialUsage(); + bool HasLoadedSerialUsage() const; void EnsureLoadedSerialUsage(); std::vector& GetSerialUsageList(); SSerialUsage* GetSerialUsage(const SString& strSerial); @@ -102,19 +102,19 @@ class CAccount bool RemoveSerial(const SString& strSerial); void RemoveUnauthorizedSerials(); - CClient* GetClient() { return m_pClient; } + CClient* GetClient() const { return m_pClient; } void SetClient(CClient* pClient); void SetChanged(bool bChanged) { m_bChanged = bChanged; } - bool HasChanged() { return m_bChanged; } + bool HasChanged() const { return m_bChanged; } uint GetScriptID() const { return m_uiScriptID; } std::shared_ptr GetData(const std::string& strKey); bool SetData(const std::string& strKey, const std::string& strValue, int iType); bool HasData(const std::string& strKey); void RemoveData(const std::string& strKey); - std::map::iterator DataBegin() { return m_Data.begin(); } - std::map::iterator DataEnd() { return m_Data.end(); } + std::map::iterator begin() { return m_Data.begin(); } + std::map::iterator end() { return m_Data.end(); } protected: CAccountData* GetDataPointer(const std::string& strKey); @@ -149,9 +149,9 @@ class CAccountData m_iType = iType; } - const std::string& GetKey() { return m_strKey; } - const std::string& GetStrValue() { return m_strValue; } - int GetType() { return m_iType; } + const std::string& GetKey() const { return m_strKey; } + const std::string& GetStrValue() const { return m_strValue; } + int GetType() const { return m_iType; } void SetStrValue(const std::string& strValue) { m_strValue = strValue; } void SetType(int iType) { m_iType = iType; } diff --git a/Server/mods/deathmatch/logic/CAccountManager.cpp b/Server/mods/deathmatch/logic/CAccountManager.cpp index 46a092c563..cae195a3a3 100644 --- a/Server/mods/deathmatch/logic/CAccountManager.cpp +++ b/Server/mods/deathmatch/logic/CAccountManager.cpp @@ -779,10 +779,9 @@ bool CAccountManager::CopyAccountData(CAccount* pFromAccount, CAccount* pToAccou if (!pFromAccount->IsRegistered()) // is not registered account, retrieve data from memory { - std::map::iterator iter = pFromAccount->DataBegin(); - for (; iter != pFromAccount->DataEnd(); iter++) + for (const auto& iter : *pFromAccount) { - MapSet(copiedData, iter->second.GetKey(), CAccountData(iter->second.GetKey(), iter->second.GetStrValue(), iter->second.GetType())); + MapSet(copiedData, iter.second.GetKey(), CAccountData(iter.second.GetKey(), iter.second.GetStrValue(), iter.second.GetType())); } } else // is registered account, retrieve from database @@ -851,31 +850,30 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) { if (!pAccount->IsRegistered()) { - std::map::iterator iter = pAccount->DataBegin(); - for (; iter != pAccount->DataEnd(); iter++) + for (const auto& iter : *pAccount) { - if (iter->second.GetType() == LUA_TNIL) + if (iter.second.GetType() == LUA_TNIL) { - lua_pushstring(pLua, iter->second.GetKey().c_str()); + lua_pushstring(pLua, iter.second.GetKey().c_str()); lua_pushnil(pLua); lua_settable(pLua, -3); } - if (iter->second.GetType() == LUA_TBOOLEAN) + if (iter.second.GetType() == LUA_TBOOLEAN) { - lua_pushstring(pLua, iter->second.GetKey().c_str()); - lua_pushboolean(pLua, iter->second.GetStrValue() == "true"); + lua_pushstring(pLua, iter.second.GetKey().c_str()); + lua_pushboolean(pLua, iter.second.GetStrValue() == "true"); lua_settable(pLua, -3); } - if (iter->second.GetType() == LUA_TNUMBER) + if (iter.second.GetType() == LUA_TNUMBER) { - lua_pushstring(pLua, iter->second.GetKey().c_str()); - lua_pushnumber(pLua, strtod(iter->second.GetStrValue().c_str(), NULL)); + lua_pushstring(pLua, iter.second.GetKey().c_str()); + lua_pushnumber(pLua, strtod(iter.second.GetStrValue().c_str(), NULL)); lua_settable(pLua, -3); } else { - lua_pushstring(pLua, iter->second.GetKey().c_str()); - lua_pushstring(pLua, iter->second.GetStrValue().c_str()); + lua_pushstring(pLua, iter.second.GetKey().c_str()); + lua_pushstring(pLua, iter.second.GetStrValue().c_str()); lua_settable(pLua, -3); } } @@ -896,7 +894,7 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) return false; // Loop through until i is the same as the number of rows - for (const auto& row : *result.operator->()) + for (const auto& row : result->Data) { // Get our key strKey = reinterpret_cast(row[0].pVal); @@ -938,7 +936,7 @@ void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector< CRegistryResult result; m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE serial = ?", SQLITE_TEXT, strSerial.c_str()); - for (const auto& row : *result.operator->()) + for (const auto& row : result->Data) { CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) @@ -952,7 +950,7 @@ void CAccountManager::GetAccountsByIP(const SString& strIP, std::vectorQueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE ip = ?", SQLITE_TEXT, strIP.c_str()); - for (const auto& row : *result.operator->()) + for (const auto& row : result->Data) { CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) @@ -965,7 +963,7 @@ CAccount* CAccountManager::GetAccountByID(int ID) CRegistryResult result; m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE id = ?", SQLITE_INTEGER, ID); - for (const auto& row : *result.operator->()) + for (const auto& row : result->Data) { return Get(reinterpret_cast(row[0].pVal)); } @@ -981,7 +979,7 @@ void CAccountManager::GetAccountsByData(const SString& dataName, const SString& "SELECT acc.name FROM accounts acc, userdata dat WHERE dat.key = ? AND dat.value = ? AND dat.userid = acc.id", SQLITE_TEXT, dataName.c_str(), SQLITE_TEXT, value.c_str()); - for (const auto& row : *result.operator->()) + for (const auto& row : result->Data) { CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) @@ -1174,7 +1172,7 @@ void CAccountManager::LoadAccountSerialUsage(CAccount* pAccount) " WHERE userid=?", SQLITE_INTEGER, pAccount->GetID()); - for (const auto& row : *result.operator->()) + for (const auto& row : result->Data) { outSerialUsageList.push_back(CAccount::SSerialUsage()); CAccount::SSerialUsage& info = outSerialUsageList.back(); From 67372ef0ff036753ccdce8d4a979b07382f785d5 Mon Sep 17 00:00:00 2001 From: Tracer <43095317+TracerDS@users.noreply.github.com> Date: Tue, 25 Jul 2023 13:03:39 +0200 Subject: [PATCH 5/6] Refactored internal SQL logic --- Server/dbconmy/CDatabaseConnectionMySql.cpp | 19 +--- .../mods/deathmatch/logic/CAccountManager.cpp | 71 +++++++-------- .../logic/CDatabaseConnectionSqlite.cpp | 28 +++--- .../logic/CPerfStat.BandwidthUsage.cpp | 20 ++-- Server/mods/deathmatch/logic/CRegistry.cpp | 33 ++++--- Server/mods/deathmatch/logic/CRegistry.h | 91 +++++++++++++------ .../deathmatch/logic/CResourceManager.cpp | 7 +- .../logic/luadefs/CLuaDatabaseDefs.cpp | 30 +++--- 8 files changed, 155 insertions(+), 144 deletions(-) diff --git a/Server/dbconmy/CDatabaseConnectionMySql.cpp b/Server/dbconmy/CDatabaseConnectionMySql.cpp index 1262e39c0a..a844645d7f 100644 --- a/Server/dbconmy/CDatabaseConnectionMySql.cpp +++ b/Server/dbconmy/CDatabaseConnectionMySql.cpp @@ -301,27 +301,16 @@ bool CDatabaseConnectionMySql::QueryInternal(const SString& strQuery, CRegistryR case SQLITE_NULL: break; case SQLITE_INTEGER: - cell.nVal = std::atoll(inData); + cell.swap(std::atoll(inData)); break; case SQLITE_FLOAT: - cell.fVal = (float)atof(inData); + cell.swap(0, static_cast(atof(inData))); break; case SQLITE_BLOB: - cell.nLength = inLength; - if (cell.nLength == 0) - { - cell.pVal = NULL; - } - else - { - cell.pVal = new unsigned char[cell.nLength]; - memcpy(cell.pVal, inData, cell.nLength); - } + cell.swap(0, 0, inData, inLength); break; default: - cell.nLength = inLength + 1; - cell.pVal = new unsigned char[cell.nLength]; - memcpy(cell.pVal, inData, cell.nLength); + cell.swap(0, 0, inData, inLength + 1); break; } } diff --git a/Server/mods/deathmatch/logic/CAccountManager.cpp b/Server/mods/deathmatch/logic/CAccountManager.cpp index cae195a3a3..042d1ab1c4 100644 --- a/Server/mods/deathmatch/logic/CAccountManager.cpp +++ b/Server/mods/deathmatch/logic/CAccountManager.cpp @@ -165,12 +165,12 @@ bool CAccountManager::Load() { const CRegistryResultRow& row = *iter; // Fill User ID, Name & Password (Required data) - int iUserID = static_cast(row[0].nVal); - SString strName = (const char*)row[1].pVal; - SString strPassword = (const char*)row[2].pVal; - SString strIP = (const char*)row[3].pVal; - SString strSerial = (const char*)row[4].pVal; - SString strHttpPassAppend = (const char*)row[5].pVal; + int iUserID = row[0].GetNumber(); + SString strName = row[1].GetString(); + SString strPassword = row[2].GetString(); + SString strIP = row[3].GetString(); + SString strSerial = row[4].GetString(); + SString strHttpPassAppend = row[5].GetString(); // Check for overlong names and incorrect escapement bool bRemoveAccount = false; @@ -330,7 +330,7 @@ bool CAccountManager::IntegrityCheck() { CRegistryResultCell& cell = result->Data.front()[0]; if (cell.nType == SQLITE_TEXT) - strResult = std::string((const char*)cell.pVal, cell.nLength - 1); + strResult = std::string(cell.GetString(), cell.nLength - 1); } // Process result @@ -378,7 +378,7 @@ bool CAccountManager::IntegrityCheck() { CRegistryResultCell& cell = result->Data.front()[0]; if (cell.nType == SQLITE_TEXT) - strResult = std::string((const char*)cell.pVal, cell.nLength - 1); + strResult = std::string(cell.GetString(), cell.nLength - 1); } // Process result @@ -698,8 +698,8 @@ std::shared_ptr CAccountManager::GetAccountData(CAccount* pAccount { const CRegistryResultRow& row = result->Data.front(); - const auto type = static_cast(row[1].nVal); - const auto value = (const char*)row[0].pVal; + const auto type = row[1].GetNumber(); + const auto value = row[0].GetString(); // Cache value for next get pAccount->SetData(szKey, value, type); @@ -799,14 +799,13 @@ bool CAccountManager::CopyAccountData(CAccount* pFromAccount, CAccount* pToAccou // Do we have any results? if (result->nRows > 0) { - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : result->Data) { - const CRegistryResultRow& row = *iter; // Get our key - strKey = (const char*)row[0].pVal; + strKey = row[0].GetString(); // Get our value - strValue = (const char*)row[1].pVal; - int iType = static_cast(row[2].nVal); + strValue = row[1].GetString(); + int iType = row[2].GetNumber(); MapSet(copiedData, strKey, CAccountData(strKey, strValue, iType)); } @@ -815,29 +814,27 @@ bool CAccountManager::CopyAccountData(CAccount* pFromAccount, CAccount* pToAccou if (copiedData.size() > 0) // got anything to copy? { - std::map::iterator iter = copiedData.begin(); - - for (; iter != copiedData.end(); iter++) + for (const auto& iter : copiedData) { if (!pToAccount->IsRegistered()) // store to memory { - pToAccount->SetData(iter->second.GetKey(), iter->second.GetStrValue(), iter->second.GetType()); + pToAccount->SetData(iter.second.GetKey(), iter.second.GetStrValue(), iter.second.GetType()); } else // store to database { CRegistryResult subResult; m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &subResult, "SELECT id,userid from userdata where userid=? and key=? LIMIT 1", - SQLITE_INTEGER, pToAccount->GetID(), SQLITE_TEXT, iter->second.GetKey().c_str()); + SQLITE_INTEGER, pToAccount->GetID(), SQLITE_TEXT, iter.second.GetKey().c_str()); // If there is a key with this value update it otherwise insert it and store the return value in bRetVal if (subResult->nRows > 0) m_pDatabaseManager->Execf(m_hDbConnection, "UPDATE userdata SET value=?, type=? WHERE userid=? AND key=?", SQLITE_TEXT, - iter->second.GetStrValue().c_str(), SQLITE_INTEGER, iter->second.GetType(), SQLITE_INTEGER, pToAccount->GetID(), - SQLITE_TEXT, iter->second.GetKey().c_str()); + iter.second.GetStrValue().c_str(), SQLITE_INTEGER, iter.second.GetType(), SQLITE_INTEGER, pToAccount->GetID(), + SQLITE_TEXT, iter.second.GetKey().c_str()); else m_pDatabaseManager->Execf(m_hDbConnection, "INSERT INTO userdata (userid, key, value, type) VALUES(?,?,?,?)", SQLITE_INTEGER, - pToAccount->GetID(), SQLITE_TEXT, iter->second.GetKey().c_str(), SQLITE_TEXT, iter->second.GetStrValue().c_str(), - SQLITE_INTEGER, iter->second.GetType()); + pToAccount->GetID(), SQLITE_TEXT, iter.second.GetKey().c_str(), SQLITE_TEXT, iter.second.GetStrValue().c_str(), + SQLITE_INTEGER, iter.second.GetType()); } } return true; @@ -897,9 +894,9 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) for (const auto& row : result->Data) { // Get our key - strKey = reinterpret_cast(row[0].pVal); + strKey = row[0].GetString(); // Get our type - int iType = static_cast(row[2].nVal); + int iType = row[2].GetNumber(); // Account data is stored as text so we don't need to check what type it is just return it if (iType == LUA_TNIL) { @@ -909,7 +906,7 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) } if (iType == LUA_TBOOLEAN) { - SString strResult = (const char*)row[1].pVal; + SString strResult = row[1].GetString(); lua_pushstring(pLua, strKey); lua_pushboolean(pLua, strResult == "true"); lua_settable(pLua, -3); @@ -917,13 +914,13 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) if (iType == LUA_TNUMBER) { lua_pushstring(pLua, strKey); - lua_pushnumber(pLua, strtod((const char*)row[1].pVal, NULL)); + lua_pushnumber(pLua, strtod(row[1].GetString(), NULL)); lua_settable(pLua, -3); } else { lua_pushstring(pLua, strKey); - lua_pushstring(pLua, ((const char*)row[1].pVal)); + lua_pushstring(pLua, (row[1].GetString())); lua_settable(pLua, -3); } } @@ -938,7 +935,7 @@ void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector< for (const auto& row : result->Data) { - CAccount* pAccount = Get((const char*)row[0].pVal); + CAccount* pAccount = Get(row[0].GetString()); if (pAccount) outAccounts.push_back(pAccount); } @@ -952,7 +949,7 @@ void CAccountManager::GetAccountsByIP(const SString& strIP, std::vectorData) { - CAccount* pAccount = Get((const char*)row[0].pVal); + CAccount* pAccount = Get(row[0].GetString()); if (pAccount) outAccounts.push_back(pAccount); } @@ -965,7 +962,7 @@ CAccount* CAccountManager::GetAccountByID(int ID) for (const auto& row : result->Data) { - return Get(reinterpret_cast(row[0].pVal)); + return Get(row[0].GetString()); } return nullptr; @@ -981,7 +978,7 @@ void CAccountManager::GetAccountsByData(const SString& dataName, const SString& for (const auto& row : result->Data) { - CAccount* pAccount = Get((const char*)row[0].pVal); + CAccount* pAccount = Get(row[0].GetString()); if (pAccount) outAccounts.push_back(pAccount); } @@ -1176,12 +1173,12 @@ void CAccountManager::LoadAccountSerialUsage(CAccount* pAccount) { outSerialUsageList.push_back(CAccount::SSerialUsage()); CAccount::SSerialUsage& info = outSerialUsageList.back(); - info.strSerial = (const char*)row[0].pVal; - info.strAddedIp = (const char*)row[1].pVal; + info.strSerial = row[0].GetString(); + info.strAddedIp = row[1].GetString(); info.tAddedDate = row[2].GetNumber(); - info.strAuthWho = (const char*)row[3].pVal; + info.strAuthWho = row[3].GetString(); info.tAuthDate = row[4].GetNumber(); - info.strLastLoginIp = (const char*)row[5].pVal; + info.strLastLoginIp = row[5].GetString(); info.tLastLoginDate = row[6].GetNumber(); info.tLastLoginHttpDate = row[7].GetNumber(); } diff --git a/Server/mods/deathmatch/logic/CDatabaseConnectionSqlite.cpp b/Server/mods/deathmatch/logic/CDatabaseConnectionSqlite.cpp index cc18c9bbe3..5e5cc84b4a 100644 --- a/Server/mods/deathmatch/logic/CDatabaseConnectionSqlite.cpp +++ b/Server/mods/deathmatch/logic/CDatabaseConnectionSqlite.cpp @@ -255,28 +255,26 @@ bool CDatabaseConnectionSqlite::QueryInternal(const SString& strQuery, CRegistry case SQLITE_NULL: break; case SQLITE_INTEGER: - cell.nVal = sqlite3_column_int64(pStmt, i); + cell.swap(sqlite3_column_int64(pStmt, i)); break; case SQLITE_FLOAT: - cell.fVal = (float)sqlite3_column_double(pStmt, i); + cell.swap(0, sqlite3_column_double(pStmt, i)); break; case SQLITE_BLOB: - cell.nLength = sqlite3_column_bytes(pStmt, i); - if (cell.nLength == 0) - { - cell.pVal = NULL; - } - else - { - cell.pVal = new unsigned char[cell.nLength]; - memcpy(cell.pVal, sqlite3_column_blob(pStmt, i), cell.nLength); - } + { + const auto inLength = sqlite3_column_bytes(pStmt, i); + const auto inData = reinterpret_cast(sqlite3_column_blob(pStmt, i)); + cell.swap(0, 0, inData, inLength); + break; + } default: - cell.nLength = sqlite3_column_bytes(pStmt, i) + 1; - cell.pVal = new unsigned char[cell.nLength]; - memcpy(cell.pVal, sqlite3_column_text(pStmt, i), cell.nLength); + { + const auto inLength = sqlite3_column_bytes(pStmt, i) + 1; + const auto inData = reinterpret_cast(sqlite3_column_text(pStmt, i)); + cell.swap(0, 0, inData, inLength); break; + } } } pResult->nRows++; diff --git a/Server/mods/deathmatch/logic/CPerfStat.BandwidthUsage.cpp b/Server/mods/deathmatch/logic/CPerfStat.BandwidthUsage.cpp index 8659a5534c..e72baff466 100644 --- a/Server/mods/deathmatch/logic/CPerfStat.BandwidthUsage.cpp +++ b/Server/mods/deathmatch/logic/CPerfStat.BandwidthUsage.cpp @@ -261,20 +261,20 @@ void CPerfStatBandwidthUsageImpl::LoadStats() if (result->nRows > 0 && result->nColumns >= 5) { - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : result->Data) { - const CRegistryResultRow& row = *iter; - SString strType = (const char*)row[0].pVal; - uint uiIndex = static_cast(row[1].nVal); - float GameRecv = std::max(0.f, row[2].fVal); - float GameSent = std::max(0.f, row[3].fVal); - float HttpSent = std::max(0.f, row[4].fVal); - float GameRecvBlocked = 0; + SString strType = row[0].GetString(); + uint uiIndex = row[1].GetNumber(); + float GameRecv = std::max(0.f, row[2].GetNumber()); + float GameSent = std::max(0.f, row[3].GetNumber()); + float HttpSent = std::max(0.f, row[4].GetNumber()); + float GameRecvBlocked = 0; + if (result->nColumns >= 6) - GameRecvBlocked = std::max(0.f, row[5].fVal); + GameRecvBlocked = std::max(0.f, row[5].GetNumber()); float GameResent = 0; if (result->nColumns >= 7) - GameResent = std::max(0.f, row[6].fVal); + GameResent = std::max(0.f, row[6].GetNumber()); uint uiType = BWStatNameToIndex(strType); diff --git a/Server/mods/deathmatch/logic/CRegistry.cpp b/Server/mods/deathmatch/logic/CRegistry.cpp index 04e7ac709c..0b8604bfe5 100644 --- a/Server/mods/deathmatch/logic/CRegistry.cpp +++ b/Server/mods/deathmatch/logic/CRegistry.cpp @@ -84,7 +84,7 @@ bool CRegistry::IntegrityCheck() { CRegistryResultCell& cell = result->Data.front()[0]; if (cell.nType == SQLITE_TEXT) - strResult = std::string((const char*)cell.pVal, cell.nLength - 1); + strResult = std::string(cell.GetString(), cell.nLength - 1); } // Process result @@ -114,7 +114,7 @@ bool CRegistry::IntegrityCheck() { CRegistryResultCell& cell = result->Data.front()[0]; if (cell.nType == SQLITE_TEXT) - strResult = std::string((const char*)cell.pVal, cell.nLength - 1); + strResult = std::string(cell.GetString(), cell.nLength - 1); } // Process result @@ -238,28 +238,27 @@ bool CRegistry::QueryInternal(const char* szQuery, CRegistryResult* ppResult) case SQLITE_NULL: break; case SQLITE_INTEGER: - cell.nVal = sqlite3_column_int(pStmt, i); + cell.swap(sqlite3_column_int(pStmt, i)); break; case SQLITE_FLOAT: - cell.fVal = (float)sqlite3_column_double(pStmt, i); + cell.swap(0, sqlite3_column_double(pStmt, i)); break; case SQLITE_BLOB: - cell.nLength = sqlite3_column_bytes(pStmt, i); - if (cell.nLength == 0) - { - cell.pVal = NULL; - } - else - { - cell.pVal = new unsigned char[cell.nLength]; - memcpy(cell.pVal, sqlite3_column_blob(pStmt, i), cell.nLength); - } + { + const auto inLength = sqlite3_column_bytes(pStmt, i); + const auto inData = reinterpret_cast( + sqlite3_column_blob(pStmt, i)); + cell.swap(0, 0, inData, inLength); break; + } default: - cell.nLength = sqlite3_column_bytes(pStmt, i) + 1; - cell.pVal = new unsigned char[cell.nLength]; - memcpy(cell.pVal, sqlite3_column_text(pStmt, i), cell.nLength); + { + const auto inLength = sqlite3_column_bytes(pStmt, i) + 1; + const auto inData = reinterpret_cast( + sqlite3_column_text(pStmt, i)); + cell.swap(0, 0, inData, inLength); break; + } } } pResult->nRows++; diff --git a/Server/mods/deathmatch/logic/CRegistry.h b/Server/mods/deathmatch/logic/CRegistry.h index 01cc353abe..a8b77d4e2b 100644 --- a/Server/mods/deathmatch/logic/CRegistry.h +++ b/Server/mods/deathmatch/logic/CRegistry.h @@ -42,7 +42,7 @@ class CRegistry bool Query(const char* szQuery, ...); bool Query(CRegistryResult* pResult, const char* szQuery, ...); - const SString& GetLastError() { return m_strLastErrorMessage; } + const SString& GetLastError() const { return m_strLastErrorMessage; } protected: bool SetLastErrorMessage(const std::string& strLastErrorMessage, const std::string& strQuery); @@ -71,41 +71,29 @@ struct CRegistryResultCell { nType = SQLITE_NULL; nLength = 0; - pVal = NULL; + value.pVal = NULL; } CRegistryResultCell(const CRegistryResultCell& cell) { - nType = cell.nType; - nLength = cell.nLength; - nVal = cell.nVal; - fVal = cell.fVal; - pVal = NULL; - if ((nType == SQLITE_BLOB || nType == SQLITE_TEXT) && cell.pVal && nLength > 0) + set(cell); + if ((nType == SQLITE_BLOB || nType == SQLITE_TEXT) && cell.value.pVal && nLength > 0) { - pVal = new unsigned char[nLength]; - memcpy(pVal, cell.pVal, nLength); + value.pVal = new uchar[nLength]; + memcpy(value.pVal, cell.value.pVal, nLength); } }; - ~CRegistryResultCell() - { - if (pVal) - delete[] pVal; - } + ~CRegistryResultCell() { SAFE_DELETE(value.pVal); } CRegistryResultCell& operator=(const CRegistryResultCell& cell) { - if (pVal) - delete[] pVal; + SAFE_DELETE(value.pVal); - nType = cell.nType; - nLength = cell.nLength; - nVal = cell.nVal; - fVal = cell.fVal; - pVal = NULL; - if ((nType == SQLITE_BLOB || nType == SQLITE_TEXT) && cell.pVal && nLength > 0) + set(cell); + + if ((nType == SQLITE_BLOB || nType == SQLITE_TEXT) && cell.value.pVal && nLength > 0) { - pVal = new unsigned char[nLength]; - memcpy(pVal, cell.pVal, nLength); + value.pVal = new uchar[nLength]; + memcpy(value.pVal, cell.value.pVal, nLength); } return *this; } @@ -120,18 +108,61 @@ struct CRegistryResultCell T GetNumber() const { if (nType == SQLITE_INTEGER) - return static_cast(nVal); + return static_cast(value.nVal); if (nType == SQLITE_FLOAT) - return static_cast(fVal); + return static_cast(value.fVal); return 0; } int nType; // Type identifier, SQLITE_* int nLength; // Length in bytes if nType == SQLITE_BLOB or SQLITE_TEXT // (includes zero terminator if TEXT) - long long int nVal; - float fVal; - unsigned char* pVal; + union + { + std::int64_t nVal; + float fVal; + uchar* pVal; + } value; + + void swap( + const std::int64_t nVal = 0, + const float fVal = 0, + const char* const pVal = 0, + const size_t length = 0 + ) noexcept { + if (nVal) + { + value.nVal = nVal; + value.fVal = 0; + value.pVal = 0; + } + else if (fVal) + { + value.nVal = 0; + value.fVal = fVal; + value.pVal = 0; + } + else if (pVal && length) + { + value.nVal = 0; + value.fVal = 0; + SAFE_DELETE(value.pVal); + value.pVal = new uchar[length]; + memcpy(value.pVal, reinterpret_cast(pVal), length); + } + } + const char* GetString() const noexcept { + return reinterpret_cast(value.pVal); + } + +private: + CRegistryResultCell& set(const CRegistryResultCell& cell) noexcept { + nType = cell.nType; + nLength = cell.nLength; + value.nVal = cell.value.nVal; + value.fVal = cell.value.fVal; + value.pVal = NULL; + } }; typedef std::vector CRegistryResultRow; diff --git a/Server/mods/deathmatch/logic/CResourceManager.cpp b/Server/mods/deathmatch/logic/CResourceManager.cpp index b3b2d2f9c1..08f1d7371a 100644 --- a/Server/mods/deathmatch/logic/CResourceManager.cpp +++ b/Server/mods/deathmatch/logic/CResourceManager.cpp @@ -1365,11 +1365,10 @@ void CResourceManager::LoadBlockedFileReasons() if (result->nRows > 0 && result->nColumns >= 2) { m_BlockedFileReasonMap.clear(); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : result->Data) { - const CRegistryResultRow& row = *iter; - SString strFileHash = (const char*)row[0].pVal; - SString strReason = (const char*)row[1].pVal; + SString strFileHash = row[0].GetString(); + SString strReason = row[1].GetString(); MapSet(m_BlockedFileReasonMap, strFileHash, strReason); } } diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaDatabaseDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaDatabaseDefs.cpp index bb5a1d1d16..7677356fde 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaDatabaseDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaDatabaseDefs.cpp @@ -515,9 +515,8 @@ void PushRegistryResultTable(lua_State* luaVM, const CRegistryResultData* Result { lua_newtable(luaVM); int i = 0; - for (CRegistryResultIterator iter = Result->begin(); iter != Result->end(); ++iter, ++i) + for (const auto& row : Result->Data) { - const CRegistryResultRow& row = *iter; lua_pushnumber(luaVM, i + 1); lua_newtable(luaVM); for (int j = 0; j < Result->nColumns; j++) @@ -529,16 +528,16 @@ void PushRegistryResultTable(lua_State* luaVM, const CRegistryResultData* Result switch (cell.nType) // push the value with the right type { case SQLITE_INTEGER: - lua_pushnumber(luaVM, static_cast(cell.nVal)); + lua_pushnumber(luaVM, cell.GetNumber()); break; case SQLITE_FLOAT: - lua_pushnumber(luaVM, cell.fVal); + lua_pushnumber(luaVM, cell.GetNumber()); break; case SQLITE_BLOB: - lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength); + lua_pushlstring(luaVM, cell.GetString(), cell.nLength); break; case SQLITE_TEXT: - lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength - 1); + lua_pushlstring(luaVM, cell.GetString(), cell.nLength - 1); break; default: lua_pushboolean(luaVM, false); @@ -683,9 +682,8 @@ int CLuaDatabaseDefs::ExecuteSQLQuery(lua_State* luaVM) { lua_newtable(luaVM); int i = 0; - for (CRegistryResultIterator iter = Result->begin(); iter != Result->end(); ++iter, ++i) + for (const auto& row : Result->Data) { - const CRegistryResultRow& row = *iter; // for ( int i = 0; i < Result.nRows; i++ ) { lua_newtable(luaVM); // new table lua_pushnumber(luaVM, i + 1); // row index number (starting at 1, not 0) @@ -702,16 +700,16 @@ int CLuaDatabaseDefs::ExecuteSQLQuery(lua_State* luaVM) switch (cell.nType) // push the value with the right type { case SQLITE_INTEGER: - lua_pushnumber(luaVM, static_cast(cell.nVal)); + lua_pushnumber(luaVM, cell.GetNumber()); break; case SQLITE_FLOAT: - lua_pushnumber(luaVM, cell.fVal); + lua_pushnumber(luaVM, cell.GetNumber()); break; case SQLITE_BLOB: - lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength); + lua_pushlstring(luaVM, cell.GetString(), cell.nLength); break; case SQLITE_TEXT: - lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength - 1); + lua_pushlstring(luaVM, cell.GetString(), cell.nLength - 1); break; default: lua_pushnil(luaVM); @@ -780,16 +778,16 @@ int CLuaDatabaseDefs::ExecuteSQLSelect(lua_State* luaVM) switch (cell.nType) // push the value with the right type { case SQLITE_INTEGER: - lua_pushnumber(luaVM, static_cast(cell.nVal)); + lua_pushnumber(luaVM, cell.GetNumber()); break; case SQLITE_FLOAT: - lua_pushnumber(luaVM, cell.fVal); + lua_pushnumber(luaVM, cell.GetNumber()); break; case SQLITE_BLOB: - lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength); + lua_pushlstring(luaVM, cell.GetString(), cell.nLength); break; case SQLITE_TEXT: - lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength - 1); + lua_pushlstring(luaVM, cell.GetString(), cell.nLength - 1); break; default: lua_pushnil(luaVM); From 4ad52f123564ab38547b187c9ec9ac9a96ef7f3f Mon Sep 17 00:00:00 2001 From: Tracer <43095317+TracerDS@users.noreply.github.com> Date: Tue, 25 Jul 2023 13:06:14 +0200 Subject: [PATCH 6/6] Revert "Refactored internal SQL logic" This reverts commit 67372ef0ff036753ccdce8d4a979b07382f785d5. --- Server/dbconmy/CDatabaseConnectionMySql.cpp | 19 +++- .../mods/deathmatch/logic/CAccountManager.cpp | 71 ++++++++------- .../logic/CDatabaseConnectionSqlite.cpp | 28 +++--- .../logic/CPerfStat.BandwidthUsage.cpp | 20 ++-- Server/mods/deathmatch/logic/CRegistry.cpp | 33 +++---- Server/mods/deathmatch/logic/CRegistry.h | 91 ++++++------------- .../deathmatch/logic/CResourceManager.cpp | 7 +- .../logic/luadefs/CLuaDatabaseDefs.cpp | 30 +++--- 8 files changed, 144 insertions(+), 155 deletions(-) diff --git a/Server/dbconmy/CDatabaseConnectionMySql.cpp b/Server/dbconmy/CDatabaseConnectionMySql.cpp index a844645d7f..1262e39c0a 100644 --- a/Server/dbconmy/CDatabaseConnectionMySql.cpp +++ b/Server/dbconmy/CDatabaseConnectionMySql.cpp @@ -301,16 +301,27 @@ bool CDatabaseConnectionMySql::QueryInternal(const SString& strQuery, CRegistryR case SQLITE_NULL: break; case SQLITE_INTEGER: - cell.swap(std::atoll(inData)); + cell.nVal = std::atoll(inData); break; case SQLITE_FLOAT: - cell.swap(0, static_cast(atof(inData))); + cell.fVal = (float)atof(inData); break; case SQLITE_BLOB: - cell.swap(0, 0, inData, inLength); + cell.nLength = inLength; + if (cell.nLength == 0) + { + cell.pVal = NULL; + } + else + { + cell.pVal = new unsigned char[cell.nLength]; + memcpy(cell.pVal, inData, cell.nLength); + } break; default: - cell.swap(0, 0, inData, inLength + 1); + cell.nLength = inLength + 1; + cell.pVal = new unsigned char[cell.nLength]; + memcpy(cell.pVal, inData, cell.nLength); break; } } diff --git a/Server/mods/deathmatch/logic/CAccountManager.cpp b/Server/mods/deathmatch/logic/CAccountManager.cpp index 042d1ab1c4..cae195a3a3 100644 --- a/Server/mods/deathmatch/logic/CAccountManager.cpp +++ b/Server/mods/deathmatch/logic/CAccountManager.cpp @@ -165,12 +165,12 @@ bool CAccountManager::Load() { const CRegistryResultRow& row = *iter; // Fill User ID, Name & Password (Required data) - int iUserID = row[0].GetNumber(); - SString strName = row[1].GetString(); - SString strPassword = row[2].GetString(); - SString strIP = row[3].GetString(); - SString strSerial = row[4].GetString(); - SString strHttpPassAppend = row[5].GetString(); + int iUserID = static_cast(row[0].nVal); + SString strName = (const char*)row[1].pVal; + SString strPassword = (const char*)row[2].pVal; + SString strIP = (const char*)row[3].pVal; + SString strSerial = (const char*)row[4].pVal; + SString strHttpPassAppend = (const char*)row[5].pVal; // Check for overlong names and incorrect escapement bool bRemoveAccount = false; @@ -330,7 +330,7 @@ bool CAccountManager::IntegrityCheck() { CRegistryResultCell& cell = result->Data.front()[0]; if (cell.nType == SQLITE_TEXT) - strResult = std::string(cell.GetString(), cell.nLength - 1); + strResult = std::string((const char*)cell.pVal, cell.nLength - 1); } // Process result @@ -378,7 +378,7 @@ bool CAccountManager::IntegrityCheck() { CRegistryResultCell& cell = result->Data.front()[0]; if (cell.nType == SQLITE_TEXT) - strResult = std::string(cell.GetString(), cell.nLength - 1); + strResult = std::string((const char*)cell.pVal, cell.nLength - 1); } // Process result @@ -698,8 +698,8 @@ std::shared_ptr CAccountManager::GetAccountData(CAccount* pAccount { const CRegistryResultRow& row = result->Data.front(); - const auto type = row[1].GetNumber(); - const auto value = row[0].GetString(); + const auto type = static_cast(row[1].nVal); + const auto value = (const char*)row[0].pVal; // Cache value for next get pAccount->SetData(szKey, value, type); @@ -799,13 +799,14 @@ bool CAccountManager::CopyAccountData(CAccount* pFromAccount, CAccount* pToAccou // Do we have any results? if (result->nRows > 0) { - for (const auto& row : result->Data) + for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) { + const CRegistryResultRow& row = *iter; // Get our key - strKey = row[0].GetString(); + strKey = (const char*)row[0].pVal; // Get our value - strValue = row[1].GetString(); - int iType = row[2].GetNumber(); + strValue = (const char*)row[1].pVal; + int iType = static_cast(row[2].nVal); MapSet(copiedData, strKey, CAccountData(strKey, strValue, iType)); } @@ -814,27 +815,29 @@ bool CAccountManager::CopyAccountData(CAccount* pFromAccount, CAccount* pToAccou if (copiedData.size() > 0) // got anything to copy? { - for (const auto& iter : copiedData) + std::map::iterator iter = copiedData.begin(); + + for (; iter != copiedData.end(); iter++) { if (!pToAccount->IsRegistered()) // store to memory { - pToAccount->SetData(iter.second.GetKey(), iter.second.GetStrValue(), iter.second.GetType()); + pToAccount->SetData(iter->second.GetKey(), iter->second.GetStrValue(), iter->second.GetType()); } else // store to database { CRegistryResult subResult; m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &subResult, "SELECT id,userid from userdata where userid=? and key=? LIMIT 1", - SQLITE_INTEGER, pToAccount->GetID(), SQLITE_TEXT, iter.second.GetKey().c_str()); + SQLITE_INTEGER, pToAccount->GetID(), SQLITE_TEXT, iter->second.GetKey().c_str()); // If there is a key with this value update it otherwise insert it and store the return value in bRetVal if (subResult->nRows > 0) m_pDatabaseManager->Execf(m_hDbConnection, "UPDATE userdata SET value=?, type=? WHERE userid=? AND key=?", SQLITE_TEXT, - iter.second.GetStrValue().c_str(), SQLITE_INTEGER, iter.second.GetType(), SQLITE_INTEGER, pToAccount->GetID(), - SQLITE_TEXT, iter.second.GetKey().c_str()); + iter->second.GetStrValue().c_str(), SQLITE_INTEGER, iter->second.GetType(), SQLITE_INTEGER, pToAccount->GetID(), + SQLITE_TEXT, iter->second.GetKey().c_str()); else m_pDatabaseManager->Execf(m_hDbConnection, "INSERT INTO userdata (userid, key, value, type) VALUES(?,?,?,?)", SQLITE_INTEGER, - pToAccount->GetID(), SQLITE_TEXT, iter.second.GetKey().c_str(), SQLITE_TEXT, iter.second.GetStrValue().c_str(), - SQLITE_INTEGER, iter.second.GetType()); + pToAccount->GetID(), SQLITE_TEXT, iter->second.GetKey().c_str(), SQLITE_TEXT, iter->second.GetStrValue().c_str(), + SQLITE_INTEGER, iter->second.GetType()); } } return true; @@ -894,9 +897,9 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) for (const auto& row : result->Data) { // Get our key - strKey = row[0].GetString(); + strKey = reinterpret_cast(row[0].pVal); // Get our type - int iType = row[2].GetNumber(); + int iType = static_cast(row[2].nVal); // Account data is stored as text so we don't need to check what type it is just return it if (iType == LUA_TNIL) { @@ -906,7 +909,7 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) } if (iType == LUA_TBOOLEAN) { - SString strResult = row[1].GetString(); + SString strResult = (const char*)row[1].pVal; lua_pushstring(pLua, strKey); lua_pushboolean(pLua, strResult == "true"); lua_settable(pLua, -3); @@ -914,13 +917,13 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) if (iType == LUA_TNUMBER) { lua_pushstring(pLua, strKey); - lua_pushnumber(pLua, strtod(row[1].GetString(), NULL)); + lua_pushnumber(pLua, strtod((const char*)row[1].pVal, NULL)); lua_settable(pLua, -3); } else { lua_pushstring(pLua, strKey); - lua_pushstring(pLua, (row[1].GetString())); + lua_pushstring(pLua, ((const char*)row[1].pVal)); lua_settable(pLua, -3); } } @@ -935,7 +938,7 @@ void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector< for (const auto& row : result->Data) { - CAccount* pAccount = Get(row[0].GetString()); + CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); } @@ -949,7 +952,7 @@ void CAccountManager::GetAccountsByIP(const SString& strIP, std::vectorData) { - CAccount* pAccount = Get(row[0].GetString()); + CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); } @@ -962,7 +965,7 @@ CAccount* CAccountManager::GetAccountByID(int ID) for (const auto& row : result->Data) { - return Get(row[0].GetString()); + return Get(reinterpret_cast(row[0].pVal)); } return nullptr; @@ -978,7 +981,7 @@ void CAccountManager::GetAccountsByData(const SString& dataName, const SString& for (const auto& row : result->Data) { - CAccount* pAccount = Get(row[0].GetString()); + CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); } @@ -1173,12 +1176,12 @@ void CAccountManager::LoadAccountSerialUsage(CAccount* pAccount) { outSerialUsageList.push_back(CAccount::SSerialUsage()); CAccount::SSerialUsage& info = outSerialUsageList.back(); - info.strSerial = row[0].GetString(); - info.strAddedIp = row[1].GetString(); + info.strSerial = (const char*)row[0].pVal; + info.strAddedIp = (const char*)row[1].pVal; info.tAddedDate = row[2].GetNumber(); - info.strAuthWho = row[3].GetString(); + info.strAuthWho = (const char*)row[3].pVal; info.tAuthDate = row[4].GetNumber(); - info.strLastLoginIp = row[5].GetString(); + info.strLastLoginIp = (const char*)row[5].pVal; info.tLastLoginDate = row[6].GetNumber(); info.tLastLoginHttpDate = row[7].GetNumber(); } diff --git a/Server/mods/deathmatch/logic/CDatabaseConnectionSqlite.cpp b/Server/mods/deathmatch/logic/CDatabaseConnectionSqlite.cpp index 5e5cc84b4a..cc18c9bbe3 100644 --- a/Server/mods/deathmatch/logic/CDatabaseConnectionSqlite.cpp +++ b/Server/mods/deathmatch/logic/CDatabaseConnectionSqlite.cpp @@ -255,26 +255,28 @@ bool CDatabaseConnectionSqlite::QueryInternal(const SString& strQuery, CRegistry case SQLITE_NULL: break; case SQLITE_INTEGER: - cell.swap(sqlite3_column_int64(pStmt, i)); + cell.nVal = sqlite3_column_int64(pStmt, i); break; case SQLITE_FLOAT: - cell.swap(0, sqlite3_column_double(pStmt, i)); + cell.fVal = (float)sqlite3_column_double(pStmt, i); break; case SQLITE_BLOB: - { - const auto inLength = sqlite3_column_bytes(pStmt, i); - const auto inData = reinterpret_cast(sqlite3_column_blob(pStmt, i)); - cell.swap(0, 0, inData, inLength); - + cell.nLength = sqlite3_column_bytes(pStmt, i); + if (cell.nLength == 0) + { + cell.pVal = NULL; + } + else + { + cell.pVal = new unsigned char[cell.nLength]; + memcpy(cell.pVal, sqlite3_column_blob(pStmt, i), cell.nLength); + } break; - } default: - { - const auto inLength = sqlite3_column_bytes(pStmt, i) + 1; - const auto inData = reinterpret_cast(sqlite3_column_text(pStmt, i)); - cell.swap(0, 0, inData, inLength); + cell.nLength = sqlite3_column_bytes(pStmt, i) + 1; + cell.pVal = new unsigned char[cell.nLength]; + memcpy(cell.pVal, sqlite3_column_text(pStmt, i), cell.nLength); break; - } } } pResult->nRows++; diff --git a/Server/mods/deathmatch/logic/CPerfStat.BandwidthUsage.cpp b/Server/mods/deathmatch/logic/CPerfStat.BandwidthUsage.cpp index e72baff466..8659a5534c 100644 --- a/Server/mods/deathmatch/logic/CPerfStat.BandwidthUsage.cpp +++ b/Server/mods/deathmatch/logic/CPerfStat.BandwidthUsage.cpp @@ -261,20 +261,20 @@ void CPerfStatBandwidthUsageImpl::LoadStats() if (result->nRows > 0 && result->nColumns >= 5) { - for (const auto& row : result->Data) + for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) { - SString strType = row[0].GetString(); - uint uiIndex = row[1].GetNumber(); - float GameRecv = std::max(0.f, row[2].GetNumber()); - float GameSent = std::max(0.f, row[3].GetNumber()); - float HttpSent = std::max(0.f, row[4].GetNumber()); - float GameRecvBlocked = 0; - + const CRegistryResultRow& row = *iter; + SString strType = (const char*)row[0].pVal; + uint uiIndex = static_cast(row[1].nVal); + float GameRecv = std::max(0.f, row[2].fVal); + float GameSent = std::max(0.f, row[3].fVal); + float HttpSent = std::max(0.f, row[4].fVal); + float GameRecvBlocked = 0; if (result->nColumns >= 6) - GameRecvBlocked = std::max(0.f, row[5].GetNumber()); + GameRecvBlocked = std::max(0.f, row[5].fVal); float GameResent = 0; if (result->nColumns >= 7) - GameResent = std::max(0.f, row[6].GetNumber()); + GameResent = std::max(0.f, row[6].fVal); uint uiType = BWStatNameToIndex(strType); diff --git a/Server/mods/deathmatch/logic/CRegistry.cpp b/Server/mods/deathmatch/logic/CRegistry.cpp index 0b8604bfe5..04e7ac709c 100644 --- a/Server/mods/deathmatch/logic/CRegistry.cpp +++ b/Server/mods/deathmatch/logic/CRegistry.cpp @@ -84,7 +84,7 @@ bool CRegistry::IntegrityCheck() { CRegistryResultCell& cell = result->Data.front()[0]; if (cell.nType == SQLITE_TEXT) - strResult = std::string(cell.GetString(), cell.nLength - 1); + strResult = std::string((const char*)cell.pVal, cell.nLength - 1); } // Process result @@ -114,7 +114,7 @@ bool CRegistry::IntegrityCheck() { CRegistryResultCell& cell = result->Data.front()[0]; if (cell.nType == SQLITE_TEXT) - strResult = std::string(cell.GetString(), cell.nLength - 1); + strResult = std::string((const char*)cell.pVal, cell.nLength - 1); } // Process result @@ -238,27 +238,28 @@ bool CRegistry::QueryInternal(const char* szQuery, CRegistryResult* ppResult) case SQLITE_NULL: break; case SQLITE_INTEGER: - cell.swap(sqlite3_column_int(pStmt, i)); + cell.nVal = sqlite3_column_int(pStmt, i); break; case SQLITE_FLOAT: - cell.swap(0, sqlite3_column_double(pStmt, i)); + cell.fVal = (float)sqlite3_column_double(pStmt, i); break; case SQLITE_BLOB: - { - const auto inLength = sqlite3_column_bytes(pStmt, i); - const auto inData = reinterpret_cast( - sqlite3_column_blob(pStmt, i)); - cell.swap(0, 0, inData, inLength); + cell.nLength = sqlite3_column_bytes(pStmt, i); + if (cell.nLength == 0) + { + cell.pVal = NULL; + } + else + { + cell.pVal = new unsigned char[cell.nLength]; + memcpy(cell.pVal, sqlite3_column_blob(pStmt, i), cell.nLength); + } break; - } default: - { - const auto inLength = sqlite3_column_bytes(pStmt, i) + 1; - const auto inData = reinterpret_cast( - sqlite3_column_text(pStmt, i)); - cell.swap(0, 0, inData, inLength); + cell.nLength = sqlite3_column_bytes(pStmt, i) + 1; + cell.pVal = new unsigned char[cell.nLength]; + memcpy(cell.pVal, sqlite3_column_text(pStmt, i), cell.nLength); break; - } } } pResult->nRows++; diff --git a/Server/mods/deathmatch/logic/CRegistry.h b/Server/mods/deathmatch/logic/CRegistry.h index a8b77d4e2b..01cc353abe 100644 --- a/Server/mods/deathmatch/logic/CRegistry.h +++ b/Server/mods/deathmatch/logic/CRegistry.h @@ -42,7 +42,7 @@ class CRegistry bool Query(const char* szQuery, ...); bool Query(CRegistryResult* pResult, const char* szQuery, ...); - const SString& GetLastError() const { return m_strLastErrorMessage; } + const SString& GetLastError() { return m_strLastErrorMessage; } protected: bool SetLastErrorMessage(const std::string& strLastErrorMessage, const std::string& strQuery); @@ -71,29 +71,41 @@ struct CRegistryResultCell { nType = SQLITE_NULL; nLength = 0; - value.pVal = NULL; + pVal = NULL; } CRegistryResultCell(const CRegistryResultCell& cell) { - set(cell); - if ((nType == SQLITE_BLOB || nType == SQLITE_TEXT) && cell.value.pVal && nLength > 0) + nType = cell.nType; + nLength = cell.nLength; + nVal = cell.nVal; + fVal = cell.fVal; + pVal = NULL; + if ((nType == SQLITE_BLOB || nType == SQLITE_TEXT) && cell.pVal && nLength > 0) { - value.pVal = new uchar[nLength]; - memcpy(value.pVal, cell.value.pVal, nLength); + pVal = new unsigned char[nLength]; + memcpy(pVal, cell.pVal, nLength); } }; - ~CRegistryResultCell() { SAFE_DELETE(value.pVal); } + ~CRegistryResultCell() + { + if (pVal) + delete[] pVal; + } CRegistryResultCell& operator=(const CRegistryResultCell& cell) { - SAFE_DELETE(value.pVal); - - set(cell); + if (pVal) + delete[] pVal; - if ((nType == SQLITE_BLOB || nType == SQLITE_TEXT) && cell.value.pVal && nLength > 0) + nType = cell.nType; + nLength = cell.nLength; + nVal = cell.nVal; + fVal = cell.fVal; + pVal = NULL; + if ((nType == SQLITE_BLOB || nType == SQLITE_TEXT) && cell.pVal && nLength > 0) { - value.pVal = new uchar[nLength]; - memcpy(value.pVal, cell.value.pVal, nLength); + pVal = new unsigned char[nLength]; + memcpy(pVal, cell.pVal, nLength); } return *this; } @@ -108,61 +120,18 @@ struct CRegistryResultCell T GetNumber() const { if (nType == SQLITE_INTEGER) - return static_cast(value.nVal); + return static_cast(nVal); if (nType == SQLITE_FLOAT) - return static_cast(value.fVal); + return static_cast(fVal); return 0; } int nType; // Type identifier, SQLITE_* int nLength; // Length in bytes if nType == SQLITE_BLOB or SQLITE_TEXT // (includes zero terminator if TEXT) - union - { - std::int64_t nVal; - float fVal; - uchar* pVal; - } value; - - void swap( - const std::int64_t nVal = 0, - const float fVal = 0, - const char* const pVal = 0, - const size_t length = 0 - ) noexcept { - if (nVal) - { - value.nVal = nVal; - value.fVal = 0; - value.pVal = 0; - } - else if (fVal) - { - value.nVal = 0; - value.fVal = fVal; - value.pVal = 0; - } - else if (pVal && length) - { - value.nVal = 0; - value.fVal = 0; - SAFE_DELETE(value.pVal); - value.pVal = new uchar[length]; - memcpy(value.pVal, reinterpret_cast(pVal), length); - } - } - const char* GetString() const noexcept { - return reinterpret_cast(value.pVal); - } - -private: - CRegistryResultCell& set(const CRegistryResultCell& cell) noexcept { - nType = cell.nType; - nLength = cell.nLength; - value.nVal = cell.value.nVal; - value.fVal = cell.value.fVal; - value.pVal = NULL; - } + long long int nVal; + float fVal; + unsigned char* pVal; }; typedef std::vector CRegistryResultRow; diff --git a/Server/mods/deathmatch/logic/CResourceManager.cpp b/Server/mods/deathmatch/logic/CResourceManager.cpp index 08f1d7371a..b3b2d2f9c1 100644 --- a/Server/mods/deathmatch/logic/CResourceManager.cpp +++ b/Server/mods/deathmatch/logic/CResourceManager.cpp @@ -1365,10 +1365,11 @@ void CResourceManager::LoadBlockedFileReasons() if (result->nRows > 0 && result->nColumns >= 2) { m_BlockedFileReasonMap.clear(); - for (const auto& row : result->Data) + for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) { - SString strFileHash = row[0].GetString(); - SString strReason = row[1].GetString(); + const CRegistryResultRow& row = *iter; + SString strFileHash = (const char*)row[0].pVal; + SString strReason = (const char*)row[1].pVal; MapSet(m_BlockedFileReasonMap, strFileHash, strReason); } } diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaDatabaseDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaDatabaseDefs.cpp index 7677356fde..bb5a1d1d16 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaDatabaseDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaDatabaseDefs.cpp @@ -515,8 +515,9 @@ void PushRegistryResultTable(lua_State* luaVM, const CRegistryResultData* Result { lua_newtable(luaVM); int i = 0; - for (const auto& row : Result->Data) + for (CRegistryResultIterator iter = Result->begin(); iter != Result->end(); ++iter, ++i) { + const CRegistryResultRow& row = *iter; lua_pushnumber(luaVM, i + 1); lua_newtable(luaVM); for (int j = 0; j < Result->nColumns; j++) @@ -528,16 +529,16 @@ void PushRegistryResultTable(lua_State* luaVM, const CRegistryResultData* Result switch (cell.nType) // push the value with the right type { case SQLITE_INTEGER: - lua_pushnumber(luaVM, cell.GetNumber()); + lua_pushnumber(luaVM, static_cast(cell.nVal)); break; case SQLITE_FLOAT: - lua_pushnumber(luaVM, cell.GetNumber()); + lua_pushnumber(luaVM, cell.fVal); break; case SQLITE_BLOB: - lua_pushlstring(luaVM, cell.GetString(), cell.nLength); + lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength); break; case SQLITE_TEXT: - lua_pushlstring(luaVM, cell.GetString(), cell.nLength - 1); + lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength - 1); break; default: lua_pushboolean(luaVM, false); @@ -682,8 +683,9 @@ int CLuaDatabaseDefs::ExecuteSQLQuery(lua_State* luaVM) { lua_newtable(luaVM); int i = 0; - for (const auto& row : Result->Data) + for (CRegistryResultIterator iter = Result->begin(); iter != Result->end(); ++iter, ++i) { + const CRegistryResultRow& row = *iter; // for ( int i = 0; i < Result.nRows; i++ ) { lua_newtable(luaVM); // new table lua_pushnumber(luaVM, i + 1); // row index number (starting at 1, not 0) @@ -700,16 +702,16 @@ int CLuaDatabaseDefs::ExecuteSQLQuery(lua_State* luaVM) switch (cell.nType) // push the value with the right type { case SQLITE_INTEGER: - lua_pushnumber(luaVM, cell.GetNumber()); + lua_pushnumber(luaVM, static_cast(cell.nVal)); break; case SQLITE_FLOAT: - lua_pushnumber(luaVM, cell.GetNumber()); + lua_pushnumber(luaVM, cell.fVal); break; case SQLITE_BLOB: - lua_pushlstring(luaVM, cell.GetString(), cell.nLength); + lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength); break; case SQLITE_TEXT: - lua_pushlstring(luaVM, cell.GetString(), cell.nLength - 1); + lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength - 1); break; default: lua_pushnil(luaVM); @@ -778,16 +780,16 @@ int CLuaDatabaseDefs::ExecuteSQLSelect(lua_State* luaVM) switch (cell.nType) // push the value with the right type { case SQLITE_INTEGER: - lua_pushnumber(luaVM, cell.GetNumber()); + lua_pushnumber(luaVM, static_cast(cell.nVal)); break; case SQLITE_FLOAT: - lua_pushnumber(luaVM, cell.GetNumber()); + lua_pushnumber(luaVM, cell.fVal); break; case SQLITE_BLOB: - lua_pushlstring(luaVM, cell.GetString(), cell.nLength); + lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength); break; case SQLITE_TEXT: - lua_pushlstring(luaVM, cell.GetString(), cell.nLength - 1); + lua_pushlstring(luaVM, (const char*)cell.pVal, cell.nLength - 1); break; default: lua_pushnil(luaVM);