Initial import of event stuff: Natives to hook and fire game events

Also made some minor internal changes to convars

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40582
This commit is contained in:
Scott Ehlert 2007-03-04 04:05:03 +00:00
parent 510b764d43
commit 68f40e96f2
10 changed files with 1128 additions and 91 deletions

View File

@ -88,7 +88,7 @@ void CConVarManager::OnPluginDestroyed(IPlugin *plugin)
CVector<ConVar *> *cvarList;
// If plugin has a convar list, free its memory
if (plugin->GetProperty("ConVar", reinterpret_cast<void **>(&cvarList), true))
if (plugin->GetProperty("ConVarList", reinterpret_cast<void **>(&cvarList), true))
{
delete cvarList;
}
@ -97,21 +97,21 @@ void CConVarManager::OnPluginDestroyed(IPlugin *plugin)
void CConVarManager::OnHandleDestroy(HandleType_t type, void *object)
{
ConVarInfo *info;
ConVar *cvar = static_cast<ConVar *>(object);
ConVar *pConVar = static_cast<ConVar *>(object);
// Find convar in lookup trie
sm_trie_retrieve(m_ConVarCache, cvar->GetName(), reinterpret_cast<void **>(&info));
sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info));
// If convar was created by SourceMod plugin...
if (info->sourceMod)
{
// Delete string allocations
delete [] cvar->GetName();
delete [] cvar->GetDefault();
delete [] cvar->GetHelpText();
delete [] pConVar->GetName();
delete [] pConVar->GetDefault();
delete [] pConVar->GetHelpText();
// Then unregister it
g_SMAPI->UnregisterConCmdBase(g_PLAPI, cvar);
// Then unlink it from SourceMM
g_SMAPI->UnregisterConCmdBase(g_PLAPI, pConVar);
}
}
@ -151,8 +151,8 @@ void CConVarManager::OnRootConsoleCommand(const char *command, unsigned int argc
// Iterate convar list and display each one
for (size_t i = 0; i < cvarList->size(); i++, id++)
{
ConVar *cvar = (*cvarList)[i];
g_RootMenu.ConsolePrint(" %02d \"%s\" = \"%s\"", id, cvar->GetName(), cvar->GetString());
ConVar *pConVar = (*cvarList)[i];
g_RootMenu.ConsolePrint(" %02d \"%s\" = \"%s\"", id, pConVar->GetName(), pConVar->GetString());
}
return;
@ -164,16 +164,16 @@ void CConVarManager::OnRootConsoleCommand(const char *command, unsigned int argc
Handle_t CConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *helpText, int flags, bool hasMin, float min, bool hasMax, float max)
{
ConVar *cvar = NULL;
ConVar *pConVar = NULL;
ConVarInfo *info = NULL;
CVector<ConVar *> *cvarList = NULL;
Handle_t hndl = 0;
// Find out if the convar exists already
cvar = icvar->FindVar(name);
pConVar = icvar->FindVar(name);
// If the convar already exists...
if (cvar != NULL)
if (pConVar != NULL)
{
// First check if we already have a handle to it
if (sm_trie_retrieve(m_ConVarCache, name, reinterpret_cast<void **>(&info)))
@ -182,13 +182,13 @@ Handle_t CConVarManager::CreateConVar(IPluginContext *pContext, const char *name
return info->handle;
} else {
// If we don't, then create a new handle from the convar
hndl = g_HandleSys.CreateHandle(m_ConVarType, cvar, NULL, g_pCoreIdent, NULL);
hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
info = new ConVarInfo;
info->handle = hndl;
info->sourceMod = false;
info->changeForward = NULL;
info->origCallback = cvar->GetCallback();
info->origCallback = pConVar->GetCallback();
m_ConVars.push_back(info);
@ -210,27 +210,27 @@ Handle_t CConVarManager::CreateConVar(IPluginContext *pContext, const char *name
}
// Since we didn't find an existing convar (or concmd with the same name), now we can finally create it!
cvar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(helpText), hasMin, min, hasMax, max);
pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(helpText), hasMin, min, hasMax, max);
// Find plugin creating convar
IPlugin *pl = g_PluginSys.FindPluginByContext(pContext->GetContext());
// Get convar list from 'ConVar' property of plugin
pl->GetProperty("ConVar", reinterpret_cast<void **>(&cvarList));
pl->GetProperty("ConVarList", reinterpret_cast<void **>(&cvarList));
// If 'ConVar' property doesn't exist...
if (cvarList == NULL)
{
// Then create it
cvarList = new CVector<ConVar *>;
pl->SetProperty("ConVar", cvarList);
pl->SetProperty("ConVarList", cvarList);
}
// Add new convar to plugin's list
cvarList->push_back(cvar);
cvarList->push_back(pConVar);
// Create a handle from the new convar
hndl = g_HandleSys.CreateHandle(m_ConVarType, cvar, NULL, g_pCoreIdent, NULL);
hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
info = new ConVarInfo;
info->handle = hndl;
@ -248,15 +248,15 @@ Handle_t CConVarManager::CreateConVar(IPluginContext *pContext, const char *name
Handle_t CConVarManager::FindConVar(const char *name)
{
ConVar *cvar = NULL;
ConVar *pConVar = NULL;
ConVarInfo *info = NULL;
Handle_t hndl = 0;
// Search for convar
cvar = icvar->FindVar(name);
pConVar = icvar->FindVar(name);
// If it doesn't exist, then return an invalid handle
if (cvar == NULL)
if (pConVar == NULL)
{
return BAD_HANDLE;
}
@ -269,13 +269,13 @@ Handle_t CConVarManager::FindConVar(const char *name)
}
// If we don't, then create a new handle from the convar
hndl = g_HandleSys.CreateHandle(m_ConVarType, cvar, NULL, g_pCoreIdent, NULL);
hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
info = new ConVarInfo;
info->handle = hndl;
info->sourceMod = false;
info->changeForward = NULL;
info->origCallback = cvar->GetCallback();
info->origCallback = pConVar->GetCallback();
m_ConVars.push_back(info);
@ -285,7 +285,7 @@ Handle_t CConVarManager::FindConVar(const char *name)
return hndl;
}
void CConVarManager::HookConVarChange(IPluginContext *pContext, ConVar *cvar, funcid_t funcid)
void CConVarManager::HookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid)
{
IPluginFunction *func = pContext->GetFunctionById(funcid);
IChangeableForward *fwd = NULL;
@ -300,7 +300,7 @@ void CConVarManager::HookConVarChange(IPluginContext *pContext, ConVar *cvar, fu
}
// Create a forward name
UTIL_Format(fwdName, sizeof(fwdName), "ConVar.%s", cvar->GetName());
UTIL_Format(fwdName, sizeof(fwdName), "ConVar.%s", pConVar->GetName());
// First find out if the forward already exists
g_Forwards.FindForward(fwdName, &fwd);
@ -315,13 +315,13 @@ void CConVarManager::HookConVarChange(IPluginContext *pContext, ConVar *cvar, fu
fwd = g_Forwards.CreateForwardEx(fwdName, ET_Ignore, 3, p);
// Find the convar in the lookup trie
if (sm_trie_retrieve(m_ConVarCache, cvar->GetName(), reinterpret_cast<void **>(&info)))
if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info)))
{
// Set the convar's forward to the newly created one
info->changeForward = fwd;
// Set the convar's callback to our static one
cvar->InstallChangeCallback(OnConVarChanged);
pConVar->InstallChangeCallback(OnConVarChanged);
}
}
@ -329,7 +329,7 @@ void CConVarManager::HookConVarChange(IPluginContext *pContext, ConVar *cvar, fu
fwd->AddFunction(func);
}
void CConVarManager::UnhookConVarChange(IPluginContext *pContext, ConVar *cvar, funcid_t funcid)
void CConVarManager::UnhookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid)
{
IPluginFunction *func = pContext->GetFunctionById(funcid);
IChangeableForward *fwd = NULL;
@ -343,7 +343,7 @@ void CConVarManager::UnhookConVarChange(IPluginContext *pContext, ConVar *cvar,
}
// Find the convar in the lookup trie
if (sm_trie_retrieve(m_ConVarCache, cvar->GetName(), reinterpret_cast<void **>(&info)))
if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info)))
{
// Get the forward
fwd = info->changeForward;
@ -351,14 +351,14 @@ void CConVarManager::UnhookConVarChange(IPluginContext *pContext, ConVar *cvar,
// If the forward doesn't exist, we can't unhook anything
if (fwd == NULL)
{
pContext->ThrowNativeError("Convar \"%s\" has no active hook", cvar->GetName());
pContext->ThrowNativeError("Convar \"%s\" has no active hook", pConVar->GetName());
return;
}
// Remove the function from the forward's list
if (!fwd->RemoveFunction(func))
{
pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", cvar->GetName());
pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", pConVar->GetName());
return;
}
@ -370,15 +370,15 @@ void CConVarManager::UnhookConVarChange(IPluginContext *pContext, ConVar *cvar,
info->changeForward = NULL;
// Put the back the original convar callback
cvar->InstallChangeCallback(info->origCallback);
pConVar->InstallChangeCallback(info->origCallback);
}
}
}
void CConVarManager::OnConVarChanged(ConVar *cvar, const char *oldValue)
void CConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
{
// If the values are the same...
if (strcmp(cvar->GetString(), oldValue) == 0)
if (strcmp(pConVar->GetString(), oldValue) == 0)
{
// Exit early in order to not trigger callbacks
return;
@ -388,7 +388,7 @@ void CConVarManager::OnConVarChanged(ConVar *cvar, const char *oldValue)
ConVarInfo *info;
// Find the convar in the lookup trie
sm_trie_retrieve(cache, cvar->GetName(), reinterpret_cast<void **>(&info));
sm_trie_retrieve(cache, pConVar->GetName(), reinterpret_cast<void **>(&info));
FnChangeCallback origCallback = info->origCallback;
IChangeableForward *fwd = info->changeForward;
@ -396,12 +396,12 @@ void CConVarManager::OnConVarChanged(ConVar *cvar, const char *oldValue)
// If there was a change callback installed previously, call it
if (origCallback)
{
origCallback(cvar, oldValue);
origCallback(pConVar, oldValue);
}
// Now call forwards in plugins that have hooked this
fwd->PushCell(info->handle);
fwd->PushString(cvar->GetString());
fwd->PushString(pConVar->GetString());
fwd->PushString(oldValue);
fwd->Execute(NULL);
}

View File

@ -85,17 +85,17 @@ public:
/**
* Add a function to call when the specified convar changes.
*/
void HookConVarChange(IPluginContext *pContext, ConVar *cvar, funcid_t funcid);
void HookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid);
/**
* Remove a function from the forward that will be called when the specified convar changes.
*/
void UnhookConVarChange(IPluginContext *pContext, ConVar *cvar, funcid_t funcid);
void UnhookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid);
private:
/**
* Static callback that Valve's ConVar class executes when the convar's value changes.
*/
static void OnConVarChanged(ConVar *cvar, const char *oldValue);
* Static callback that Valve's ConVar class executes when the convar's value changes.
*/
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
private:
HandleType_t m_ConVarType;
List<ConVarInfo *> m_ConVars;

