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
This commit is contained in:
Scott Ehlert 2007-03-06 04:50:30 +00:00
parent 68f40e96f2
commit dbb74a612d
5 changed files with 89 additions and 55 deletions

View File

@ -25,7 +25,7 @@ typedef List<EventHook *> EventHookList;
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell}; 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 */ /* Create an event lookup trie */
m_EventHooks = sm_trie_create(); m_EventHooks = sm_trie_create();
@ -34,6 +34,15 @@ EventManager::EventManager() : m_EventCopy(NULL), m_NotifyState(true)
EventManager::~EventManager() EventManager::~EventManager()
{ {
sm_trie_destroy(m_EventHooks); sm_trie_destroy(m_EventHooks);
/* Free memory used by EventInfo structs if any */
CStack<EventInfo *>::iterator iter;
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
{
delete (*iter);
}
m_FreeEvents.popall();
} }
void EventManager::OnSourceModAllInitialized() void EventManager::OnSourceModAllInitialized()
@ -68,15 +77,16 @@ void EventManager::OnSourceModShutdown()
void EventManager::OnHandleDestroy(HandleType_t type, void *object) void EventManager::OnHandleDestroy(HandleType_t type, void *object)
{ {
if (type == m_EventType) EventInfo *pInfo = static_cast<EventInfo *>(object);
{
EventInfo *pInfo = static_cast<EventInfo *>(object);
if (pInfo->canDelete) /* Should only free event when created by a plugin */
{ if (pInfo->pOwner)
gameevents->FreeEvent(pInfo->pEvent); {
delete pInfo; /* 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; 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 */ /* IGameEventManager2::FireEvent hook */
bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
{ {
@ -273,7 +323,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
IChangeableForward *pForward; IChangeableForward *pForward;
cell_t res = Pl_Continue; cell_t res = Pl_Continue;
if (!m_NotifyState) if (!m_NotifyPlugins)
{ {
RETURN_META_VALUE(MRES_IGNORED, true); RETURN_META_VALUE(MRES_IGNORED, true);
} }
@ -321,9 +371,11 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
IChangeableForward *pForward; IChangeableForward *pForward;
Handle_t hndl; 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); RETURN_META_VALUE(MRES_IGNORED, true);
} }

View File

@ -8,7 +8,7 @@
* in whole or significant part. * in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
* *
* Version: $$ * Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_ #ifndef _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_
@ -18,6 +18,7 @@
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_trie.h" #include "sm_trie.h"
#include <sh_list.h> #include <sh_list.h>
#include <sh_stack.h>
#include <IHandleSys.h> #include <IHandleSys.h>
#include <IForwardSys.h> #include <IForwardSys.h>
#include <IPluginSys.h> #include <IPluginSys.h>
@ -30,7 +31,7 @@ using namespace SourceHook;
struct EventInfo struct EventInfo
{ {
IGameEvent *pEvent; IGameEvent *pEvent;
bool canDelete; IdentityToken_t *pOwner;
}; };
struct EventHook struct EventHook
@ -87,31 +88,23 @@ public:
*/ */
inline HandleType_t GetHandleType() inline HandleType_t GetHandleType()
{ {
return EventManager::m_EventType; return 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;
} }
public: public:
EventHookError HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post); EventHookError HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
EventHookError UnhookEvent(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 private: // IGameEventManager2 hooks
bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast); bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast);
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast); bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
private: private:
HandleType_t m_EventType; HandleType_t m_EventType;
Trie *m_EventHooks; Trie *m_EventHooks;
bool m_NotifyState; bool m_NotifyPlugins;
IGameEvent *m_EventCopy; IGameEvent *m_EventCopy;
const char *m_EventName; const char *m_EventName;
CStack<EventInfo *> m_FreeEvents;
}; };
extern EventManager g_EventManager; extern EventManager g_EventManager;

View File

@ -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) static cell_t sm_CreateEvent(IPluginContext *pContext, const cell_t *params)
{ {
IGameEvent *pEvent;
EventInfo *pInfo;
char *name; char *name;
EventInfo *pInfo;
pContext->LocalToString(params[1], &name); 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); 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); 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 */ return pContext->ThrowNativeError("Game event \"%s\" could not be fired because it was not created by this plugin", pInfo->pEvent->GetName());
g_EventManager.SetNotifyState(false);
} }
/* Fire game event */ g_EventManager.FireEvent(pContext, pInfo, params[2], params[3] ? true : false);
gameevents->FireEvent(pInfo->pEvent, params[2] ? true : false);
pInfo->canDelete = false;
/* Free handle on game event */ /* Free handle on game event */
HandleSecurity sec = { pContext->GetIdentity(), g_pCoreIdent }; HandleSecurity sec = {pContext->GetIdentity(), g_pCoreIdent};
g_HandleSys.FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
/* Free EventInfo memory */
delete pInfo;
return 1; 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); 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 /* Free handle on game event */
delete pInfo; HandleSecurity sec = {pContext->GetIdentity(), g_pCoreIdent};
// Free handle on game event
HandleSecurity sec = { pContext->GetIdentity(), g_pCoreIdent };
g_HandleSys.FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
return 1; return 1;

View File

@ -17,7 +17,6 @@
#include "convar_sm.h" #include "convar_sm.h"
#include <ISmmPlugin.h> #include <ISmmPlugin.h>
#include <eiface.h> #include <eiface.h>
#include <icvar.h>
#include <igameevents.h> #include <igameevents.h>
#include <random.h> #include <random.h>

View File

@ -91,12 +91,12 @@ native Handle:CreateEvent(const String:name[]);
* Fires a game event. * Fires a game event.
* *
* @param event Handle to the 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 flags Optional bitstring flags. See EVENT_* constants for more details.
* @param dontBroadcast Optional boolean that determines if event should be broadcast to clients.
* @noreturn * @noreturn
* @error Invalid or corrupt Handle. * @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. * Cancels a previously created game event that has not been fired.