From 1aad7cabaae1660d5e3b18870b1b042a46f36258 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Sun, 9 Nov 2025 04:03:45 +0200 Subject: [PATCH 1/4] Implement event context management in CEvents and CElement classes --- Server/mods/deathmatch/logic/CElement.cpp | 13 +++--- Server/mods/deathmatch/logic/CEvents.cpp | 45 +++++++++++++++++--- Server/mods/deathmatch/logic/CEvents.h | 8 ++-- Shared/mods/deathmatch/logic/CEventContext.h | 40 +++++++++++++++++ 4 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 Shared/mods/deathmatch/logic/CEventContext.h diff --git a/Server/mods/deathmatch/logic/CElement.cpp b/Server/mods/deathmatch/logic/CElement.cpp index d8cc25bf7ea..793e509a48c 100644 --- a/Server/mods/deathmatch/logic/CElement.cpp +++ b/Server/mods/deathmatch/logic/CElement.cpp @@ -438,10 +438,11 @@ bool CElement::CallEvent(const char* szName, const CLuaArguments& Arguments, CPl if (!g_pGame->GetDebugHookManager()->OnPreEvent(szName, Arguments, this, pCaller)) return false; - CEvents* pEvents = g_pGame->GetEvents(); + CEvents* pEvents = g_pGame->GetEvents(); + CEventContext eventContext; // Make sure our event-manager knows we're about to call an event - pEvents->PreEventPulse(); + pEvents->PreEventPulse(&eventContext); // Call the event on our parents/us first CallParentEvent(szName, Arguments, this, pCaller); @@ -450,15 +451,13 @@ bool CElement::CallEvent(const char* szName, const CLuaArguments& Arguments, CPl CallEventNoParent(szName, Arguments, this, pCaller); // Tell the event manager that we're done calling the event - pEvents->PostEventPulse(); + pEvents->PostEventPulse(&eventContext); g_pGame->GetDebugHookManager()->OnPostEvent(szName, Arguments, this, pCaller); // Return whether our event was cancelled or not - return (!pEvents->WasEventCancelled()); -} - -bool CElement::DeleteEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) + return !eventContext.IsCancelled(); +}bool CElement::DeleteEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) { return m_pEventManager->Delete(pLuaMain, szName, iLuaFunction); } diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp index eb82ea1e092..cbff47760ff 100644 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ b/Server/mods/deathmatch/logic/CEvents.cpp @@ -11,11 +11,15 @@ #include "StdInc.h" #include "CEvents.h" +#include "CLogger.h" +#include "CGame.h" +#include "CScriptDebugging.h" CEvents::CEvents() { m_bWasEventCancelled = false; m_bEventCancelled = false; + m_pCurrentContext = nullptr; } bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pLuaMain, bool bAllowRemoteTrigger) @@ -123,38 +127,67 @@ void CEvents::RemoveAllEvents() m_EventHashMap.clear(); } -void CEvents::PreEventPulse() +void CEvents::PreEventPulse(CEventContext* pContext) { + assert(pContext); + m_CancelledList.push_back(m_bEventCancelled); + + m_pCurrentContext = pContext; + pContext->Reset(); + m_bEventCancelled = false; m_bWasEventCancelled = false; m_strLastError = ""; } -void CEvents::PostEventPulse() +void CEvents::PostEventPulse(CEventContext* pContext) { - m_bWasEventCancelled = m_bEventCancelled; + assert(pContext); + assert(m_pCurrentContext == pContext); + + m_bWasEventCancelled = pContext->IsCancelled(); m_bEventCancelled = m_CancelledList.back() ? true : false; m_CancelledList.pop_back(); + + m_pCurrentContext = nullptr; } void CEvents::CancelEvent(bool bCancelled) { - m_bEventCancelled = bCancelled; + CancelEvent(bCancelled, nullptr); } void CEvents::CancelEvent(bool bCancelled, const char* szReason) { + // ALWAYS set the old global variable for backward compatibility m_bEventCancelled = bCancelled; - m_strLastError = SStringX(szReason); + + // Also update context if it exists + if (m_pCurrentContext) + { + if (bCancelled) + m_pCurrentContext->Cancel(szReason); + else + m_pCurrentContext->Reset(); + } + + if (szReason) + m_strLastError = szReason; } bool CEvents::WasEventCancelled() { - return m_bWasEventCancelled; + if (m_pCurrentContext) + return m_pCurrentContext->IsCancelled(); + + return m_bEventCancelled || m_bWasEventCancelled; } const char* CEvents::GetLastError() { + if (m_pCurrentContext) + return m_pCurrentContext->GetCancelReason().c_str(); + return m_strLastError; } diff --git a/Server/mods/deathmatch/logic/CEvents.h b/Server/mods/deathmatch/logic/CEvents.h index f15a112eb23..d5d9be7a0a7 100644 --- a/Server/mods/deathmatch/logic/CEvents.h +++ b/Server/mods/deathmatch/logic/CEvents.h @@ -14,6 +14,7 @@ #include #include #include +#include "CEventContext.h" struct SEvent { @@ -40,8 +41,8 @@ class CEvents CFastHashMap::const_iterator IterBegin() { return m_EventHashMap.begin(); }; CFastHashMap::const_iterator IterEnd() { return m_EventHashMap.end(); }; - void PreEventPulse(); - void PostEventPulse(); + void PreEventPulse(CEventContext* pContext); + void PostEventPulse(CEventContext* pContext); void CancelEvent(bool bCancelled = true); void CancelEvent(bool bCancelled, const char* szReason); @@ -56,6 +57,7 @@ class CEvents std::vector m_CancelledList; bool m_bEventCancelled; bool m_bWasEventCancelled; + SString m_strLastError; - SString m_strLastError; + CEventContext* m_pCurrentContext; }; diff --git a/Shared/mods/deathmatch/logic/CEventContext.h b/Shared/mods/deathmatch/logic/CEventContext.h new file mode 100644 index 00000000000..d60af9b6fc2 --- /dev/null +++ b/Shared/mods/deathmatch/logic/CEventContext.h @@ -0,0 +1,40 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: Shared/mods/deathmatch/logic/CEventContext.h + * PURPOSE: Per-event context for event dispatch and cancellation + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include + +class CEventContext +{ +public: + CEventContext() noexcept : m_isCancelled(false) {} + + void Cancel(const char* reason = nullptr) noexcept + { + m_isCancelled = true; + if (reason) + m_cancelReason = reason; + } + + bool IsCancelled() const noexcept { return m_isCancelled; } + const std::string& GetCancelReason() const noexcept { return m_cancelReason; } + + void Reset() noexcept + { + m_isCancelled = false; + m_cancelReason.clear(); + } + +private: + bool m_isCancelled; + std::string m_cancelReason; +}; From c830b40263901d722f893ea03428b885d110cc70 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Sun, 9 Nov 2025 08:25:45 +0200 Subject: [PATCH 2/4] Refactor CEvents class to use a context stack instead of a single current context pointer --- Server/mods/deathmatch/logic/CEvents.cpp | 24 ++++++++++++------------ Server/mods/deathmatch/logic/CEvents.h | 10 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp index cbff47760ff..b96afe82036 100644 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ b/Server/mods/deathmatch/logic/CEvents.cpp @@ -19,7 +19,6 @@ CEvents::CEvents() { m_bWasEventCancelled = false; m_bEventCancelled = false; - m_pCurrentContext = nullptr; } bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pLuaMain, bool bAllowRemoteTrigger) @@ -132,8 +131,8 @@ void CEvents::PreEventPulse(CEventContext* pContext) assert(pContext); m_CancelledList.push_back(m_bEventCancelled); + m_ContextStack.push_back(pContext); - m_pCurrentContext = pContext; pContext->Reset(); m_bEventCancelled = false; @@ -144,13 +143,13 @@ void CEvents::PreEventPulse(CEventContext* pContext) void CEvents::PostEventPulse(CEventContext* pContext) { assert(pContext); - assert(m_pCurrentContext == pContext); + assert(!m_ContextStack.empty()); + assert(m_ContextStack.back() == pContext); m_bWasEventCancelled = pContext->IsCancelled(); m_bEventCancelled = m_CancelledList.back() ? true : false; m_CancelledList.pop_back(); - - m_pCurrentContext = nullptr; + m_ContextStack.pop_back(); } void CEvents::CancelEvent(bool bCancelled) @@ -164,12 +163,13 @@ void CEvents::CancelEvent(bool bCancelled, const char* szReason) m_bEventCancelled = bCancelled; // Also update context if it exists - if (m_pCurrentContext) + if (!m_ContextStack.empty()) { + CEventContext* pCurrentContext = m_ContextStack.back(); if (bCancelled) - m_pCurrentContext->Cancel(szReason); + pCurrentContext->Cancel(szReason); else - m_pCurrentContext->Reset(); + pCurrentContext->Reset(); } if (szReason) @@ -178,16 +178,16 @@ void CEvents::CancelEvent(bool bCancelled, const char* szReason) bool CEvents::WasEventCancelled() { - if (m_pCurrentContext) - return m_pCurrentContext->IsCancelled(); + if (!m_ContextStack.empty()) + return m_ContextStack.back()->IsCancelled(); return m_bEventCancelled || m_bWasEventCancelled; } const char* CEvents::GetLastError() { - if (m_pCurrentContext) - return m_pCurrentContext->GetCancelReason().c_str(); + if (!m_ContextStack.empty()) + return m_ContextStack.back()->GetCancelReason().c_str(); return m_strLastError; } diff --git a/Server/mods/deathmatch/logic/CEvents.h b/Server/mods/deathmatch/logic/CEvents.h index d5d9be7a0a7..3572c6f5575 100644 --- a/Server/mods/deathmatch/logic/CEvents.h +++ b/Server/mods/deathmatch/logic/CEvents.h @@ -54,10 +54,10 @@ class CEvents CFastHashMap m_EventHashMap; - std::vector m_CancelledList; - bool m_bEventCancelled; - bool m_bWasEventCancelled; - SString m_strLastError; + std::vector m_CancelledList; + bool m_bEventCancelled; + bool m_bWasEventCancelled; + SString m_strLastError; - CEventContext* m_pCurrentContext; + std::vector m_ContextStack; }; From 83f9bc8d39eb5ac29d642b79be6fccb8c143ad20 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Sun, 9 Nov 2025 08:45:31 +0200 Subject: [PATCH 3/4] Remove unused includes from CEvents.cpp --- Server/mods/deathmatch/logic/CEvents.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp index b96afe82036..ed627d78c5b 100644 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ b/Server/mods/deathmatch/logic/CEvents.cpp @@ -11,9 +11,6 @@ #include "StdInc.h" #include "CEvents.h" -#include "CLogger.h" -#include "CGame.h" -#include "CScriptDebugging.h" CEvents::CEvents() { From 053445dd9e535cd6aee4e312385ad1f25e84f85e Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Sat, 22 Nov 2025 15:25:17 +0200 Subject: [PATCH 4/4] add line breaks in CElement --- Server/mods/deathmatch/logic/CElement.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Server/mods/deathmatch/logic/CElement.cpp b/Server/mods/deathmatch/logic/CElement.cpp index 793e509a48c..e1d20f5f3f5 100644 --- a/Server/mods/deathmatch/logic/CElement.cpp +++ b/Server/mods/deathmatch/logic/CElement.cpp @@ -457,7 +457,9 @@ bool CElement::CallEvent(const char* szName, const CLuaArguments& Arguments, CPl // Return whether our event was cancelled or not return !eventContext.IsCancelled(); -}bool CElement::DeleteEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) +} + +bool CElement::DeleteEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) { return m_pEventManager->Delete(pLuaMain, szName, iLuaFunction); }