363
core/EventManager.cpp Normal file
View File

@ -0,0 +1,363 @@
/**
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#include "EventManager.h"
#include "ForwardSys.h"
#include "HandleSys.h"
#include "PluginSys.h"
#include "sm_stringutil.h"
EventManager g_EventManager;
SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool);
typedef List<EventHook *> EventHookList;
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
EventManager::EventManager() : m_EventCopy(NULL), m_NotifyState(true)
{
/* Create an event lookup trie */
m_EventHooks = sm_trie_create();
}
EventManager::~EventManager()
{
sm_trie_destroy(m_EventHooks);
}
void EventManager::OnSourceModAllInitialized()
{
/* Add a hook for IGameEventManager2::FireEvent() */
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
HandleAccess sec;
/* Handle access security for 'GameEvent' handle type */
sec.access[HandleAccess_Read] = 0;
sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
/* Create the 'GameEvent' handle type */
m_EventType = g_HandleSys.CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL);
}
void EventManager::OnSourceModShutdown()
{
/* Remove hook for IGameEventManager2::FireEvent() */
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
/* Remove the 'GameEvent' handle type */
g_HandleSys.RemoveType(m_EventType, g_pCoreIdent);
/* Remove ourselves as listener for events */
gameevents->RemoveListener(this);
}
void EventManager::OnHandleDestroy(HandleType_t type, void *object)
{
if (type == m_EventType)
{
EventInfo *pInfo = static_cast<EventInfo *>(object);
if (pInfo->canDelete)
{
gameevents->FreeEvent(pInfo->pEvent);
delete pInfo;
}
}
}
void EventManager::OnPluginUnloaded(IPlugin *plugin)
{
EventHookList *pHookList;
EventHook *pHook;
// If plugin has an event hook list...
if (plugin->GetProperty("EventHooks", reinterpret_cast<void **>(&pHookList), true))
{
for (EventHookList::iterator iter = pHookList->begin(); iter != pHookList->end(); iter++)
{
pHook = (*iter);
if (--pHook->refCount == 0)
{
if (pHook->pPreHook)
{
g_Forwards.ReleaseForward(pHook->pPreHook);
}
if (pHook->pPostHook)
{
g_Forwards.ReleaseForward(pHook->pPostHook);
}
delete pHook;
}
}
delete pHookList;
}
}
/* IGameEventListener2::FireGameEvent */
void EventManager::FireGameEvent(IGameEvent *pEvent)
{
/* Not going to do anything here.
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
}
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
{
EventHook *pHook;
/* If we aren't listening to this event... */
if (!gameevents->FindListener(this, name))
{
/* Then add ourselves */
if (!gameevents->AddListener(this, name, true))
{
/* If event doesn't exist... */
return EventHookErr_InvalidEvent;
}
}
/* If a hook structure does not exist... */
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
{
EventHookList *pHookList;
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
/* Check plugin for an existing EventHook list */
if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
{
pHookList = new EventHookList();
plugin->SetProperty("EventHooks", pHookList);
}
/* Create new GameEventHook structure */
pHook = new EventHook();
if (mode == EventHookMode_Pre)
{
/* Create forward for a pre hook */
pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
/* Add to forward list */
pHook->pPreHook->AddFunction(pFunction);
} else {
/* Create forward for a post hook */
pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
/* Should we copy data from a pre hook to the post hook? */
pHook->postCopy = (mode == EventHookMode_Post);
/* Add to forward list */
pHook->pPostHook->AddFunction(pFunction);
}
/* Increase reference count */
pHook->refCount++;
/* Add hook structure to hook lists */
pHookList->push_back(pHook);
sm_trie_insert(m_EventHooks, name, pHook);
return EventHookErr_Okay;
}
/* Hook structure already exists at this point */
if (mode == EventHookMode_Pre)
{
/* Create pre hook forward if necessary */
if (!pHook->pPreHook)
{
pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
}
/* Add plugin function to forward list */
pHook->pPreHook->AddFunction(pFunction);
} else {
/* Create post hook forward if necessary */
if (!pHook->pPostHook)
{
pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
}
/* If postCopy is false, then we may want to set it to true */
if (!pHook->postCopy)
{
pHook->postCopy = (mode == EventHookMode_Post);
}
/* Add plugin function to forward list */
pHook->pPostHook->AddFunction(pFunction);
}
/* Increase reference count */
pHook->refCount++;
return EventHookErr_Okay;
}
EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
{
EventHook *pHook;
IChangeableForward **pEventForward;
/* If hook does not exist at all */
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
{
return EventHookErr_NotActive;
}
/* One forward to rule them all */
if (mode == EventHookMode_Pre)
{
pEventForward = &pHook->pPreHook;
} else {
pEventForward = &pHook->pPostHook;
}
/* Remove function from forward's list */
if (*pEventForward == NULL || !(*pEventForward)->RemoveFunction(pFunction))
{
return EventHookErr_InvalidCallback;
}
/* If forward's list contains 0 functions now, free it */
if ((*pEventForward)->GetFunctionCount() == 0)
{
g_Forwards.ReleaseForward(*pEventForward);
*pEventForward = NULL;
}
/* Decrement reference count */
if (--pHook->refCount == 0)
{
/* If reference count is now 0, free hook structure */
EventHookList *pHookList;
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
/* Get plugin's event hook list */
plugin->GetProperty("EventHooks", (void**)&pHookList);
/* Remove current structure from plugin's list */
pHookList->remove(pHook);
/* Delete entry in trie */
sm_trie_delete(m_EventHooks, name);
/* And finally free structure memory */
delete pHook;
}
return EventHookErr_Okay;
}
/* IGameEventManager2::FireEvent hook */
bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
{
EventHook *pHook;
IChangeableForward *pForward;
cell_t res = Pl_Continue;
if (!m_NotifyState)
{
RETURN_META_VALUE(MRES_IGNORED, true);
}
/* Get the event name, we're going to need this for passing to post hooks */
m_EventName = pEvent->GetName();
if (sm_trie_retrieve(m_EventHooks, m_EventName, reinterpret_cast<void **>(&pHook)))
{
pForward = pHook->pPreHook;
if (pForward)
{
EventInfo info = {pEvent, false};
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
pForward->PushCell(hndl);
pForward->PushString(m_EventName);
pForward->PushCell(bDontBroadcast);
pForward->Execute(&res, NULL);
HandleSecurity sec = { NULL, g_pCoreIdent };
g_HandleSys.FreeHandle(hndl, &sec);
}
if (pHook->postCopy)
{
m_EventCopy = gameevents->DuplicateEvent(pEvent);
}
if (res)
{
gameevents->FreeEvent(pEvent);
RETURN_META_VALUE(MRES_SUPERCEDE, false);
}
}
RETURN_META_VALUE(MRES_IGNORED, true);
}
/* IGameEventManager2::FireEvent post hook */
bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{
EventHook *pHook;
IChangeableForward *pForward;
Handle_t hndl;
if (!m_NotifyState)
{
m_NotifyState = true;
RETURN_META_VALUE(MRES_IGNORED, true);
}
if (sm_trie_retrieve(m_EventHooks, m_EventName, reinterpret_cast<void **>(&pHook)))
{
pForward = pHook->pPostHook;
if (pForward)
{
if (pHook->postCopy)
{
EventInfo info = {m_EventCopy, false};
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
pForward->PushCell(hndl);
} else {
pForward->PushCell(BAD_HANDLE);
}
pForward->PushString(m_EventName);
pForward->PushCell(bDontBroadcast);
pForward->Execute(NULL);
if (pHook->postCopy)
{
/* Free handle */
HandleSecurity sec = { NULL, g_pCoreIdent };
g_HandleSys.FreeHandle(hndl, &sec);
/* Free event structure */
gameevents->FreeEvent(m_EventCopy);
m_EventCopy = NULL;
}
}
}
RETURN_META_VALUE(MRES_IGNORED, true);
}

