From dbb74a612d008fc23b30e992e48355b4c482090f Mon Sep 17 00:00:00 2001 From: Scott Ehlert Date: Tue, 6 Mar 2007 04:50:30 +0000 Subject: [PATCH] Creating/Firing/Canceling events now use CStack to avoid the need to use new when possible --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40583 --- core/EventManager.cpp | 76 ++++++++++++++++++++++++++++++++------ core/EventManager.h | 23 ++++-------- core/smn_events.cpp | 40 ++++++++------------ core/sourcemm_api.h | 1 - plugins/include/events.inc | 4 +- 5 files changed, 89 insertions(+), 55 deletions(-) diff --git a/core/EventManager.cpp b/core/EventManager.cpp index bf70b97f..587a20d5 100644 --- a/core/EventManager.cpp +++ b/core/EventManager.cpp @@ -25,7 +25,7 @@ typedef List EventHookList; const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell}; -EventManager::EventManager() : m_EventCopy(NULL), m_NotifyState(true) +EventManager::EventManager() : m_EventCopy(NULL), m_NotifyPlugins(true) { /* Create an event lookup trie */ m_EventHooks = sm_trie_create(); @@ -34,6 +34,15 @@ EventManager::EventManager() : m_EventCopy(NULL), m_NotifyState(true) EventManager::~EventManager() { sm_trie_destroy(m_EventHooks); + + /* Free memory used by EventInfo structs if any */ + CStack::iterator iter; + for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++) + { + delete (*iter); + } + + m_FreeEvents.popall(); } void EventManager::OnSourceModAllInitialized() @@ -68,15 +77,16 @@ void EventManager::OnSourceModShutdown() void EventManager::OnHandleDestroy(HandleType_t type, void *object) { - if (type == m_EventType) - { - EventInfo *pInfo = static_cast(object); + EventInfo *pInfo = static_cast(object); - if (pInfo->canDelete) - { - gameevents->FreeEvent(pInfo->pEvent); - delete pInfo; - } + /* Should only free event when created by a plugin */ + if (pInfo->pOwner) + { + /* Free IGameEvent */ + gameevents->FreeEvent(pInfo->pEvent); + + /* Add EventInfo struct to free event stack */ + m_FreeEvents.push(pInfo); } } @@ -266,6 +276,46 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun return EventHookErr_Okay; } +EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name) +{ + EventInfo *pInfo; + IGameEvent *pEvent = gameevents->CreateEvent(name, true); + + if (pEvent) + { + if (m_FreeEvents.empty()) + { + pInfo = new EventInfo(); + } else { + pInfo = m_FreeEvents.front(); + m_FreeEvents.pop(); + } + + + pInfo->pEvent = pEvent; + pInfo->pOwner = pContext->GetIdentity(); + + return pInfo; + } + + return NULL; +} + +void EventManager::FireEvent(IPluginContext *pContext, EventInfo *pInfo, int flags, bool bDontBroadcast) +{ + /* Should SourceMod plugins be notified of this event? */ + m_NotifyPlugins = (flags & EVENT_PASSTHRU_ALL) ? true : false; + + /* Actually fire event now */ + gameevents->FireEvent(pInfo->pEvent, bDontBroadcast); + + /* IGameEvent is free at this point, so no one owns this */ + pInfo->pOwner = NULL; + + /* Add EventInfo struct to free event stack */ + m_FreeEvents.push(pInfo); +} + /* IGameEventManager2::FireEvent hook */ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) { @@ -273,7 +323,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) IChangeableForward *pForward; cell_t res = Pl_Continue; - if (!m_NotifyState) + if (!m_NotifyPlugins) { RETURN_META_VALUE(MRES_IGNORED, true); } @@ -321,9 +371,11 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) IChangeableForward *pForward; Handle_t hndl; - if (!m_NotifyState) + if (!m_NotifyPlugins) { - m_NotifyState = true; + /* Reset plugin notification state */ + m_NotifyPlugins = true; + RETURN_META_VALUE(MRES_IGNORED, true); } diff --git a/core/EventManager.h b/core/EventManager.h index 7b67cb00..360a9201 100644 --- a/core/EventManager.h +++ b/core/EventManager.h @@ -8,7 +8,7 @@ * in whole or significant part. * For information, see LICENSE.txt or http://www.sourcemod.net/license.php * -* Version: $$ +* Version: $Id$ */ #ifndef _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_ @@ -18,6 +18,7 @@ #include "sourcemm_api.h" #include "sm_trie.h" #include +#include #include #include #include @@ -30,7 +31,7 @@ using namespace SourceHook; struct EventInfo { IGameEvent *pEvent; - bool canDelete; + IdentityToken_t *pOwner; }; struct EventHook @@ -87,31 +88,23 @@ public: */ inline HandleType_t GetHandleType() { - return EventManager::m_EventType; - } - - /** - * Sets the current SourceMod event notification state. - * - * If notify is set to true, SourceMod plugins will be notified of events. If false, they will not. - * This is temporarily used to make EVENT_PASSTHRU work when firing events from plugins. - */ - inline void SetNotifyState(bool notify) - { - m_NotifyState = notify; + return m_EventType; } public: EventHookError HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post); EventHookError UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post); + EventInfo *CreateEvent(IPluginContext *pContext, const char *name); + void FireEvent(IPluginContext *pContext, EventInfo *pInfo, int flags=0, bool bDontBroadcast=false); private: // IGameEventManager2 hooks bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast); bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast); private: HandleType_t m_EventType; Trie *m_EventHooks; - bool m_NotifyState; + bool m_NotifyPlugins; IGameEvent *m_EventCopy; const char *m_EventName; + CStack m_FreeEvents; }; extern EventManager g_EventManager; diff --git a/core/smn_events.cpp b/core/smn_events.cpp index edc3b471..7e8814e9 100644 --- a/core/smn_events.cpp +++ b/core/smn_events.cpp @@ -65,20 +65,15 @@ static cell_t sm_UnhookEvent(IPluginContext *pContext, const cell_t *params) static cell_t sm_CreateEvent(IPluginContext *pContext, const cell_t *params) { - IGameEvent *pEvent; - EventInfo *pInfo; char *name; + EventInfo *pInfo; pContext->LocalToString(params[1], &name); - pEvent = gameevents->CreateEvent(name, true); + pInfo = g_EventManager.CreateEvent(pContext, name); - if (pEvent) + if (pInfo) { - pInfo = new EventInfo; - pInfo->pEvent = pEvent; - pInfo->canDelete = true; - return g_HandleSys.CreateHandle(g_EventManager.GetHandleType(), pInfo, pContext->GetIdentity(), g_pCoreIdent, NULL); } @@ -97,24 +92,18 @@ static cell_t sm_FireEvent(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err); } - if ((params[3] & EVENT_PASSTHRU_ALL) == false) + /* If identities do not match, don't fire event */ + if (pContext->GetIdentity() != pInfo->pOwner) { - /* Set whether or not SourceMod plugins should be notified */ - g_EventManager.SetNotifyState(false); + return pContext->ThrowNativeError("Game event \"%s\" could not be fired because it was not created by this plugin", pInfo->pEvent->GetName()); } - /* Fire game event */ - gameevents->FireEvent(pInfo->pEvent, params[2] ? true : false); - - pInfo->canDelete = false; + g_EventManager.FireEvent(pContext, pInfo, params[2], params[3] ? true : false); /* Free handle on game event */ - HandleSecurity sec = { pContext->GetIdentity(), g_pCoreIdent }; + HandleSecurity sec = {pContext->GetIdentity(), g_pCoreIdent}; g_HandleSys.FreeHandle(hndl, &sec); - /* Free EventInfo memory */ - delete pInfo; - return 1; } @@ -130,13 +119,14 @@ static cell_t sm_CancelCreatedEvent(IPluginContext *pContext, const cell_t *para return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err); } - gameevents->FreeEvent(pInfo->pEvent); + /* If identities do not match, don't cancel event */ + if (pContext->GetIdentity() != pInfo->pOwner) + { + return pContext->ThrowNativeError("Game event \"%s\" could not be canceled because it was not created by this plugin", pInfo->pEvent->GetName()); + } - // Free GameEventInfo memory - delete pInfo; - - // Free handle on game event - HandleSecurity sec = { pContext->GetIdentity(), g_pCoreIdent }; + /* Free handle on game event */ + HandleSecurity sec = {pContext->GetIdentity(), g_pCoreIdent}; g_HandleSys.FreeHandle(hndl, &sec); return 1; diff --git a/core/sourcemm_api.h b/core/sourcemm_api.h index 317215d5..138b02e1 100644 --- a/core/sourcemm_api.h +++ b/core/sourcemm_api.h @@ -17,7 +17,6 @@ #include "convar_sm.h" #include #include -#include #include #include diff --git a/plugins/include/events.inc b/plugins/include/events.inc index 3b4cadb9..349517cb 100644 --- a/plugins/include/events.inc +++ b/plugins/include/events.inc @@ -91,12 +91,12 @@ native Handle:CreateEvent(const String:name[]); * Fires a game event. * * @param event Handle to the event. - * @param dontBroadcast Optional boolean that determines if event should be broadcast to clients. * @param flags Optional bitstring flags. See EVENT_* constants for more details. + * @param dontBroadcast Optional boolean that determines if event should be broadcast to clients. * @noreturn * @error Invalid or corrupt Handle. */ -native FireEvent(Handle:event, bool:dontBroadcast=false, flags=0); +native FireEvent(Handle:event, flags=0, bool:dontBroadcast=false); /** * Cancels a previously created game event that has not been fired.