示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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++;
		}
	}
}
示例#4
0
	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;
	}
示例#5
0
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;
}
示例#6
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;
}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
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;
}
示例#10
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);
}
示例#11
0
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);
	}
}
示例#12
0
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);
	}
}
示例#13
0
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;
}
示例#14
0
// 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;
}
示例#15
0
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 #>");
}
示例#16
0
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;
}
示例#17
0
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;
}
示例#20
0
// 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;
}