119
core/EventManager.h Normal file
View File

@ -0,0 +1,119 @@
/**
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $$
*/
#ifndef _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_
#define _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_
#include "sm_globals.h"
#include "sourcemm_api.h"
#include "sm_trie.h"
#include <sh_list.h>
#include <IHandleSys.h>
#include <IForwardSys.h>
#include <IPluginSys.h>
using namespace SourceHook;
//#define EVENT_PASSTHRU (1<<0)
#define EVENT_PASSTHRU_ALL (1<<1)
struct EventInfo
{
IGameEvent *pEvent;
bool canDelete;
};
struct EventHook
{
EventHook()
{
pPreHook = NULL;
pPostHook = NULL;
postCopy = false;
refCount = 0;
}
IChangeableForward *pPreHook;
IChangeableForward *pPostHook;
bool postCopy;
unsigned int refCount;
};
enum EventHookMode
{
EventHookMode_Pre,
EventHookMode_Post,
EventHookMode_PostNoCopy
};
enum EventHookError
{
EventHookErr_Okay = 0, /**< No error */
EventHookErr_InvalidEvent, /**< Specified event does not exist */
EventHookErr_NotActive, /**< Specified event has no active hook */
EventHookErr_InvalidCallback, /**< Specified event does not fire specified callback */
};
class EventManager :
public SMGlobalClass,
public IHandleTypeDispatch,
public IPluginsListener,
public IGameEventListener2
{
public:
EventManager();
~EventManager();
public: // SMGlobalClass
void OnSourceModAllInitialized();
void OnSourceModShutdown();
public: // IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object);
public: // IPluginsListener
void OnPluginUnloaded(IPlugin *plugin);
public: // IGameEventListener2
void FireGameEvent(IGameEvent *pEvent);
public:
/**
* Get the 'GameEvent' handle type ID.
*/
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;
}
public:
EventHookError HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
EventHookError UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
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;
IGameEvent *m_EventCopy;
const char *m_EventName;
};
extern EventManager g_EventManager;
#endif // _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_

