From 007336fedba444801696abb04c58060036d1141f Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sun, 3 Nov 2024 15:42:27 +0300 Subject: [PATCH 1/7] First iteration --- Server/mods/deathmatch/logic/CCustomData.cpp | 15 ++++++++++++++- Server/mods/deathmatch/logic/CCustomData.h | 5 ++++- Server/mods/deathmatch/logic/CElement.cpp | 8 ++++++-- Server/mods/deathmatch/logic/CElement.h | 2 +- Server/mods/deathmatch/logic/CGame.cpp | 18 +++++++++++++++++- .../logic/luadefs/CLuaElementDefs.cpp | 14 ++++++++++++++ .../deathmatch/logic/luadefs/CLuaElementDefs.h | 2 ++ 7 files changed, 58 insertions(+), 6 deletions(-) diff --git a/Server/mods/deathmatch/logic/CCustomData.cpp b/Server/mods/deathmatch/logic/CCustomData.cpp index f18bbd37d19..955c71fc378 100644 --- a/Server/mods/deathmatch/logic/CCustomData.cpp +++ b/Server/mods/deathmatch/logic/CCustomData.cpp @@ -21,7 +21,7 @@ void CCustomData::Copy(CCustomData* pCustomData) } } -SCustomData* CCustomData::Get(const char* szName) +SCustomData* CCustomData::Get(const char* szName) const { assert(szName); @@ -100,6 +100,7 @@ void CCustomData::Set(const char* szName, const CLuaArgument& Variable, ESyncTyp SCustomData newData; newData.Variable = Variable; newData.syncType = syncType; + newData.allowClientChanges = true; m_Data[szName] = newData; UpdateSynced(szName, Variable, syncType); } @@ -120,6 +121,18 @@ bool CCustomData::Delete(const char* szName) return false; } +bool CCustomData::IsClientChangesAllowed(const char* szName) const +{ + SCustomData* pData = Get(szName); + return pData ? pData->allowClientChanges : true; +} + +void CCustomData::SetClientChangesAllowed(const char* szName, bool enabled) +{ + SCustomData& pData = m_Data[szName]; + pData.allowClientChanges = enabled; +} + CXMLNode* CCustomData::OutputToXML(CXMLNode* pNode) { std::map::const_iterator iter = m_Data.begin(); diff --git a/Server/mods/deathmatch/logic/CCustomData.h b/Server/mods/deathmatch/logic/CCustomData.h index bfb17ff5290..e97d2554f98 100644 --- a/Server/mods/deathmatch/logic/CCustomData.h +++ b/Server/mods/deathmatch/logic/CCustomData.h @@ -29,6 +29,7 @@ struct SCustomData { CLuaArgument Variable; ESyncType syncType; + bool allowClientChanges; }; class CCustomData @@ -36,11 +37,13 @@ class CCustomData public: void Copy(CCustomData* pCustomData); - SCustomData* Get(const char* szName); + SCustomData* Get(const char* szName) const; SCustomData* GetSynced(const char* szName); void Set(const char* szName, const CLuaArgument& Variable, ESyncType syncType = ESyncType::BROADCAST); bool Delete(const char* szName); + bool IsClientChangesAllowed(const char* szName) const; + void SetClientChangesAllowed(const char* szName, bool enabled); unsigned short CountOnlySynchronized(); diff --git a/Server/mods/deathmatch/logic/CElement.cpp b/Server/mods/deathmatch/logic/CElement.cpp index 59086a2f143..6134d965c2e 100644 --- a/Server/mods/deathmatch/logic/CElement.cpp +++ b/Server/mods/deathmatch/logic/CElement.cpp @@ -508,7 +508,7 @@ void CElement::ReadCustomData(CEvents* pEvents, CXMLNode& Node) } } -CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType) +CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType, bool* clientChangesAllowed) { assert(szName); @@ -518,13 +518,17 @@ CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESy { if (pSyncType) *pSyncType = pData->syncType; + + if (clientChangesAllowed) + *clientChangesAllowed = pData->allowClientChanges; + return &pData->Variable; } // If none, try returning parent's custom data if (bInheritData && m_pParent) { - return m_pParent->GetCustomData(szName, true, pSyncType); + return m_pParent->GetCustomData(szName, true, pSyncType, clientChangesAllowed); } // None available diff --git a/Server/mods/deathmatch/logic/CElement.h b/Server/mods/deathmatch/logic/CElement.h index e3a0fa4d070..801071ab699 100644 --- a/Server/mods/deathmatch/logic/CElement.h +++ b/Server/mods/deathmatch/logic/CElement.h @@ -136,7 +136,7 @@ class CElement void ReadCustomData(CEvents* pEvents, CXMLNode& Node); CCustomData& GetCustomDataManager() { return m_CustomData; } - CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = NULL); + CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = nullptr, bool* clientChangesAllowed = nullptr); CLuaArguments* GetAllCustomData(CLuaArguments* table); bool GetCustomDataString(const char* szName, char* pOut, size_t sizeBuffer, bool bInheritData); bool GetCustomDataInt(const char* szName, int& iOut, bool bInheritData); diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index d4efea393f4..53bdba5456b 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -1607,6 +1607,7 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onPlayerTriggerEventThreshold", "", nullptr, false); m_Events.AddEvent("onPlayerTeamChange", "oldTeam, newTeam", nullptr, false); m_Events.AddEvent("onPlayerTriggerInvalidEvent", "eventName, isAdded, isRemote", nullptr, false); + m_Events.AddEvent("onPlayerChangesProtectedData", "element, key, value", nullptr, false); // Ped events m_Events.AddEvent("onPedVehicleEnter", "vehicle, seat, jacked", NULL, false); @@ -2652,7 +2653,22 @@ void CGame::Packet_CustomData(CCustomDataPacket& Packet) } ESyncType lastSyncType = ESyncType::BROADCAST; - pElement->GetCustomData(szName, false, &lastSyncType); + bool clientChangesAllowed = true; + + pElement->GetCustomData(szName, false, &lastSyncType, &clientChangesAllowed); + + if (!clientChangesAllowed) + { + CLogger::ErrorPrintf("Client trying to change protected element data %s (%s)", Packet.GetSourcePlayer()->GetNick(), + szName); + + CLuaArguments arguments; + arguments.PushElement(pElement); + arguments.PushString(szName); + arguments.PushArgument(Value); + pSourcePlayer->CallEvent("onPlayerChangesProtectedData", arguments); + return; + } if (lastSyncType != ESyncType::LOCAL) { diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index 6cacbdcc989..3e8b5656945 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -80,6 +80,8 @@ void CLuaElementDefs::LoadFunctions() {"addElementDataSubscriber", addElementDataSubscriber}, {"removeElementDataSubscriber", removeElementDataSubscriber}, {"hasElementDataSubscriber", hasElementDataSubscriber}, + {"setElementDataClientTrustEnabled", ArgumentParser}, + {"isElementDataClientTrustEnabled", ArgumentParser}, // Set {"setElementID", setElementID}, @@ -151,6 +153,7 @@ void CLuaElementDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "setLowLOD", "setLowLODElement"); lua_classfunction(luaVM, "setAttachedOffsets", "setElementAttachedOffsets"); lua_classfunction(luaVM, "setCallPropagationEnabled", "setElementCallPropagationEnabled"); + lua_classfunction(luaVM, "setDataClientTrustEnabled", "setElementDataClientTrustEnabled"); lua_classfunction(luaVM, "getAttachedOffsets", "getElementAttachedOffsets"); lua_classfunction(luaVM, "getChild", "getElementChild"); @@ -189,6 +192,7 @@ void CLuaElementDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "isVisibleTo", "isElementVisibleTo"); lua_classfunction(luaVM, "isLowLOD", "isElementLowLOD"); lua_classfunction(luaVM, "isAttached", "isElementAttached"); + lua_classfunction(luaVM, "isDataClientTrustEnabled", "isElementDataClientTrustEnabled"); lua_classvariable(luaVM, "id", "setElementID", "getElementID"); lua_classvariable(luaVM, "callPropagationEnabled", "setElementCallPropagationEnabled", "isElementCallPropagationEnabled"); @@ -2437,3 +2441,13 @@ int CLuaElementDefs::isElementCallPropagationEnabled(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +void CLuaElementDefs::SetElementDataClientTrustEnabled(CElement* pElement, std::string_view key, bool enabled) +{ + pElement->GetCustomDataManager().SetClientChangesAllowed(key.data(), enabled); +} + +bool CLuaElementDefs::IsElementDataClientTrustEnabled(CElement* pElement, std::string_view key) +{ + return pElement->GetCustomDataManager().IsClientChangesAllowed(key.data()); +} diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h index b58f613b596..77449f2f391 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h @@ -77,6 +77,8 @@ class CLuaElementDefs : public CLuaDefs LUA_DECLARE(addElementDataSubscriber); LUA_DECLARE(removeElementDataSubscriber); LUA_DECLARE(hasElementDataSubscriber); + static void SetElementDataClientTrustEnabled(CElement* pElement, std::string_view key, bool enabled); + static bool IsElementDataClientTrustEnabled(CElement* pElement, std::string_view key); // Attachement LUA_DECLARE(attachElements); From 06e4c82ebd2955c8e6dc83e7b0b5528da427f66e Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sun, 3 Nov 2024 16:26:59 +0300 Subject: [PATCH 2/7] Allow changes for all element data --- Server/mods/deathmatch/logic/CCustomData.cpp | 11 ++++--- Server/mods/deathmatch/logic/CCustomData.h | 20 +++++++++--- Server/mods/deathmatch/logic/CElement.cpp | 8 ++--- Server/mods/deathmatch/logic/CElement.h | 2 +- Server/mods/deathmatch/logic/CGame.cpp | 8 +++-- .../logic/luadefs/CLuaElementDefs.cpp | 32 ++++++++++++++----- .../logic/luadefs/CLuaElementDefs.h | 5 +-- 7 files changed, 60 insertions(+), 26 deletions(-) diff --git a/Server/mods/deathmatch/logic/CCustomData.cpp b/Server/mods/deathmatch/logic/CCustomData.cpp index 955c71fc378..12563e04dda 100644 --- a/Server/mods/deathmatch/logic/CCustomData.cpp +++ b/Server/mods/deathmatch/logic/CCustomData.cpp @@ -100,7 +100,7 @@ void CCustomData::Set(const char* szName, const CLuaArgument& Variable, ESyncTyp SCustomData newData; newData.Variable = Variable; newData.syncType = syncType; - newData.allowClientChanges = true; + newData.clientChangesMode = ECustomDataClientTrust::UNSET; m_Data[szName] = newData; UpdateSynced(szName, Variable, syncType); } @@ -124,13 +124,16 @@ bool CCustomData::Delete(const char* szName) bool CCustomData::IsClientChangesAllowed(const char* szName) const { SCustomData* pData = Get(szName); - return pData ? pData->allowClientChanges : true; + if (!pData || pData->clientChangesMode == ECustomDataClientTrust::UNSET) + return IsClientChangesAllowed(); + + return pData->clientChangesMode == ECustomDataClientTrust::ALLOW; } -void CCustomData::SetClientChangesAllowed(const char* szName, bool enabled) +void CCustomData::SetClientChangesMode(const char* szName, ECustomDataClientTrust mode) { SCustomData& pData = m_Data[szName]; - pData.allowClientChanges = enabled; + pData.clientChangesMode = mode; } CXMLNode* CCustomData::OutputToXML(CXMLNode* pNode) diff --git a/Server/mods/deathmatch/logic/CCustomData.h b/Server/mods/deathmatch/logic/CCustomData.h index e97d2554f98..b22674e580d 100644 --- a/Server/mods/deathmatch/logic/CCustomData.h +++ b/Server/mods/deathmatch/logic/CCustomData.h @@ -25,11 +25,18 @@ enum class ESyncType SUBSCRIBE, }; +enum class ECustomDataClientTrust : std::uint8_t +{ + UNSET, + ALLOW, + DENY, +}; + struct SCustomData { - CLuaArgument Variable; - ESyncType syncType; - bool allowClientChanges; + CLuaArgument Variable; + ESyncType syncType; + ECustomDataClientTrust clientChangesMode; }; class CCustomData @@ -42,8 +49,12 @@ class CCustomData void Set(const char* szName, const CLuaArgument& Variable, ESyncType syncType = ESyncType::BROADCAST); bool Delete(const char* szName); + bool IsClientChangesAllowed(const char* szName) const; - void SetClientChangesAllowed(const char* szName, bool enabled); + void SetClientChangesMode(const char* szName, ECustomDataClientTrust mode); + + bool IsClientChangesAllowed() const noexcept { return m_clientChangesAllowed; }; + void SetClientChangesAllowed(bool enabled) noexcept { m_clientChangesAllowed = enabled; }; unsigned short CountOnlySynchronized(); @@ -61,4 +72,5 @@ class CCustomData std::map m_Data; std::map m_SyncedData; + bool m_clientChangesAllowed{true}; }; diff --git a/Server/mods/deathmatch/logic/CElement.cpp b/Server/mods/deathmatch/logic/CElement.cpp index 6134d965c2e..f98cf3f38e1 100644 --- a/Server/mods/deathmatch/logic/CElement.cpp +++ b/Server/mods/deathmatch/logic/CElement.cpp @@ -508,7 +508,7 @@ void CElement::ReadCustomData(CEvents* pEvents, CXMLNode& Node) } } -CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType, bool* clientChangesAllowed) +CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType, ECustomDataClientTrust* clientChangesMode) { assert(szName); @@ -519,8 +519,8 @@ CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESy if (pSyncType) *pSyncType = pData->syncType; - if (clientChangesAllowed) - *clientChangesAllowed = pData->allowClientChanges; + if (clientChangesMode) + *clientChangesMode = pData->clientChangesMode; return &pData->Variable; } @@ -528,7 +528,7 @@ CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESy // If none, try returning parent's custom data if (bInheritData && m_pParent) { - return m_pParent->GetCustomData(szName, true, pSyncType, clientChangesAllowed); + return m_pParent->GetCustomData(szName, true, pSyncType, clientChangesMode); } // None available diff --git a/Server/mods/deathmatch/logic/CElement.h b/Server/mods/deathmatch/logic/CElement.h index 801071ab699..9f25ab1001d 100644 --- a/Server/mods/deathmatch/logic/CElement.h +++ b/Server/mods/deathmatch/logic/CElement.h @@ -136,7 +136,7 @@ class CElement void ReadCustomData(CEvents* pEvents, CXMLNode& Node); CCustomData& GetCustomDataManager() { return m_CustomData; } - CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = nullptr, bool* clientChangesAllowed = nullptr); + CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = nullptr, ECustomDataClientTrust* clientChangesMode = nullptr); CLuaArguments* GetAllCustomData(CLuaArguments* table); bool GetCustomDataString(const char* szName, char* pOut, size_t sizeBuffer, bool bInheritData); bool GetCustomDataInt(const char* szName, int& iOut, bool bInheritData); diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 53bdba5456b..324d2ed2773 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -2653,11 +2653,13 @@ void CGame::Packet_CustomData(CCustomDataPacket& Packet) } ESyncType lastSyncType = ESyncType::BROADCAST; - bool clientChangesAllowed = true; + ECustomDataClientTrust clientChangesMode{}; - pElement->GetCustomData(szName, false, &lastSyncType, &clientChangesAllowed); + pElement->GetCustomData(szName, false, &lastSyncType, &clientChangesMode); - if (!clientChangesAllowed) + const bool changesAllowed = clientChangesMode == ECustomDataClientTrust::UNSET ? pElement->GetCustomDataManager().IsClientChangesAllowed() + : clientChangesMode == ECustomDataClientTrust::ALLOW; + if (!changesAllowed) { CLogger::ErrorPrintf("Client trying to change protected element data %s (%s)", Packet.GetSourcePlayer()->GetNick(), szName); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index 3e8b5656945..673edc97639 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -80,8 +80,9 @@ void CLuaElementDefs::LoadFunctions() {"addElementDataSubscriber", addElementDataSubscriber}, {"removeElementDataSubscriber", removeElementDataSubscriber}, {"hasElementDataSubscriber", hasElementDataSubscriber}, - {"setElementDataClientTrustEnabled", ArgumentParser}, - {"isElementDataClientTrustEnabled", ArgumentParser}, + {"setElementDataClientTrust", ArgumentParser}, + {"isElementDataClientTrusted", ArgumentParser}, + {"resetElementDataClientTrust", ArgumentParser}, // Set {"setElementID", setElementID}, @@ -131,6 +132,7 @@ void CLuaElementDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "addDataSubscriber", "addElementDataSubscriber"); lua_classfunction(luaVM, "removeDataSubscriber", "removeElementDataSubscriber"); lua_classfunction(luaVM, "hasDataSubscriber", "hasElementDataSubscriber"); + lua_classfunction(luaVM, "resetDataClientTrust", "resetElementDataClientTrust"); lua_classfunction(luaVM, "setParent", "setElementParent"); lua_classfunction(luaVM, "setFrozen", "setElementFrozen"); @@ -153,7 +155,7 @@ void CLuaElementDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "setLowLOD", "setLowLODElement"); lua_classfunction(luaVM, "setAttachedOffsets", "setElementAttachedOffsets"); lua_classfunction(luaVM, "setCallPropagationEnabled", "setElementCallPropagationEnabled"); - lua_classfunction(luaVM, "setDataClientTrustEnabled", "setElementDataClientTrustEnabled"); + lua_classfunction(luaVM, "setDataClientTrust", "setElementDataClientTrust"); lua_classfunction(luaVM, "getAttachedOffsets", "getElementAttachedOffsets"); lua_classfunction(luaVM, "getChild", "getElementChild"); @@ -192,7 +194,7 @@ void CLuaElementDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "isVisibleTo", "isElementVisibleTo"); lua_classfunction(luaVM, "isLowLOD", "isElementLowLOD"); lua_classfunction(luaVM, "isAttached", "isElementAttached"); - lua_classfunction(luaVM, "isDataClientTrustEnabled", "isElementDataClientTrustEnabled"); + lua_classfunction(luaVM, "isDataClientTrusted", "isElementDataClientTrusted"); lua_classvariable(luaVM, "id", "setElementID", "getElementID"); lua_classvariable(luaVM, "callPropagationEnabled", "setElementCallPropagationEnabled", "isElementCallPropagationEnabled"); @@ -2442,12 +2444,26 @@ int CLuaElementDefs::isElementCallPropagationEnabled(lua_State* luaVM) return 1; } -void CLuaElementDefs::SetElementDataClientTrustEnabled(CElement* pElement, std::string_view key, bool enabled) +void CLuaElementDefs::SetElementDataClientTrust(CElement* pElement, bool enabled, std::optional key) { - pElement->GetCustomDataManager().SetClientChangesAllowed(key.data(), enabled); + if (key.has_value()) + pElement->GetCustomDataManager().SetClientChangesMode(key.value().data(), enabled ? ECustomDataClientTrust::ALLOW : ECustomDataClientTrust::DENY); + else + pElement->GetCustomDataManager().SetClientChangesAllowed(enabled); +} + +bool CLuaElementDefs::IsElementDataClientTrusted(CElement* pElement, std::optional key) +{ + if (key.has_value()) + return pElement->GetCustomDataManager().IsClientChangesAllowed(key.value().data()); + else + return pElement->GetCustomDataManager().IsClientChangesAllowed(); } -bool CLuaElementDefs::IsElementDataClientTrustEnabled(CElement* pElement, std::string_view key) +void CLuaElementDefs::ResetElementDataClientTrust(CElement* pElement, std::optional key) { - return pElement->GetCustomDataManager().IsClientChangesAllowed(key.data()); + if (key.has_value()) + pElement->GetCustomDataManager().SetClientChangesMode(key.value().data(), ECustomDataClientTrust::UNSET); + else + pElement->GetCustomDataManager().SetClientChangesAllowed(true); } diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h index 77449f2f391..aa69183f272 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h @@ -77,8 +77,9 @@ class CLuaElementDefs : public CLuaDefs LUA_DECLARE(addElementDataSubscriber); LUA_DECLARE(removeElementDataSubscriber); LUA_DECLARE(hasElementDataSubscriber); - static void SetElementDataClientTrustEnabled(CElement* pElement, std::string_view key, bool enabled); - static bool IsElementDataClientTrustEnabled(CElement* pElement, std::string_view key); + static void SetElementDataClientTrust(CElement* pElement, bool enabled, std::optional key); + static void ResetElementDataClientTrust(CElement* pElement, std::optional key); + static bool IsElementDataClientTrusted(CElement* pElement, std::optional key); // Attachement LUA_DECLARE(attachElements); From 640c46f02c3a206cf7075f172aca5c9a3143962b Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Wed, 6 Nov 2024 18:44:43 +0300 Subject: [PATCH 3/7] Replace with server config setting and setElementData parameter --- Server/mods/deathmatch/local.conf | 6 +++ Server/mods/deathmatch/logic/CCustomData.cpp | 9 ----- Server/mods/deathmatch/logic/CCustomData.h | 5 --- Server/mods/deathmatch/logic/CGame.cpp | 2 +- Server/mods/deathmatch/logic/CMainConfig.cpp | 3 ++ Server/mods/deathmatch/logic/CMainConfig.h | 2 + .../logic/CStaticFunctionDefinitions.cpp | 13 ++++-- .../logic/CStaticFunctionDefinitions.h | 3 +- .../logic/lua/CLuaFunctionParseHelpers.cpp | 6 +++ .../logic/lua/CLuaFunctionParseHelpers.h | 1 + .../logic/luadefs/CLuaElementDefs.cpp | 40 +++++-------------- .../logic/luadefs/CLuaElementDefs.h | 3 -- Server/mods/deathmatch/mtaserver.conf | 6 +++ .../mods/deathmatch/mtaserver.conf.template | 6 +++ 14 files changed, 51 insertions(+), 54 deletions(-) diff --git a/Server/mods/deathmatch/local.conf b/Server/mods/deathmatch/local.conf index ec3defd37d2..4b83df674a5 100644 --- a/Server/mods/deathmatch/local.conf +++ b/Server/mods/deathmatch/local.conf @@ -264,6 +264,12 @@ Values: 0 - Off, 1 - Enabled. Default - 1 --> 1 + + 0 + diff --git a/Server/mods/deathmatch/logic/CCustomData.cpp b/Server/mods/deathmatch/logic/CCustomData.cpp index 12563e04dda..27e99ec015b 100644 --- a/Server/mods/deathmatch/logic/CCustomData.cpp +++ b/Server/mods/deathmatch/logic/CCustomData.cpp @@ -121,15 +121,6 @@ bool CCustomData::Delete(const char* szName) return false; } -bool CCustomData::IsClientChangesAllowed(const char* szName) const -{ - SCustomData* pData = Get(szName); - if (!pData || pData->clientChangesMode == ECustomDataClientTrust::UNSET) - return IsClientChangesAllowed(); - - return pData->clientChangesMode == ECustomDataClientTrust::ALLOW; -} - void CCustomData::SetClientChangesMode(const char* szName, ECustomDataClientTrust mode) { SCustomData& pData = m_Data[szName]; diff --git a/Server/mods/deathmatch/logic/CCustomData.h b/Server/mods/deathmatch/logic/CCustomData.h index b22674e580d..6f1dbc597f6 100644 --- a/Server/mods/deathmatch/logic/CCustomData.h +++ b/Server/mods/deathmatch/logic/CCustomData.h @@ -50,12 +50,8 @@ class CCustomData bool Delete(const char* szName); - bool IsClientChangesAllowed(const char* szName) const; void SetClientChangesMode(const char* szName, ECustomDataClientTrust mode); - bool IsClientChangesAllowed() const noexcept { return m_clientChangesAllowed; }; - void SetClientChangesAllowed(bool enabled) noexcept { m_clientChangesAllowed = enabled; }; - unsigned short CountOnlySynchronized(); CXMLNode* OutputToXML(CXMLNode* pNode); @@ -72,5 +68,4 @@ class CCustomData std::map m_Data; std::map m_SyncedData; - bool m_clientChangesAllowed{true}; }; diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 324d2ed2773..52029f2d76d 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -2657,7 +2657,7 @@ void CGame::Packet_CustomData(CCustomDataPacket& Packet) pElement->GetCustomData(szName, false, &lastSyncType, &clientChangesMode); - const bool changesAllowed = clientChangesMode == ECustomDataClientTrust::UNSET ? pElement->GetCustomDataManager().IsClientChangesAllowed() + const bool changesAllowed = clientChangesMode == ECustomDataClientTrust::UNSET ? !m_pMainConfig->IsElementDataWhitelisted() : clientChangesMode == ECustomDataClientTrust::ALLOW; if (!changesAllowed) { diff --git a/Server/mods/deathmatch/logic/CMainConfig.cpp b/Server/mods/deathmatch/logic/CMainConfig.cpp index d47950e73e2..87881e33701 100644 --- a/Server/mods/deathmatch/logic/CMainConfig.cpp +++ b/Server/mods/deathmatch/logic/CMainConfig.cpp @@ -79,6 +79,7 @@ CMainConfig::CMainConfig(CConsole* pConsole) : CXMLConfig(NULL) m_iBackupInterval = 3; m_iBackupAmount = 5; m_bSyncMapElementData = true; + m_elementDataWhitelisted = false; } bool CMainConfig::Load() @@ -526,6 +527,8 @@ bool CMainConfig::Load() g_TickRateSettings.iLightSync = Clamp(200, g_TickRateSettings.iLightSync, 4000); } + GetBoolean(m_pRootNode, "elementdata_whitelisted", m_elementDataWhitelisted); + ApplyNetOptions(); return true; diff --git a/Server/mods/deathmatch/logic/CMainConfig.h b/Server/mods/deathmatch/logic/CMainConfig.h index b52733229a4..8c1c1f30fb8 100644 --- a/Server/mods/deathmatch/logic/CMainConfig.h +++ b/Server/mods/deathmatch/logic/CMainConfig.h @@ -126,6 +126,7 @@ class CMainConfig : public CXMLConfig const std::vector& GetOwnerEmailAddressList() const { return m_OwnerEmailAddressList; } bool IsDatabaseCredentialsProtectionEnabled() const { return m_bDatabaseCredentialsProtectionEnabled != 0; } bool IsFakeLagCommandEnabled() const { return m_bFakeLagCommandEnabled != 0; } + bool IsElementDataWhitelisted() const { return m_elementDataWhitelisted; }; SString GetSetting(const SString& configSetting); bool GetSetting(const SString& configSetting, SString& strValue); @@ -227,4 +228,5 @@ class CMainConfig : public CXMLConfig int m_bFakeLagCommandEnabled; int m_iPlayerTriggeredEventIntervalMs; int m_iMaxPlayerTriggeredEventsPerInterval; + bool m_elementDataWhitelisted; }; diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 67764f80573..2d65af0eaf0 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -954,14 +954,19 @@ bool CStaticFunctionDefinitions::SetElementID(CElement* pElement, const char* sz return true; } -bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType) +bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType, + std::optional clientTrust) { assert(pElement); assert(szName); assert(strlen(szName) <= MAX_CUSTOMDATA_NAME_LENGTH); - ESyncType lastSyncType = ESyncType::BROADCAST; - CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType); + ESyncType lastSyncType = ESyncType::BROADCAST; + ECustomDataClientTrust lastClientTrust{}; + CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType, &lastClientTrust); + + if (clientTrust.has_value() && lastClientTrust != clientTrust.value()) + pElement->GetCustomDataManager().SetClientChangesMode(szName, clientTrust.value()); if (!pCurrentVariable || *pCurrentVariable != Variable || lastSyncType != syncType) { @@ -984,7 +989,7 @@ bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* // Unsubscribe all the players if (lastSyncType == ESyncType::SUBSCRIBE && syncType != ESyncType::SUBSCRIBE) m_pPlayerManager->ClearElementData(pElement, szName); - + // Set its custom data pElement->SetCustomData(szName, Variable, syncType); return true; diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h index dd6202208ff..e36b04734e7 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -83,7 +83,8 @@ class CStaticFunctionDefinitions // Element set funcs static bool ClearElementVisibleTo(CElement* pElement); static bool SetElementID(CElement* pElement, const char* szID); - static bool SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType); + static bool SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType, + std::optional clientTrust); static bool RemoveElementData(CElement* pElement, const char* szName); static bool AddElementDataSubscriber(CElement* pElement, const char* szName, CPlayer* pPlayer); static bool RemoveElementDataSubscriber(CElement* pElement, const char* szName, CPlayer* pPlayer); diff --git a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index ef25750c053..a8bb8d82226 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -285,6 +285,12 @@ ADD_ENUM(ESyncType::LOCAL, "local") ADD_ENUM(ESyncType::SUBSCRIBE, "subscribe") IMPLEMENT_ENUM_CLASS_END("sync-mode") +IMPLEMENT_ENUM_CLASS_BEGIN(ECustomDataClientTrust) +ADD_ENUM(ECustomDataClientTrust::UNSET, "default") +ADD_ENUM(ECustomDataClientTrust::ALLOW, "allow") +ADD_ENUM(ECustomDataClientTrust::DENY, "deny") +IMPLEMENT_ENUM_CLASS_END("client-trust-mode") + // // CResource from userdata // diff --git a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index 52a4536012e..f9cd0c85d9e 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -38,6 +38,7 @@ DECLARE_ENUM(CAccessControlListRight::ERightType); DECLARE_ENUM(CElement::EElementType); DECLARE_ENUM(CAccountPassword::EAccountPasswordType); DECLARE_ENUM_CLASS(ESyncType); +DECLARE_ENUM_CLASS(ECustomDataClientTrust) enum eHudComponent { diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index 673edc97639..8e3e2f39694 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -80,9 +80,6 @@ void CLuaElementDefs::LoadFunctions() {"addElementDataSubscriber", addElementDataSubscriber}, {"removeElementDataSubscriber", removeElementDataSubscriber}, {"hasElementDataSubscriber", hasElementDataSubscriber}, - {"setElementDataClientTrust", ArgumentParser}, - {"isElementDataClientTrusted", ArgumentParser}, - {"resetElementDataClientTrust", ArgumentParser}, // Set {"setElementID", setElementID}, @@ -132,7 +129,6 @@ void CLuaElementDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "addDataSubscriber", "addElementDataSubscriber"); lua_classfunction(luaVM, "removeDataSubscriber", "removeElementDataSubscriber"); lua_classfunction(luaVM, "hasDataSubscriber", "hasElementDataSubscriber"); - lua_classfunction(luaVM, "resetDataClientTrust", "resetElementDataClientTrust"); lua_classfunction(luaVM, "setParent", "setElementParent"); lua_classfunction(luaVM, "setFrozen", "setElementFrozen"); @@ -155,7 +151,6 @@ void CLuaElementDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "setLowLOD", "setLowLODElement"); lua_classfunction(luaVM, "setAttachedOffsets", "setElementAttachedOffsets"); lua_classfunction(luaVM, "setCallPropagationEnabled", "setElementCallPropagationEnabled"); - lua_classfunction(luaVM, "setDataClientTrust", "setElementDataClientTrust"); lua_classfunction(luaVM, "getAttachedOffsets", "getElementAttachedOffsets"); lua_classfunction(luaVM, "getChild", "getElementChild"); @@ -194,7 +189,6 @@ void CLuaElementDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "isVisibleTo", "isElementVisibleTo"); lua_classfunction(luaVM, "isLowLOD", "isElementLowLOD"); lua_classfunction(luaVM, "isAttached", "isElementAttached"); - lua_classfunction(luaVM, "isDataClientTrusted", "isElementDataClientTrusted"); lua_classvariable(luaVM, "id", "setElementID", "getElementID"); lua_classvariable(luaVM, "callPropagationEnabled", "setElementCallPropagationEnabled", "isElementCallPropagationEnabled"); @@ -1544,6 +1538,7 @@ int CLuaElementDefs::setElementData(lua_State* luaVM) SString strKey; CLuaArgument value; ESyncType syncType = ESyncType::BROADCAST; + std::optional clientTrust{}; CScriptArgReader argStream(luaVM); argStream.ReadUserData(pElement); @@ -1560,6 +1555,13 @@ int CLuaElementDefs::setElementData(lua_State* luaVM) else argStream.ReadEnumString(syncType, ESyncType::BROADCAST); + if (!argStream.NextIsNone()) + { + ECustomDataClientTrust trustReaded; + argStream.ReadEnumString(trustReaded); + clientTrust = trustReaded; + } + if (!argStream.HasErrors()) { LogWarningIfPlayerHasNotJoinedYet(luaVM, pElement); @@ -1572,7 +1574,7 @@ int CLuaElementDefs::setElementData(lua_State* luaVM) strKey = strKey.Left(MAX_CUSTOMDATA_NAME_LENGTH); } - if (CStaticFunctionDefinitions::SetElementData(pElement, strKey, value, syncType)) + if (CStaticFunctionDefinitions::SetElementData(pElement, strKey, value, syncType, clientTrust)) { lua_pushboolean(luaVM, true); return 1; @@ -2443,27 +2445,3 @@ int CLuaElementDefs::isElementCallPropagationEnabled(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } - -void CLuaElementDefs::SetElementDataClientTrust(CElement* pElement, bool enabled, std::optional key) -{ - if (key.has_value()) - pElement->GetCustomDataManager().SetClientChangesMode(key.value().data(), enabled ? ECustomDataClientTrust::ALLOW : ECustomDataClientTrust::DENY); - else - pElement->GetCustomDataManager().SetClientChangesAllowed(enabled); -} - -bool CLuaElementDefs::IsElementDataClientTrusted(CElement* pElement, std::optional key) -{ - if (key.has_value()) - return pElement->GetCustomDataManager().IsClientChangesAllowed(key.value().data()); - else - return pElement->GetCustomDataManager().IsClientChangesAllowed(); -} - -void CLuaElementDefs::ResetElementDataClientTrust(CElement* pElement, std::optional key) -{ - if (key.has_value()) - pElement->GetCustomDataManager().SetClientChangesMode(key.value().data(), ECustomDataClientTrust::UNSET); - else - pElement->GetCustomDataManager().SetClientChangesAllowed(true); -} diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h index aa69183f272..b58f613b596 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h @@ -77,9 +77,6 @@ class CLuaElementDefs : public CLuaDefs LUA_DECLARE(addElementDataSubscriber); LUA_DECLARE(removeElementDataSubscriber); LUA_DECLARE(hasElementDataSubscriber); - static void SetElementDataClientTrust(CElement* pElement, bool enabled, std::optional key); - static void ResetElementDataClientTrust(CElement* pElement, std::optional key); - static bool IsElementDataClientTrusted(CElement* pElement, std::optional key); // Attachement LUA_DECLARE(attachElements); diff --git a/Server/mods/deathmatch/mtaserver.conf b/Server/mods/deathmatch/mtaserver.conf index 19fe4a05d83..7acb9af9ebb 100644 --- a/Server/mods/deathmatch/mtaserver.conf +++ b/Server/mods/deathmatch/mtaserver.conf @@ -268,6 +268,12 @@ Values: 0 - Off, 1 - Enabled. Default - 1 --> 1 + + 0 + 1 + + 0 +