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};
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<EventInfo *>::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<EventInfo *>(object);
if (pInfo->canDelete)
/* Should only free event when created by a plugin */
if (pInfo->pOwner)
{
/* Free IGameEvent */
gameevents->FreeEvent(pInfo->pEvent);
delete pInfo;
}
/* 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);
}

View File

@ -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 <sh_list.h>
#include <sh_stack.h>
#include <IHandleSys.h>
#include <IForwardSys.h>
#include <IPluginSys.h>
@ -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<EventInfo *> m_FreeEvents;
};
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)
{
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;

View File

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

View File

@ -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.