View File

@ -227,6 +227,10 @@
RelativePath="..\CUserMessages.cpp"
>
</File>
<File
RelativePath="..\EventManager.cpp"
>
</File>
<File
RelativePath="..\sm_autonatives.cpp"
>
@ -317,6 +321,10 @@
RelativePath="..\CUserMessages.h"
>
</File>
<File
RelativePath="..\EventManager.h"
>
</File>
<File
RelativePath="..\sm_autonatives.h"
>
@ -689,6 +697,10 @@
RelativePath="..\smn_entities.cpp"
>
</File>
<File
RelativePath="..\smn_events.cpp"
>
</File>
<File
RelativePath="..\smn_filesystem.cpp"
>

View File

@ -62,15 +62,15 @@ static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
g_ConVarManager.HookConVarChange(pContext, cvar, static_cast<funcid_t>(params[2]));
g_ConVarManager.HookConVarChange(pContext, pConVar, static_cast<funcid_t>(params[2]));
return 1;
}
@ -79,15 +79,15 @@ static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *para
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
g_ConVarManager.UnhookConVarChange(pContext, cvar, static_cast<funcid_t>(params[2]));
g_ConVarManager.UnhookConVarChange(pContext, pConVar, static_cast<funcid_t>(params[2]));
return 1;
}
@ -96,30 +96,30 @@ static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
return cvar->GetBool();
return pConVar->GetBool();
}
static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
return cvar->GetInt();
return pConVar->GetInt();
}
/* This handles both SetConVarBool() and SetConVarInt() */
@ -127,15 +127,15 @@ static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
cvar->SetValue(params[2]);
pConVar->SetValue(params[2]);
return 1;
}
@ -144,15 +144,15 @@ static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
float value = cvar->GetFloat();
float value = pConVar->GetFloat();
return sp_ftoc(value);
}
@ -161,16 +161,16 @@ static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
float value = sp_ctof(params[2]);
cvar->SetValue(value);
pConVar->SetValue(value);
return 1;
}
@ -179,15 +179,15 @@ static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
pContext->StringToLocalUTF8(params[2], params[3], cvar->GetString(), NULL);
pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL);
return 1;
}
@ -196,9 +196,9 @@ static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
@ -207,7 +207,7 @@ static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
char *value;
pContext->LocalToString(params[2], &value);
cvar->SetValue(value);
pConVar->SetValue(value);
return 1;
}
@ -216,30 +216,30 @@ static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
return cvar->GetFlags();
return pConVar->GetFlags();
}
static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
cvar->SetFlags(params[2]);
pConVar->SetFlags(params[2]);
return 1;
}
@ -248,9 +248,9 @@ static cell_t sm_GetConVarMin(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
@ -262,7 +262,7 @@ static cell_t sm_GetConVarMin(IPluginContext *pContext, const cell_t *params)
pContext->LocalToPhysAddr(params[2], &addr);
hasMin = cvar->GetMin(min);
hasMin = pConVar->GetMin(min);
*addr = sp_ftoc(min);
return hasMin;
@ -272,9 +272,9 @@ static cell_t sm_GetConVarMax(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
@ -286,7 +286,7 @@ static cell_t sm_GetConVarMax(IPluginContext *pContext, const cell_t *params)
pContext->LocalToPhysAddr(params[2], &addr);
hasMax = cvar->GetMax(max);
hasMax = pConVar->GetMax(max);
*addr = sp_ftoc(max);
return hasMax;
@ -296,15 +296,15 @@ static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
pContext->StringToLocalUTF8(params[2], params[3], cvar->GetName(), NULL);
pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL);
return 1;
}
@ -313,15 +313,15 @@ static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
ConVar *cvar;
ConVar *pConVar;
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&cvar))
if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid ConVar Handle %x (error %d)", hndl, err);
}
cvar->Revert();
pConVar->Revert();
return 1;
}

