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:
parent
68f40e96f2
commit
dbb74a612d
@ -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);
|
||||
EventInfo *pInfo = static_cast<EventInfo *>(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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "convar_sm.h"
|
||||
#include <ISmmPlugin.h>
|
||||
#include <eiface.h>
|
||||
#include <icvar.h>
|
||||
#include <igameevents.h>
|
||||
#include <random.h>
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user