bool UsrMessageNatives::FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter) { MsgWrapperList *pList; MsgWrapperIter _iter; MsgListenerWrapper *pListener; IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext()); if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList))) { return false; } for (_iter=pList->begin(); _iter!=pList->end(); _iter++) { pListener = (*_iter); if ((msgid == pListener->GetMessageId()) && (intercept == pListener->IsInterceptHook()) && (pHook == pListener->GetHookedFunction())) { *iter = _iter; return true; } } return false; }
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) { /* Only check convars that have not been created by SourceMod's core */ ConVarInfo *pInfo; if (!convar_cache_lookup(name, &pInfo)) { return; } HandleSecurity sec(NULL, g_pCoreIdent); /* Remove it from our cache */ m_ConVars.remove(pInfo); convar_cache.remove(name); /* Now make sure no plugins are referring to this pointer */ IPluginIterator *pl_iter = scripts->GetPluginIterator(); while (pl_iter->MorePlugins()) { IPlugin *pl = pl_iter->GetPlugin(); ConVarList *pConVarList; if (pl->GetProperty("ConVarList", (void **)&pConVarList, true) && pConVarList != NULL) { pConVarList->remove(pInfo->pVar); } pl_iter->NextPlugin(); } /* Free resources */ handlesys->FreeHandle(pInfo->handle, &sec); delete pInfo; }
void EntityOutputManager::CleanUpHook(omg_hooks *hook) { FreeHooks.push(hook); OnHookRemoved(); IPlugin *pPlugin = plsys->FindPluginByContext(hook->pf->GetParentContext()->GetContext()); SourceHook::List<omg_hooks *> *pList = NULL; if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList) { return; } SourceHook::List<omg_hooks *>::iterator p_iter = pList->begin(); omg_hooks *pluginHook; while (p_iter != pList->end()) { pluginHook = (omg_hooks *)*p_iter; if (pluginHook == hook) { p_iter = pList->erase(p_iter); } else { p_iter++; } } }
MTRand *RandObjForPlugin(IPluginContext *ctx) { IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext()); MTRand *mtrand; if (!plugin->GetProperty("core.logic.mtrand", (void**)&mtrand)) { mtrand = new MTRand(); plugin->SetProperty("core.logic.mtrand", mtrand); } return mtrand; }
static cell_t SQL_ExecuteTransaction(IPluginContext *pContext, const cell_t *params) { HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); IDatabase *db = NULL; HandleError err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db); if (err != HandleError_None) return pContext->ThrowNativeError("Invalid database handle %x (error: %d)", params[1], err); Transaction *txn; if ((err = handlesys->ReadHandle(params[2], hTransactionType, &sec, (void **)&txn)) != HandleError_None) return pContext->ThrowNativeError("Invalid transaction handle %x (error %d)", params[2], err); if (!db->GetDriver()->IsThreadSafe()) return pContext->ThrowNativeError("Driver \"%s\" is not thread safe!", db->GetDriver()->GetIdentifier()); IPluginFunction *onSuccess = NULL; IPluginFunction *onError = NULL; if (params[3] != -1 && ((onSuccess = pContext->GetFunctionById(params[3])) == NULL)) return pContext->ThrowNativeError("Function id %x is invalid", params[3]); if (params[4] != -1 && ((onError = pContext->GetFunctionById(params[4])) == NULL)) return pContext->ThrowNativeError("Function id %x is invalid", params[4]); cell_t data = params[5]; PrioQueueLevel priority = PrioQueue_Normal; if (params[6] == (cell_t)PrioQueue_High) priority = PrioQueue_High; else if (params[6] == (cell_t)PrioQueue_Low) priority = PrioQueue_Low; TTransactOp *op = new TTransactOp(db, txn, params[2], pContext->GetIdentity(), onSuccess, onError, data); // The handle owns the underlying Transaction object, but we want to close // the plugin's view both to ensure reliable access for us and to prevent // further tampering on the main thread. To do this, TTransactOp clones the // transaction handle and automatically closes it. Therefore, it's safe to // close the plugin's handle here. handlesys->FreeHandle(params[2], &sec); IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); if (pPlugin->GetProperty("DisallowDBThreads", NULL) || !g_DBMan.AddToThreadQueue(op, priority)) { // Do everything right now. op->RunThreadPart(); op->RunThinkPart(); op->Destroy(); } return 0; }
static cell_t SQL_TQuery(IPluginContext *pContext, const cell_t *params) { IDatabase *db = NULL; HandleError err; if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db)) != HandleError_None) { return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err); } if (!db->GetDriver()->IsThreadSafe()) { return pContext->ThrowNativeError("Driver \"%s\" is not thread safe!", db->GetDriver()->GetIdentifier()); } IPluginFunction *pf = pContext->GetFunctionById(params[2]); if (!pf) { return pContext->ThrowNativeError("Function id %x is invalid", params[2]); } char *query; pContext->LocalToString(params[3], &query); cell_t data = params[4]; PrioQueueLevel level = PrioQueue_Normal; if (params[5] == (cell_t)PrioQueue_High) { level = PrioQueue_High; } else if (params[5] == (cell_t)PrioQueue_Low) { level = PrioQueue_Low; } IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); TQueryOp *op = new TQueryOp(db, pf, query, data); if (pPlugin->GetProperty("DisallowDBThreads", NULL) || !g_DBMan.AddToThreadQueue(op, level)) { /* Do everything right now */ op->RunThreadPart(); op->RunThinkPart(); op->Destroy(); } return 1; }
bool UsrMessageNatives::DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter) { MsgWrapperList *pList; MsgListenerWrapper *pListener; IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext()); if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList))) { return false; } pListener = (*iter); pList->erase(iter); m_FreeListeners.push(pListener); return true; }
cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params) { if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) { return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection"); } char *display; pContext->LocalToString(params[3], &display); /* Register a callback */ ItemHandler *pItem = new ItemHandler; pItem->isAutoMenu = false; pItem->forward = forwards->CreateForwardEx(NULL, ET_Ignore, 5, NULL, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_Cell); pItem->forward->AddFunction(pContext, static_cast<funcid_t>(params[1])); char info[20]; AutoMenuData *data = new AutoMenuData; data->datavalue = params[2]; data->handler = pItem; UTIL_Format(info, sizeof(info), "%x", data); ItemDrawInfo draw(display, 0); g_CookieManager.clientMenu->AppendItem(info, draw); /* Track this in case the plugin unloads */ IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext()); SourceHook::List<char *> *pList = NULL; if (!pPlugin->GetProperty("SettingsMenuItems", (void **)&pList, false) || !pList) { pList = new SourceHook::List<char *>; pPlugin->SetProperty("SettingsMenuItems", pList); } char *copyarray = new char[strlen(display)+1]; UTIL_Format(copyarray, strlen(display)+1, "%s", display); pList->push_back(copyarray); return 0; }
cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params) { g_ClientPrefs.AttemptReconnection(); char *display; pContext->LocalToString(params[3], &display); /* Register a callback */ ItemHandler *pItem = new ItemHandler; pItem->isAutoMenu = false; pItem->forward = forwards->CreateForwardEx(NULL, ET_Ignore, 5, NULL, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_Cell); pItem->forward->AddFunction(pContext, static_cast<funcid_t>(params[1])); char info[20]; AutoMenuData *data = new AutoMenuData; data->datavalue = params[2]; data->handler = pItem; g_pSM->Format(info, sizeof(info), "%x", data); ItemDrawInfo draw(display, 0); g_CookieManager.clientMenu->AppendItem(info, draw); /* Track this in case the plugin unloads */ IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext()); ke::Vector<char *> *pList = NULL; if (!pPlugin->GetProperty("SettingsMenuItems", (void **)&pList, false) || !pList) { pList = new ke::Vector<char *>; pPlugin->SetProperty("SettingsMenuItems", pList); } char *copyarray = new char[strlen(display)+1]; g_pSM->Format(copyarray, strlen(display)+1, "%s", display); pList->append(copyarray); return 0; }
void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) { /* Whoa, first get its information struct */ ConCmdInfo *pInfo; if (!m_Cmds.retrieve(name, &pInfo)) return; CmdHookList::iterator iter = pInfo->hooks.begin(); while (iter != pInfo->hooks.end()) { CmdHook *hook = *iter; IPluginContext *pContext = hook->pf->GetParentContext(); IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); // The list is guaranteed to exist. PluginHookList *list; pPlugin->GetProperty("CommandList", (void **)&list, false); for (PluginHookList::iterator hiter = list->begin(); hiter != list->end(); hiter++) { if (*hiter == hook) { list->erase(hiter); break; } } if (hook->admin) hook->admin->group->hooks.remove(hook); iter = pInfo->hooks.erase(iter); delete hook; } RemoveConCmd(pInfo, name, is_read_safe, false); }
void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar) { ConVarList *pConVarList; ConVarList::iterator iter; bool inserted = false; const char *orig = pConVar->GetName(); IPlugin *plugin = scripts->FindPluginByContext(pContext->GetContext()); /* Check plugin for an existing convar list */ if (!plugin->GetProperty("ConVarList", (void **)&pConVarList)) { pConVarList = new ConVarList(); plugin->SetProperty("ConVarList", pConVarList); } else if (pConVarList->find(pConVar) != pConVarList->end()) { /* If convar is already in list, then don't add it */ return; } /* Insert convar into list which is sorted alphabetically */ for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++) { if (strcmp(orig, (*iter)->GetName()) < 0) { pConVarList->insert(iter, pConVar); inserted = true; break; } } if (!inserted) { pConVarList->push_back(pConVar); } }
void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist) { List<CmdHook *>::iterator iter = cmdlist.begin(); while (iter != cmdlist.end()) { CmdHook *pHook = (*iter); IPluginContext *pContext = pHook->pf->GetParentContext(); IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); CmdList *pList = NULL; //gaben if (!pPlugin->GetProperty("CommandList", (void **)&pList, false) || !pList) { continue; } CmdList::iterator p_iter = pList->begin(); while (p_iter != pList->end()) { PlCmdInfo &cmd = (*p_iter); if (cmd.pHook == pHook) { p_iter = pList->erase(p_iter); } else { p_iter++; } } delete pHook->pAdmin; delete pHook; iter = cmdlist.erase(iter); } }
MsgListenerWrapper *UsrMessageNatives::CreateListener(IPluginContext *pCtx) { MsgWrapperList *pList; MsgListenerWrapper *pListener; IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext()); if (m_FreeListeners.empty()) { pListener = new MsgListenerWrapper; } else { pListener = m_FreeListeners.front(); m_FreeListeners.pop(); } if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList))) { pList = new List<MsgListenerWrapper *>; pl->SetProperty("MsgListeners", pList); } pList->push_back(pListener); return pListener; }
// HookSingleEntityOutput(int ent, const char[] output, EntityOutput function, bool once); cell_t HookSingleEntityOutput(IPluginContext *pContext, const cell_t *params) { if (!g_OutputManager.IsEnabled()) { return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details"); } CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(params[1]); if (!pEntity) { return pContext->ThrowNativeError("Invalid Entity index %i (%i)", gamehelpers->ReferenceToIndex(params[1]), params[1]); } const char *classname = gamehelpers->GetEntityClassname(pEntity); char *outputname; pContext->LocalToString(params[2], &outputname); OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, true); //Check for an existing identical hook SourceHook::List<omg_hooks *>::iterator _iter; omg_hooks *hook; IPluginFunction *pFunction; pFunction = pContext->GetFunctionById(params[3]); for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) { hook = (omg_hooks *)*_iter; if (hook->pf == pFunction && hook->entity_ref == gamehelpers->EntityToReference(pEntity)) { return 0; } } hook = g_OutputManager.NewHook(); hook->entity_ref = gamehelpers->EntityToReference(pEntity); hook->only_once= !!params[4]; hook->pf = pFunction; hook->m_parent = pOutputName; hook->in_use = false; hook->delete_me = false; pOutputName->hooks.push_back(hook); g_OutputManager.OnHookAdded(); IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext()); SourceHook::List<omg_hooks *> *pList = NULL; if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList) { pList = new SourceHook::List<omg_hooks *>; pPlugin->SetProperty("OutputHookList", pList); } pList->push_back(hook); return 1; }
void ConVarManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) { int argcount = command->ArgC(); if (argcount >= 3) { bool wantReset = false; /* Get plugin index that was passed */ const char *arg = command->Arg(2); if (argcount >= 4 && strcmp(arg, "reset") == 0) { wantReset = true; arg = command->Arg(3); } /* Get plugin object */ IPlugin *plugin = scripts->FindPluginByConsoleArg(arg); if (!plugin) { UTIL_ConsolePrint("[SM] Plugin \"%s\" was not found.", arg); return; } /* Get plugin name */ const sm_plugininfo_t *plinfo = plugin->GetPublicInfo(); const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : plugin->GetFilename(); ConVarList *pConVarList; ConVarList::iterator iter; /* If no convar list... */ if (!plugin->GetProperty("ConVarList", (void **)&pConVarList)) { UTIL_ConsolePrint("[SM] No convars found for: %s", plname); return; } if (!wantReset) { UTIL_ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname); UTIL_ConsolePrint(" %-32.31s %s", "[Name]", "[Value]"); } /* Iterate convar list and display/reset each one */ for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++) { /*const */ConVar *pConVar = const_cast<ConVar *>(*iter); if (!wantReset) { UTIL_ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString()); } else { pConVar->Revert(); } } if (wantReset) { UTIL_ConsolePrint("[SM] Reset %d convars for: %s", pConVarList->size(), plname); } return; } /* Display usage of subcommand */ UTIL_ConsolePrint("[SM] Usage: sm cvars [reset] <plugin #>"); }
static cell_t ConnectToDbAsync(IPluginContext *pContext, const cell_t *params, AsyncCallbackMode acm) { IPluginFunction *pf = pContext->GetFunctionById(params[1]); if (!pf) { return pContext->ThrowNativeError("Function id %x is invalid", params[1]); } char *conf; pContext->LocalToString(params[2], &conf); IDBDriver *driver = NULL; const DatabaseInfo *pInfo = g_DBMan.FindDatabaseConf(conf); char error[255]; if (pInfo != NULL) { if (pInfo->driver[0] == '\0') { driver = g_DBMan.GetDefaultDriver(); } else { driver = g_DBMan.FindOrLoadDriver(pInfo->driver); } if (!driver) { g_pSM->Format(error, sizeof(error), "Could not find driver \"%s\"", pInfo->driver[0] == '\0' ? g_DBMan.GetDefaultDriverName() : pInfo->driver); } else if (!driver->IsThreadSafe()) { g_pSM->Format(error, sizeof(error), "Driver \"%s\" is not thread safe!", driver->GetIdentifier()); } } else { g_pSM->Format(error, sizeof(error), "Could not find database conf \"%s\"", conf); } if (!pInfo || !driver) { pf->PushCell(BAD_HANDLE); if (acm == ACM_Old) pf->PushCell(BAD_HANDLE); pf->PushString(error); pf->PushCell(0); pf->Execute(NULL); return 0; } /* HACK! Add us to the dependency list */ IExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity()); if (pExt) { g_Extensions.BindChildPlugin(pExt, scripts->FindPluginByContext(pContext->GetContext())); } /* Finally, add to the thread if we can */ TConnectOp *op = new TConnectOp(pf, driver, conf, acm, params[3]); IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); if (pPlugin->GetProperty("DisallowDBThreads", NULL) || !g_DBMan.AddToThreadQueue(op, PrioQueue_High)) { /* Do everything right now */ op->RunThreadPart(); op->RunThinkPart(); op->Destroy(); } return 1; }
cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params) { g_ClientPrefs.AttemptReconnection(); Handle_t hndl = static_cast<Handle_t>(params[1]); HandleError err; HandleSecurity sec; sec.pOwner = NULL; sec.pIdentity = myself->GetIdentity(); Cookie *pCookie; if ((err = handlesys->ReadHandle(hndl, g_CookieType, &sec, (void **)&pCookie)) != HandleError_None) { return pContext->ThrowNativeError("Invalid Cookie handle %x (error %d)", hndl, err); } /* Register a callback */ ItemHandler *pItem = new ItemHandler; pItem->isAutoMenu = true; pItem->autoMenuType = (CookieMenu)params[2]; /* User passed a function id for a callback */ if (params[4] != -1) { pItem->forward = forwards->CreateForwardEx(NULL, ET_Ignore, 5, NULL, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_Cell); pItem->forward->AddFunction(pContext, static_cast<funcid_t>(params[4])); } else { pItem->forward = NULL; } char *display; pContext->LocalToString(params[3], &display); ItemDrawInfo draw(display, 0); char info[20]; AutoMenuData *data = new AutoMenuData; data->datavalue = params[5]; data->pCookie = pCookie; data->type = (CookieMenu)params[2]; data->handler = pItem; g_pSM->Format(info, sizeof(info), "%x", data); g_CookieManager.clientMenu->AppendItem(info, draw); /* Track this in case the plugin unloads */ IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext()); ke::Vector<char *> *pList = NULL; if (!pPlugin->GetProperty("SettingsMenuItems", (void **)&pList, false) || !pList) { pList = new ke::Vector<char *>; pPlugin->SetProperty("SettingsMenuItems", pList); } char *copyarray = new char[strlen(display)+1]; g_pSM->Format(copyarray, strlen(display)+1, "%s", display); pList->append(copyarray); return 0; }
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_Hook, 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 */ if (!plugin->GetProperty("EventHooks", (void**)&pHookList)) { return EventHookErr_NotActive; } /* Make sure the event was actually being hooked */ if (pHookList->find(pHook) == pHookList->end()) { return EventHookErr_NotActive; } /* 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; }
// HookEntityOutput(const char[] classname, const char[] output, EntityOutput function); cell_t HookEntityOutput(IPluginContext *pContext, const cell_t *params) { if (!g_OutputManager.IsEnabled()) { return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details"); } //Find or create the base structures for this classname and the output char *classname; pContext->LocalToString(params[1], &classname); char *outputname; pContext->LocalToString(params[2], &outputname); OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, true); //Check for an existing identical hook SourceHook::List<omg_hooks *>::iterator _iter; omg_hooks *hook; IPluginFunction *pFunction; pFunction = pContext->GetFunctionById(params[3]); for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) { hook = (omg_hooks *)*_iter; if (hook->pf == pFunction && hook->entity_ref == -1) { //already hooked to this function... //throw an error or just let them get away with stupidity? // seems like poor coding if they dont know if something is hooked or not return 0; } } hook = g_OutputManager.NewHook(); hook->entity_ref = -1; hook->pf = pFunction; hook->m_parent = pOutputName; hook->in_use = false; hook->delete_me = false; pOutputName->hooks.push_back(hook); g_OutputManager.OnHookAdded(); IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext()); SourceHook::List<omg_hooks *> *pList = NULL; if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList) { pList = new SourceHook::List<omg_hooks *>; pPlugin->SetProperty("OutputHookList", pList); } pList->push_back(hook); return 1; }