337
core/smn_events.cpp Normal file
View File

@ -0,0 +1,337 @@
/**
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#include "sm_globals.h"
#include "sourcemm_api.h"
#include "HandleSys.h"
#include "EventManager.h"
static cell_t sm_HookEvent(IPluginContext *pContext, const cell_t *params)
{
char *name;
IPluginFunction *pFunction;
pContext->LocalToString(params[1], &name);
pFunction = pContext->GetFunctionById(params[2]);
if (!pFunction)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
}
if (g_EventManager.HookEvent(name, pFunction, static_cast<EventHookMode>(params[3])) == EventHookErr_InvalidEvent)
{
return pContext->ThrowNativeError("Game event \"%s\" does not exist", name);
}
return 1;
}
static cell_t sm_UnhookEvent(IPluginContext *pContext, const cell_t *params)
{
char *name;
IPluginFunction *pFunction;
pContext->LocalToString(params[1], &name);
pFunction = pContext->GetFunctionById(params[2]);
if (!pFunction)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
}
EventHookError err = g_EventManager.UnhookEvent(name, pFunction, static_cast<EventHookMode>(params[3]));
/* Possible errors that UnhookGameEvent can return */
if (err == EventHookErr_NotActive)
{
return pContext->ThrowNativeError("Game event \"%s\" has no active hook", name);
} else if (err == EventHookErr_InvalidCallback) {
return pContext->ThrowNativeError("Invalid hook callback specified for game event \"%s\"", name);
}
return 1;
}
static cell_t sm_CreateEvent(IPluginContext *pContext, const cell_t *params)
{
IGameEvent *pEvent;
EventInfo *pInfo;
char *name;
pContext->LocalToString(params[1], &name);
pEvent = gameevents->CreateEvent(name, true);
if (pEvent)
{
pInfo = new EventInfo;
pInfo->pEvent = pEvent;
pInfo->canDelete = true;
return g_HandleSys.CreateHandle(g_EventManager.GetHandleType(), pInfo, pContext->GetIdentity(), g_pCoreIdent, NULL);
}
return BAD_HANDLE;
}
static cell_t sm_FireEvent(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
if ((params[3] & EVENT_PASSTHRU_ALL) == false)
{
/* Set whether or not SourceMod plugins should be notified */
g_EventManager.SetNotifyState(false);
}
/* Fire game event */
gameevents->FireEvent(pInfo->pEvent, params[2] ? true : false);
pInfo->canDelete = false;
/* Free handle on game event */
HandleSecurity sec = { pContext->GetIdentity(), g_pCoreIdent };
g_HandleSys.FreeHandle(hndl, &sec);
/* Free EventInfo memory */
delete pInfo;
return 1;
}
static cell_t sm_CancelCreatedEvent(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
gameevents->FreeEvent(pInfo->pEvent);
// Free GameEventInfo memory
delete pInfo;
// Free handle on game event
HandleSecurity sec = { pContext->GetIdentity(), g_pCoreIdent };
g_HandleSys.FreeHandle(hndl, &sec);
return 1;
}
static cell_t sm_GetEventName(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
pContext->StringToLocalUTF8(params[2], params[3], pInfo->pEvent->GetName(), NULL);
return 1;
}
static cell_t sm_GetEventBool(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
char *key;
pContext->LocalToString(params[2], &key);
return pInfo->pEvent->GetBool(key);
}
static cell_t sm_GetEventInt(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
char *key;
pContext->LocalToString(params[2], &key);
return pInfo->pEvent->GetInt(key);
}
static cell_t sm_GetEventFloat(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
char *key;
pContext->LocalToString(params[2], &key);
float value = pInfo->pEvent->GetFloat(key);
return sp_ftoc(value);
}
static cell_t sm_GetEventString(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
char *key;
pContext->LocalToString(params[2], &key);
pContext->StringToLocalUTF8(params[3], params[4], pInfo->pEvent->GetString(key), NULL);
return 1;
}
static cell_t sm_SetEventBool(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
char *key;
pContext->LocalToString(params[2], &key);
pInfo->pEvent->SetBool(key, params[3] ? true : false);
return 1;
}
static cell_t sm_SetEventInt(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
char *key;
pContext->LocalToString(params[2], &key);
pInfo->pEvent->SetInt(key, params[3]);
return 1;
}
static cell_t sm_SetEventFloat(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
char *key;
pContext->LocalToString(params[2], &key);
float value = sp_ctof(params[3]);
pInfo->pEvent->SetFloat(key, value);
return 1;
}
static cell_t sm_SetEventString(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
if ((err=g_HandleSys.ReadHandle(hndl, g_EventManager.GetHandleType(), NULL, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid GameEvent Handle %x (error %d)", hndl, err);
}
char *key, *value;
pContext->LocalToString(params[2], &key);
pContext->LocalToString(params[3], &value);
pInfo->pEvent->SetString(key, value);
return 1;
}
REGISTER_NATIVES(gameEventNatives)
{
{"HookEvent", sm_HookEvent},
{"UnhookEvent", sm_UnhookEvent},
{"CreateEvent", sm_CreateEvent},
{"FireEvent", sm_FireEvent},
{"CancelCreatedEvent", sm_CancelCreatedEvent},
{"GetEventName", sm_GetEventName},
{"GetEventBool", sm_GetEventBool},
{"GetEventInt", sm_GetEventInt},
{"GetEventFloat", sm_GetEventFloat},
{"GetEventString", sm_GetEventString},
{"SetEventBool", sm_SetEventBool},
{"SetEventInt", sm_SetEventInt},
{"SetEventFloat", sm_SetEventFloat},
{"SetEventString", sm_SetEventString},
{NULL, NULL}
};

View File

@ -207,7 +207,7 @@ native GetCmdArgString(String:buffer[], maxlength);
* @param name Name of new convar.
* @param defaultValue String containing the default value of new convar.
* @param helpText Optional description of the convar.
* @param flags Optional bitstream of flags determining how the convar should be handled. (See FCVAR_* constants for more details)
* @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details.
* @param hasMin Optional boolean that determines if the convar has a minimum value.
* @param min Minimum floating point value that the convar can have if hasMin is true.
* @param hasMax Optional boolean that determines if the convar has a maximum value.

205
plugins/include/events.inc Normal file
View File

@ -0,0 +1,205 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is part of the SourceMod/SourcePawn SDK. This file may only be used
* or modified under the Terms and Conditions of its License Agreement, which is found
* in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins
* may change at any time. To view the latest information, see:
* http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#if defined _events_included
#endinput
#endif
#define _events_included
/**
* Flags for firing game events
*/
#define EVENT_PASSTHRU_ALL (1<<1) /**< Event will pass through other SourceMM plugins AND SourceMod */
/**
* Event hook modes determining how hooking should be handled
*/
enum EventHookMode
{
EventHookMode_Pre, /**< Hook callback fired before event is fired */
EventHookMode_Post, /**< Hook callback fired after event is fired */
EventHookMode_PostNoCopy /**< Hook callback fired after event is fired, but event data won't be copied */
};
funcenum EventHook
{
/**
* Called when a game event is fired.
*
* @param event Handle to event. This could be INVALID_HANDLE if every plugin hooking
* this event has set the hook mode EventHookMode_PostNoCopy.
* @param name String containing the name of the event.
* @param dontBroadcast True if event was not broadcast to clients, false otherwise.
* @return Ignored for post hooks. Plugin_Handled will block event if hooked as pre.
*/
Action:public(Handle:event, const String:name[], bool:dontBroadcast),
/**
* Called when a game event is fired.
*
* @param event Handle to event. This could be INVALID_HANDLE if every plugin hooking
* this event has set the hook mode EventHookMode_PostNoCopy.
* @param name String containing the name of the event.
* @param dontBroadcast True if event was not broadcast to clients, false otherwise.
* @noreturn
*/
public(Handle:event, const String:name[], bool:dontBroadcast),
};
/**
* Creates a hook for when a game event is fired.
*
* @param name Name of event.
* @param callback An EventHook function pointer.
* @param mode Optional EventHookMode determining the type of hook.
* @noreturn
* @error Invalid event name or invalid callback function.
*/
native HookEvent(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post);
/**
* Removes a hook for when a game event is fired.
*
* @param name Name of event.
* @param callback An EventHook function pointer.
* @param mode Optional EventHookMode determining the type of hook.
* @noreturn
* @error Invalid callback function or no active hook for specified event.
*/
native UnhookEvent(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post);
/**
* Creates a game event to be fired later.
*
* @param name Name of event.
* @return Handle to event or INVALID_HANDLE if event doesn't exist.
*/
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.
* @noreturn
* @error Invalid or corrupt Handle.
*/
native FireEvent(Handle:event, bool:dontBroadcast=false, flags=0);
/**
* Cancels a previously created game event that has not been fired.
*
* @param event Handled to the event.
* @noreturn
* @error Invalid or corrupt Handle.
*/
native CancelCreatedEvent(Handle:event);
/**
* Returns the boolean value of a game event's key.
*
* @param event Handle to the event.
* @param key Name of event key.
* @return The boolean value of the specfied event key.
* @error Invalid or corrupt Handle.
*/
native bool:GetEventBool(Handle:event, const String:key[]);
/**
* Sets the boolean value of a game event's key.
*
* @param event Handle to the event.
* @param key Name of event key.
* @param value New boolean value.
* @noreturn
* @error Invalid or corrupt Handle.
*/
native SetEventBool(Handle:event, const String:key[], bool:value);
/**
* Returns the integer value of a game event's key.
*
* @param event Handle to the event.
* @param key Name of event key.
* @return The integer value of the specfied event key.
* @error Invalid or corrupt Handle.
*/
native GetEventInt(Handle:event, const String:key[]);
/**
* Sets the integer value of a game event's key.
*
* @param event Handle to the event.
* @param key Name of event key.
* @param value New integer value.
* @noreturn
* @error Invalid or corrupt Handle.
*/
native SetEventInt(Handle:event, const String:key[], value);
/**
* Returns the floating point value of a game event's key.
*
* @param event Handle to the event.
* @param key Name of event key.
* @return The floating point value of the specfied event key.
* @error Invalid or corrupt Handle.
*/
native Float:GetEventFloat(Handle:event, const String:key[]);
/**
* Sets the floating point value of a game event's key.
*
* @param event Handle to the event.
* @param key Name of event key.
* @param value New floating point value.
* @noreturn
* @error Invalid or corrupt Handle.
*/
native SetEventFloat(Handle:event, const String:key[], Float:value);
/**
* Retrieves the string value of a game event's key.
*
* @param event Handle to the event.
* @param key Name of event key.
* @param value Buffer to store the value of the specified event key.
* @param maxlength Maximum length of string buffer.
* @noreturn
* @error Invalid or corrupt Handle.
*/
native GetEventString(Handle:event, const String:key[], String:value[], maxlength);
/**
* Sets the string value of a game event's key.
*
* @param event Handle to the event.
* @param key Name of event key.
* @param value New string value.
* @noreturn
* @error Invalid or corrupt Handle.
*/
native SetEventString(Handle:event, const String:key[], const String:value[]);
/**
* Retrieves the name of a game event.
*
* @param event Handle to the event.
* @param value Buffer to store the name of the event.
* @param maxlength Maximum length of string buffer.
* @noreturn
* @error Invalid or corrupt Handle.
*/
native GetEventName(Handle:event, String:name[], maxlength);

View File

@ -37,6 +37,8 @@ struct Plugin
#include <bitbuffer>
#include <sorting>
#include <clients>
#include <usermessages>
#include <events>
/**
* Declare this as a struct in your plugin to expose its information.
@ -219,6 +221,5 @@ native GetGameDescription(String:buffer[], maxlength, bool:original=false);
*/
native GetCurrentMap(String:buffer[], maxlength);
#include <usermessages>
#include <helpers>
#include <entity>