static cell_t sm_RemoveAllFromForward(IPluginContext *pContext, const cell_t *params) { Handle_t fwdHandle = static_cast<Handle_t>(params[1]); Handle_t plHandle = static_cast<Handle_t>(params[2]); HandleError err; IChangeableForward *pForward; IPlugin *pPlugin; if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward)) != HandleError_None) { return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err); } if (plHandle == 0) { pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext()); } else { pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err); if (!pPlugin) { return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err); } } return pForward->RemoveFunctionsOfPlugin(pPlugin); }
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue) { /* If the values are the same, exit early in order to not trigger callbacks */ if (strcmp(pConVar->GetString(), oldValue) == 0) { return; } ConVarInfo *pInfo; /* Find the convar in the lookup trie */ if (!convar_cache_lookup(pConVar->GetName(), &pInfo)) { return; } IChangeableForward *pForward = pInfo->pChangeForward; if (pInfo->changeListeners.size() != 0) { for (auto i = pInfo->changeListeners.begin(); i != pInfo->changeListeners.end(); i++) (*i)->OnConVarChanged(pConVar, oldValue, flOldValue); } if (pForward != NULL) { ConVarReentrancyGuard guard(pConVar); /* Now call forwards in plugins that have hooked this */ pForward->PushCell(pInfo->handle); pForward->PushString(oldValue); pForward->PushString(pConVar->GetString()); pForward->Execute(NULL); } }
static cell_t sm_RemoveFromForward(IPluginContext *pContext, const cell_t *params) { Handle_t fwdHandle = static_cast<Handle_t>(params[1]); Handle_t plHandle = static_cast<Handle_t>(params[2]); HandleError err; IChangeableForward *pForward; IPlugin *pPlugin; if ((err=handlesys->ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward)) != HandleError_None) { return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err); } if (plHandle == 0) { pPlugin = pluginsys->FindPluginByContext(pContext->GetContext()); } else { pPlugin = pluginsys->PluginFromHandle(plHandle, &err); if (!pPlugin) { return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err); } } IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]); if (!pFunction) { return pContext->ThrowNativeError("Invalid function id (%X)", params[3]); } return pForward->RemoveFunction(pFunction); }
/* IGameEventManager2::FireEvent hook */ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) { EventHook *pHook; IChangeableForward *pForward; const char *name; cell_t res = Pl_Continue; /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ if (!pEvent) { RETURN_META_VALUE(MRES_IGNORED, false); } name = pEvent->GetName(); if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook))) { /* Push the event onto the event stack. The reference count is increased to make sure * the structure is not garbage collected in between now and the post hook. */ pHook->refCount++; m_EventStack.push(pHook); pForward = pHook->pPreHook; if (pForward) { EventInfo info(pEvent, NULL); HandleSecurity sec(NULL, g_pCoreIdent); Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); pForward->PushCell(hndl); pForward->PushString(name); pForward->PushCell(bDontBroadcast); pForward->Execute(&res, NULL); g_HandleSys.FreeHandle(hndl, &sec); } if (pHook->postCopy) { m_EventCopies.push(gameevents->DuplicateEvent(pEvent)); } if (res) { gameevents->FreeEvent(pEvent); RETURN_META_VALUE(MRES_SUPERCEDE, false); } } else { m_EventStack.push(NULL); } RETURN_META_VALUE(MRES_IGNORED, true); }
/* IGameEventManager2::FireEvent hook */ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) { EventHook *pHook; IChangeableForward *pForward; const char *name; cell_t res = Pl_Continue; /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ if (!pEvent) { RETURN_META_VALUE(MRES_IGNORED, false); } /* Get the event name, we're going to need this for passing to post hooks */ name = pEvent->GetName(); m_EventNames.push(name); if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook))) { pForward = pHook->pPreHook; if (pForward) { EventInfo info = { pEvent, NULL }; Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); pForward->PushCell(hndl); pForward->PushString(name); pForward->PushCell(bDontBroadcast); pForward->Execute(&res, NULL); HandleSecurity sec(NULL, g_pCoreIdent); g_HandleSys.FreeHandle(hndl, &sec); } if (pHook->postCopy) { pHook->pEventCopy = gameevents->DuplicateEvent(pEvent); } if (res) { gameevents->FreeEvent(pEvent); RETURN_META_VALUE(MRES_SUPERCEDE, false); } } RETURN_META_VALUE(MRES_IGNORED, true); }
static void PawnFrameAction(void *pData) { ke::AutoPtr<SMFrameActionData> frame(reinterpret_cast<SMFrameActionData *>(pData)); IPlugin *pPlugin = pluginsys->PluginFromHandle(frame->ownerhandle, NULL); if (!pPlugin) { return; } IChangeableForward *pForward; HandleSecurity sec(pPlugin->GetIdentity(), g_pCoreIdent); if (handlesys->ReadHandle(frame->handle, g_PrivateFwdType, &sec, (void **)&pForward) != HandleError_None) { return; } pForward->PushCell(frame->data); pForward->Execute(NULL); handlesys->FreeHandle(frame->handle, &sec); }
void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction) { ConVarInfo *pInfo; IChangeableForward *pForward; /* Find the convar in the lookup trie */ if (convar_cache_lookup(pConVar->GetName(), &pInfo)) { /* Get the forward */ pForward = pInfo->pChangeForward; /* If forward does not exist, create it */ if (!pForward) { pForward = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS); pInfo->pChangeForward = pForward; } /* Add function to forward's list */ pForward->AddFunction(pFunction); } }
void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction) { ConVarInfo *pInfo; IChangeableForward *pForward; IPluginContext *pContext = pFunction->GetParentContext(); /* Find the convar in the lookup trie */ if (convar_cache_lookup(pConVar->GetName(), &pInfo)) { /* Get the forward */ pForward = pInfo->pChangeForward; /* If the forward doesn't exist, we can't unhook anything */ if (!pForward) { pContext->ThrowNativeError("Convar \"%s\" has no active hook", pConVar->GetName()); return; } /* Remove the function from the forward's list */ if (!pForward->RemoveFunction(pFunction)) { pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", pConVar->GetName()); return; } /* If the forward now has 0 functions in it... */ if (pForward->GetFunctionCount() == 0 && !ConVarReentrancyGuard::IsCvarInChain(pConVar)) { /* Free this forward */ forwardsys->ReleaseForward(pForward); pInfo->pChangeForward = NULL; } } }
static cell_t sm_AddFrameAction(IPluginContext *pContext, const cell_t *params) { IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext()); IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[1]); if (!pFunction) { return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); } IChangeableForward *pForward = forwardsys->CreateForwardEx(NULL, ET_Ignore, 1, NULL, Param_Cell); IdentityToken_t *pIdentity = pContext->GetIdentity(); Handle_t Handle = handlesys->CreateHandle(g_PrivateFwdType, pForward, pIdentity, g_pCoreIdent, NULL); if (Handle == BAD_HANDLE) { forwardsys->ReleaseForward(pForward); return 0; } pForward->AddFunction(pFunction); SMFrameActionData *pData = new SMFrameActionData(Handle, pPlugin->GetMyHandle(), params[2]); g_pSM->AddFrameAction(PawnFrameAction, pData); return 1; }
/* IGameEventManager2::FireEvent post hook */ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) { IGameEvent *pEventCopy = NULL; EventHook *pHook; IChangeableForward *pForward; const char *name; Handle_t hndl = 0; /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ if (!pEvent) { RETURN_META_VALUE(MRES_IGNORED, false); } name = m_EventNames.front(); if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook))) { pForward = pHook->pPostHook; if (pForward) { EventInfo info = { pHook->pEventCopy, NULL }; if (pHook->postCopy) { hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); pForward->PushCell(hndl); } else { pForward->PushCell(BAD_HANDLE); } pForward->PushString(name); 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(pEventCopy); pHook->pEventCopy = NULL; } } } m_EventNames.pop(); RETURN_META_VALUE(MRES_IGNORED, true); }
/* IGameEventManager2::FireEvent post hook */ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) { EventHook *pHook; EventInfo info; IChangeableForward *pForward; Handle_t hndl = 0; /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ if (!pEvent) { RETURN_META_VALUE(MRES_IGNORED, false); } pHook = m_EventStack.front(); if (pHook != NULL) { pForward = pHook->pPostHook; if (pForward) { if (pHook->postCopy) { info.bDontBroadcast = bDontBroadcast; info.pEvent = m_EventCopies.front(); info.pOwner = NULL; hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); pForward->PushCell(hndl); } else { pForward->PushCell(BAD_HANDLE); } pForward->PushString(pHook->name.chars()); pForward->PushCell(bDontBroadcast); pForward->Execute(NULL); if (pHook->postCopy) { /* Free handle */ HandleSecurity sec(NULL, g_pCoreIdent); handlesys->FreeHandle(hndl, &sec); /* Free event structure */ gameevents->FreeEvent(info.pEvent); m_EventCopies.pop(); } } /* Decrement reference count, check if a delayed delete is needed */ if (--pHook->refCount == 0) { assert(pHook->pPostHook == NULL); assert(pHook->pPreHook == NULL); m_EventHooks.remove(pHook->name.chars()); delete pHook; } } m_EventStack.pop(); RETURN_META_VALUE(MRES_IGNORED, true); }