diff --git a/Server/mods/deathmatch/logic/CCustomData.cpp b/Server/mods/deathmatch/logic/CCustomData.cpp index 955c71fc37..12563e04dd 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 e97d2554f9..b22674e580 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 6134d965c2..f98cf3f38e 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 801071ab69..9f25ab1001 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 53bdba5456..324d2ed277 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 3e8b565694..673edc9763 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 77449f2f39..aa69183f27 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);