Many things:
1) General code clean-up in convar manager 2) Fixed bug where convar handles were not being cached for pre-existing convars 3) Fixed bug where a convar's old value and new value were switched in the ConVarChanged hooks 4) Made convar and concmd listings more consistent, I think 5) Alphabetized convar listing 6) Minor clean-up in event manager --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40588
This commit is contained in:
		
							parent
							
								
									e6a127ac17
								
							
						
					
					
						commit
						0b25b6d667
					
				| @ -741,15 +741,18 @@ void ConCmdManager::OnRootConsoleCommand(const char *command, unsigned int argco | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		const sm_plugininfo_t *plinfo = pPlugin->GetPublicInfo(); | ||||
| 		const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : pPlugin->GetFilename(); | ||||
| 
 | ||||
| 		CmdList *pList; | ||||
| 		if (!pPlugin->GetProperty("CommandList", (void **)&pList)) | ||||
| 		{ | ||||
| 			g_RootMenu.ConsolePrint("[SM] No commands found for %s", pPlugin->GetFilename()); | ||||
| 			g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname); | ||||
| 			return; | ||||
| 		} | ||||
| 		if (!pList->size()) | ||||
| 		{ | ||||
| 			g_RootMenu.ConsolePrint("[SM] No commands found for %s", pPlugin->GetFilename()); | ||||
| 			g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| @ -757,10 +760,11 @@ void ConCmdManager::OnRootConsoleCommand(const char *command, unsigned int argco | ||||
| 		const char *type = NULL; | ||||
| 		const char *name; | ||||
| 		const char *help; | ||||
| 		g_RootMenu.ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]"); | ||||
| 		g_RootMenu.ConsolePrint("[SM] Listing %d commands for: %s", pList->size(), plname); | ||||
| 		g_RootMenu.ConsolePrint("  %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]"); | ||||
| 		for (iter=pList->begin(); | ||||
| 			 iter!=pList->end(); | ||||
| 			 iter++) | ||||
| 			 iter++, id++) | ||||
| 		{ | ||||
| 			PlCmdInfo &cmd = (*iter); | ||||
| 			if (cmd.type == Cmd_Server) | ||||
| @ -778,7 +782,7 @@ void ConCmdManager::OnRootConsoleCommand(const char *command, unsigned int argco | ||||
| 			} else { | ||||
| 				help = cmd.pInfo->pCmd->GetHelpText(); | ||||
| 			} | ||||
| 			g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);		 | ||||
| 			g_RootMenu.ConsolePrint("  %-17.16s %-12.11s %s", name, type, help);		 | ||||
| 		} | ||||
| 
 | ||||
| 		return; | ||||
|  | ||||
| @ -21,9 +21,12 @@ | ||||
| 
 | ||||
| ConVarManager g_ConVarManager; | ||||
| 
 | ||||
| const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String}; | ||||
| typedef List<const ConVar *> ConVarList; | ||||
| 
 | ||||
| ConVarManager::ConVarManager() : m_ConVarType(0) | ||||
| { | ||||
| 	// Create a convar lookup trie
 | ||||
| 	/* Create a convar lookup trie */ | ||||
| 	m_ConVarCache = sm_trie_create(); | ||||
| } | ||||
| 
 | ||||
| @ -31,10 +34,10 @@ ConVarManager::~ConVarManager() | ||||
| { | ||||
| 	List<ConVarInfo *>::iterator iter; | ||||
| 
 | ||||
| 	// Destroy our convar lookup trie
 | ||||
| 	/* Destroy our convar lookup trie */ | ||||
| 	sm_trie_destroy(m_ConVarCache); | ||||
| 
 | ||||
| 	// Destroy all the ConVarInfo structures
 | ||||
| 	/* Destroy all the ConVarInfo structures */ | ||||
| 	for (iter = m_ConVars.begin(); iter != m_ConVars.end(); iter++) | ||||
| 	{ | ||||
| 		delete (*iter); | ||||
| @ -47,15 +50,15 @@ void ConVarManager::OnSourceModAllInitialized() | ||||
| { | ||||
| 	HandleAccess sec; | ||||
| 
 | ||||
| 	// Set up access rights for the 'ConVar' handle type
 | ||||
| 	/* Set up access rights for the 'ConVar' 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 'ConVar' handle type
 | ||||
| 	/* Create the 'ConVar' handle type */ | ||||
| 	m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL); | ||||
| 
 | ||||
| 	// Add the 'cvars' option to the 'sm' console command
 | ||||
| 	/* Add the 'convars' option to the 'sm' console command */ | ||||
| 	g_RootMenu.AddRootConsoleCommand("convars", "View convars created by a plugin", this); | ||||
| } | ||||
| 
 | ||||
| @ -64,33 +67,33 @@ void ConVarManager::OnSourceModShutdown() | ||||
| 	IChangeableForward *fwd; | ||||
| 	List<ConVarInfo *>::iterator i; | ||||
| 
 | ||||
| 	// Iterate list of ConVarInfo structures
 | ||||
| 	/* Iterate list of ConVarInfo structures */ | ||||
| 	for (i = m_ConVars.begin(); i != m_ConVars.end(); i++) | ||||
| 	{ | ||||
| 		fwd = (*i)->changeForward; | ||||
| 
 | ||||
| 		// Free any convar-change forwards that still exist
 | ||||
| 		/* Free any convar-change forwards that still exist */ | ||||
| 		if (fwd) | ||||
| 		{ | ||||
| 			g_Forwards.ReleaseForward(fwd); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Remove the 'cvars' option from the 'sm' console command
 | ||||
| 	/* Remove the 'convars' option from the 'sm' console command */ | ||||
| 	g_RootMenu.RemoveRootConsoleCommand("convars", this); | ||||
| 
 | ||||
| 	// Remove the 'ConVar' handle type
 | ||||
| 	/* Remove the 'ConVar' handle type */ | ||||
| 	g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent); | ||||
| } | ||||
| 
 | ||||
| void ConVarManager::OnPluginDestroyed(IPlugin *plugin) | ||||
| void ConVarManager::OnPluginUnloaded(IPlugin *plugin) | ||||
| { | ||||
| 	CVector<ConVar *> *cvarList; | ||||
| 	ConVarList *pConVarList; | ||||
| 
 | ||||
| 	// If plugin has a convar list, free its memory
 | ||||
| 	if (plugin->GetProperty("ConVarList", reinterpret_cast<void **>(&cvarList), true)) | ||||
| 	/* If plugin has a convar list, free its memory */ | ||||
| 	if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true)) | ||||
| 	{ | ||||
| 		delete cvarList; | ||||
| 		delete pConVarList; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -99,18 +102,18 @@ void ConVarManager::OnHandleDestroy(HandleType_t type, void *object) | ||||
| 	ConVarInfo *info; | ||||
| 	ConVar *pConVar = static_cast<ConVar *>(object); | ||||
| 
 | ||||
| 	// Find convar in lookup trie
 | ||||
| 	/* Find convar in lookup trie */ | ||||
| 	sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info)); | ||||
| 
 | ||||
| 	// If convar was created by SourceMod plugin...
 | ||||
| 	/* If convar was created by SourceMod plugin... */ | ||||
| 	if (info->sourceMod) | ||||
| 	{ | ||||
| 		// Delete string allocations
 | ||||
| 		/* Delete string allocations */ | ||||
| 		delete [] pConVar->GetName();  | ||||
| 		delete [] pConVar->GetDefault(); | ||||
| 		delete [] pConVar->GetHelpText(); | ||||
| 
 | ||||
| 		// Then unlink it from SourceMM
 | ||||
| 		/* Then unlink it from SourceMM */ | ||||
| 		g_SMAPI->UnregisterConCmdBase(g_PLAPI, pConVar); | ||||
| 	} | ||||
| } | ||||
| @ -119,78 +122,80 @@ void ConVarManager::OnRootConsoleCommand(const char *command, unsigned int argco | ||||
| { | ||||
| 	if (argcount >= 3) | ||||
| 	{ | ||||
| 		int id = 1; | ||||
| 
 | ||||
| 		// Get plugin index that was passed
 | ||||
| 		int num = atoi(g_RootMenu.GetArgument(2)); | ||||
| 		/* Get plugin index that was passed */ | ||||
| 		int id = atoi(g_RootMenu.GetArgument(2)); | ||||
| 		 | ||||
| 		// If invalid plugin index...
 | ||||
| 		if (num < 1 || num > (int)g_PluginSys.GetPluginCount()) | ||||
| 		/* Get plugin object */ | ||||
| 		CPlugin *plugin = g_PluginSys.GetPluginByOrder(id); | ||||
| 
 | ||||
| 		if (!plugin) | ||||
| 		{ | ||||
| 			g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", num); | ||||
| 			g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", id); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		// Get plugin object
 | ||||
| 		CPlugin *pl = g_PluginSys.GetPluginByOrder(num); | ||||
| 		/* Get plugin name */ | ||||
| 		const sm_plugininfo_t *plinfo = plugin->GetPublicInfo(); | ||||
| 		const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : plugin->GetFilename(); | ||||
| 
 | ||||
| 		CVector<ConVar *> *cvarList = NULL; | ||||
| 		ConVarList *pConVarList; | ||||
| 		ConVarList::iterator iter; | ||||
| 
 | ||||
| 		// Get convar list from 'ConVar' property
 | ||||
| 		pl->GetProperty("ConVar", reinterpret_cast<void **>(&cvarList)); | ||||
| 
 | ||||
| 		// If no cvar list...
 | ||||
| 		if (cvarList == NULL) | ||||
| 		/* If no convar list... */ | ||||
| 		if (!plugin->GetProperty("ConVarList", (void **)&pConVarList)) | ||||
| 		{ | ||||
| 			g_RootMenu.ConsolePrint("[SM] No convars for \"%s\"", pl->GetPublicInfo()->name); | ||||
| 			g_RootMenu.ConsolePrint("[SM] No convars found for: %s", plname); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		g_RootMenu.ConsolePrint("[SM] Displaying convars for \"%s\"", pl->GetPublicInfo()->name); | ||||
| 		g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname); | ||||
| 		g_RootMenu.ConsolePrint("  %-32.31s %s", "[Name]", "[Value]"); | ||||
| 
 | ||||
| 		// Iterate convar list and display each one
 | ||||
| 		for (size_t i = 0; i < cvarList->size(); i++, id++) | ||||
| 		/* Iterate convar list and display each one */ | ||||
| 		for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++) | ||||
| 		{ | ||||
| 			ConVar *pConVar = (*cvarList)[i]; | ||||
| 			g_RootMenu.ConsolePrint("  %02d \"%s\" = \"%s\"", id, pConVar->GetName(), pConVar->GetString());  | ||||
| 			const ConVar *pConVar = (*iter); | ||||
| 			g_RootMenu.ConsolePrint("  %-32.31s %s", pConVar->GetName(), pConVar->GetString());  | ||||
| 		} | ||||
| 
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	// Display usage of subcommand
 | ||||
| 	/* Display usage of subcommand */ | ||||
| 	g_RootMenu.ConsolePrint("[SM] Usage: sm convars <plugin #>"); | ||||
| } | ||||
| 
 | ||||
| Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *helpText, int flags, bool hasMin, float min, bool hasMax, float max) | ||||
| Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *description, int flags, bool hasMin, float min, bool hasMax, float max) | ||||
| { | ||||
| 	ConVar *pConVar = NULL; | ||||
| 	ConVarInfo *info = NULL; | ||||
| 	CVector<ConVar *> *cvarList = NULL; | ||||
| 	ConVarInfo *pInfo = NULL; | ||||
| 	ConVarList *pConVarList = NULL; | ||||
| 	Handle_t hndl = 0; | ||||
| 
 | ||||
| 	// Find out if the convar exists already
 | ||||
| 	/* Find out if the convar exists already */ | ||||
| 	pConVar = icvar->FindVar(name); | ||||
| 
 | ||||
| 	// If the convar already exists...
 | ||||
| 	if (pConVar != NULL) | ||||
| 	/* If the convar already exists... */ | ||||
| 	if (pConVar) | ||||
| 	{ | ||||
| 		// First check if we already have a handle to it
 | ||||
| 		if (sm_trie_retrieve(m_ConVarCache, name, reinterpret_cast<void **>(&info))) | ||||
| 		/* First find out if we already have a handle to it */ | ||||
| 		if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo)) | ||||
| 		{ | ||||
| 			// If we do, then return that handle
 | ||||
| 			return info->handle; | ||||
| 			return pInfo->handle; | ||||
| 		} else { | ||||
| 			// If we don't, then create a new handle from the convar
 | ||||
| 			/* If we don't, then create a new handle from the convar */ | ||||
| 			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 = pConVar->GetCallback(); | ||||
| 			/* Create and initialize ConVarInfo structure */ | ||||
| 			pInfo = new ConVarInfo(); | ||||
| 			pInfo->handle = hndl; | ||||
| 			pInfo->sourceMod = false; | ||||
| 			pInfo->changeForward = NULL; | ||||
| 			pInfo->origCallback = pConVar->GetCallback(); | ||||
| 
 | ||||
| 			m_ConVars.push_back(info); | ||||
| 			/* Insert struct into caches */ | ||||
| 			m_ConVars.push_back(pInfo); | ||||
| 			sm_trie_insert(m_ConVarCache, name, pInfo); | ||||
| 
 | ||||
| 			return hndl; | ||||
| 		} | ||||
| @ -201,47 +206,33 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, | ||||
| 
 | ||||
| 	while (pBase) | ||||
| 	{ | ||||
| 		if (strcmp(pBase->GetName(), name) == 0) | ||||
| 		if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0) | ||||
| 		{ | ||||
| 			return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name); | ||||
| 			return BAD_HANDLE; | ||||
| 		} | ||||
| 
 | ||||
| 		pBase = const_cast<ConCommandBase *>(pBase->GetNext()); | ||||
| 	} | ||||
| 
 | ||||
| 	// Since we didn't find an existing convar (or concmd with the same name), now we can finally create it!
 | ||||
| 	pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(helpText), hasMin, min, hasMax, max); | ||||
| 	/* Since an existing convar (or concmd with the same name) was not found , now we can finally create it */ | ||||
| 	pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(description), hasMin, min, hasMax, max); | ||||
| 
 | ||||
| 	// Find plugin creating convar
 | ||||
| 	IPlugin *pl = g_PluginSys.FindPluginByContext(pContext->GetContext()); | ||||
| 	/* Add convar to plugin's list */ | ||||
| 	AddConVarToPluginList(pContext, pConVar); | ||||
| 
 | ||||
| 	// Get convar list from 'ConVar' property of plugin
 | ||||
| 	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("ConVarList", cvarList); | ||||
| 	} | ||||
| 
 | ||||
| 	// Add new convar to plugin's list
 | ||||
| 	cvarList->push_back(pConVar); | ||||
| 
 | ||||
| 	// Create a handle from the new convar
 | ||||
| 	/* Create a handle from the new convar */ | ||||
| 	hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL); | ||||
| 
 | ||||
| 	info = new ConVarInfo; | ||||
| 	info->handle = hndl; | ||||
| 	info->sourceMod = true; | ||||
| 	info->changeForward = NULL; | ||||
| 	info->origCallback = NULL; | ||||
| 	/* Create and initialize ConVarInfo structure */ | ||||
| 	pInfo = new ConVarInfo(); | ||||
| 	pInfo->handle = hndl; | ||||
| 	pInfo->sourceMod = true; | ||||
| 	pInfo->changeForward = NULL; | ||||
| 	pInfo->origCallback = NULL; | ||||
| 
 | ||||
| 	m_ConVars.push_back(info); | ||||
| 
 | ||||
| 	// Insert the handle into our lookup trie
 | ||||
| 	sm_trie_insert(m_ConVarCache, name, info); | ||||
| 	/* Insert struct into caches */ | ||||
| 	m_ConVars.push_back(pInfo); | ||||
| 	sm_trie_insert(m_ConVarCache, name, pInfo); | ||||
| 
 | ||||
| 	return hndl; | ||||
| } | ||||
| @ -249,159 +240,165 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, | ||||
| Handle_t ConVarManager::FindConVar(const char *name) | ||||
| { | ||||
| 	ConVar *pConVar = NULL; | ||||
| 	ConVarInfo *info = NULL; | ||||
| 	Handle_t hndl = 0; | ||||
| 	ConVarInfo *pInfo; | ||||
| 	Handle_t hndl; | ||||
| 
 | ||||
| 	// Search for convar
 | ||||
| 	/* Search for convar */ | ||||
| 	pConVar = icvar->FindVar(name); | ||||
| 
 | ||||
| 	// If it doesn't exist, then return an invalid handle
 | ||||
| 	if (pConVar == NULL) | ||||
| 	/* If it doesn't exist, then return an invalid handle */ | ||||
| 	if (!pConVar) | ||||
| 	{ | ||||
| 		return BAD_HANDLE; | ||||
| 	} | ||||
| 
 | ||||
| 	// At this point, convar exists, so find out if we already have a handle for it
 | ||||
| 	if (sm_trie_retrieve(m_ConVarCache, name, reinterpret_cast<void **>(&info))) | ||||
| 	/* At this point, the convar exists. So, find out if we already have a handle */ | ||||
| 	if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo)) | ||||
| 	{ | ||||
| 		// If we do, then return that handle
 | ||||
| 		return info->handle; | ||||
| 		return pInfo->handle; | ||||
| 	} | ||||
| 
 | ||||
| 	// If we don't, then create a new handle from the convar
 | ||||
| 	/* If we don't have a handle, then create a new one */ | ||||
| 	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 = pConVar->GetCallback(); | ||||
| 	/* Create and initilize ConVarInfo structure */ | ||||
| 	pInfo = new ConVarInfo(); | ||||
| 	pInfo->handle = hndl; | ||||
| 	pInfo->sourceMod = false; | ||||
| 	pInfo->changeForward = NULL; | ||||
| 	pInfo->origCallback = pConVar->GetCallback(); | ||||
| 
 | ||||
| 	m_ConVars.push_back(info); | ||||
| 
 | ||||
| 	// Insert the handle into our cache
 | ||||
| 	sm_trie_insert(m_ConVarCache, name, info); | ||||
| 	/* Insert struct into our caches */ | ||||
| 	m_ConVars.push_back(pInfo); | ||||
| 	sm_trie_insert(m_ConVarCache, name, pInfo); | ||||
| 
 | ||||
| 	return hndl; | ||||
| } | ||||
| 
 | ||||
| void ConVarManager::HookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid) | ||||
| void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction) | ||||
| { | ||||
| 	IPluginFunction *func = pContext->GetFunctionById(funcid); | ||||
| 	IChangeableForward *fwd = NULL; | ||||
| 	char fwdName[64]; | ||||
| 	ConVarInfo *info = NULL; | ||||
| 	ConVarInfo *pInfo; | ||||
| 	IChangeableForward *pForward; | ||||
| 
 | ||||
| 	// This shouldn't happen...
 | ||||
| 	if (func == NULL) | ||||
| 	/* Find the convar in the lookup trie */ | ||||
| 	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), (void **)&pInfo)) | ||||
| 	{ | ||||
| 		pContext->ThrowNativeError("Invalid function specified"); | ||||
| 		return; | ||||
| 	} | ||||
| 		/* Get the forward */ | ||||
| 		pForward = pInfo->changeForward; | ||||
| 
 | ||||
| 	// Create a forward name
 | ||||
| 	UTIL_Format(fwdName, sizeof(fwdName), "ConVar.%s", pConVar->GetName()); | ||||
| 
 | ||||
| 	// First find out if the forward already exists
 | ||||
| 	g_Forwards.FindForward(fwdName, &fwd); | ||||
| 
 | ||||
| 	// If the forward doesn't exist...
 | ||||
| 	if (fwd == NULL) | ||||
| 	{ | ||||
| 		// This is the forward's parameter type list
 | ||||
| 		ParamType p[] = {Param_Cell, Param_String, Param_String}; | ||||
| 
 | ||||
| 		// Create the forward
 | ||||
| 		fwd = g_Forwards.CreateForwardEx(fwdName, ET_Ignore, 3, p); | ||||
| 
 | ||||
| 		// Find the convar in the lookup trie
 | ||||
| 		if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info))) | ||||
| 		/* If forward does not exist, create it */ | ||||
| 		if (!pForward) | ||||
| 		{ | ||||
| 			// Set the convar's forward to the newly created one
 | ||||
| 			info->changeForward = fwd; | ||||
| 			pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS); | ||||
| 			pInfo->changeForward = pForward; | ||||
| 
 | ||||
| 			// Set the convar's callback to our static one
 | ||||
| 			/* Install our own callback */ | ||||
| 			pConVar->InstallChangeCallback(OnConVarChanged); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Add the function to the forward's list
 | ||||
| 	fwd->AddFunction(func); | ||||
| 		/* Add function to forward's list */ | ||||
| 		pForward->AddFunction(pFunction); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ConVarManager::UnhookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid) | ||||
| void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction) | ||||
| { | ||||
| 	IPluginFunction *func = pContext->GetFunctionById(funcid); | ||||
| 	IChangeableForward *fwd = NULL; | ||||
| 	ConVarInfo *info = NULL; | ||||
| 	ConVarInfo *pInfo; | ||||
| 	IChangeableForward *pForward; | ||||
| 	IPluginContext *pContext = pFunction->GetParentContext(); | ||||
| 
 | ||||
| 	// This shouldn't happen...
 | ||||
| 	if (func == NULL) | ||||
| 	/* Find the convar in the lookup trie */ | ||||
| 	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), (void **)&pInfo)) | ||||
| 	{ | ||||
| 		pContext->ThrowNativeError("Invalid function specified"); | ||||
| 		return; | ||||
| 	} | ||||
| 		/* Get the forward */ | ||||
| 		pForward = pInfo->changeForward; | ||||
| 
 | ||||
| 	// Find the convar in the lookup trie
 | ||||
| 	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info))) | ||||
| 	{ | ||||
| 		// Get the forward
 | ||||
| 		fwd = info->changeForward; | ||||
| 
 | ||||
| 		// If the forward doesn't exist, we can't unhook anything
 | ||||
| 		if (fwd == NULL) | ||||
| 		/* 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 (!fwd->RemoveFunction(func)) | ||||
| 		/* 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 (fwd->GetFunctionCount() == 0) | ||||
| 		/* If the forward now has 0 functions in it... */ | ||||
| 		if (pForward->GetFunctionCount() == 0) | ||||
| 		{ | ||||
| 			// Free this forward
 | ||||
| 			g_Forwards.ReleaseForward(fwd); | ||||
| 			info->changeForward = NULL; | ||||
| 			/* Free this forward */ | ||||
| 			g_Forwards.ReleaseForward(pForward); | ||||
| 			pInfo->changeForward = NULL; | ||||
| 
 | ||||
| 			// Put the back the original convar callback
 | ||||
| 			pConVar->InstallChangeCallback(info->origCallback); | ||||
| 			/* Put back the original convar callback */ | ||||
| 			pConVar->InstallChangeCallback(pInfo->origCallback); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar) | ||||
| { | ||||
| 	ConVarList *pConVarList; | ||||
| 	ConVarList::iterator iter; | ||||
| 	bool inserted = false; | ||||
| 	const char *orig = pConVar->GetName(); | ||||
| 
 | ||||
| 	IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext()); | ||||
| 
 | ||||
| 	/* Check plugin for an existing convar list */ | ||||
| 	if (!plugin->GetProperty("ConVarList", (void **)&pConVarList)) | ||||
| 	{ | ||||
| 		pConVarList = new ConVarList(); | ||||
| 		plugin->SetProperty("ConVarList", pConVarList); | ||||
| 	} | ||||
| 
 | ||||
| 	/* 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 ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue) | ||||
| { | ||||
| 	// If the values are the same...
 | ||||
| 	/* If the values are the same, exit early in order to not trigger callbacks */ | ||||
| 	if (strcmp(pConVar->GetString(), oldValue) == 0) | ||||
| 	{ | ||||
| 		// Exit early in order to not trigger callbacks
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	Trie *cache = g_ConVarManager.GetConVarCache(); | ||||
| 	ConVarInfo *info; | ||||
| 	Trie *pCache = g_ConVarManager.GetConVarCache(); | ||||
| 	ConVarInfo *pInfo; | ||||
| 
 | ||||
| 	// Find the convar in the lookup trie
 | ||||
| 	sm_trie_retrieve(cache, pConVar->GetName(), reinterpret_cast<void **>(&info)); | ||||
| 	/* Find the convar in the lookup trie */ | ||||
| 	sm_trie_retrieve(pCache, pConVar->GetName(), (void **)&pInfo); | ||||
| 
 | ||||
| 	FnChangeCallback origCallback = info->origCallback; | ||||
| 	IChangeableForward *fwd = info->changeForward; | ||||
| 	FnChangeCallback origCallback = pInfo->origCallback; | ||||
| 	IChangeableForward *pForward = pInfo->changeForward; | ||||
| 
 | ||||
| 	// If there was a change callback installed previously, call it
 | ||||
| 	/* If there was a change callback installed previously, call it */ | ||||
| 	if (origCallback) | ||||
| 	{ | ||||
| 		origCallback(pConVar, oldValue); | ||||
| 	} | ||||
| 
 | ||||
| 	// Now call forwards in plugins that have hooked this
 | ||||
| 	fwd->PushCell(info->handle); | ||||
| 	fwd->PushString(pConVar->GetString()); | ||||
| 	fwd->PushString(oldValue); | ||||
| 	fwd->Execute(NULL); | ||||
| 	/* Now call forwards in plugins that have hooked this */ | ||||
| 	pForward->PushCell(pInfo->handle); | ||||
| 	pForward->PushString(oldValue); | ||||
| 	pForward->PushString(pConVar->GetString()); | ||||
| 	pForward->Execute(NULL); | ||||
| } | ||||
|  | ||||
| @ -51,7 +51,7 @@ public: // SMGlobalClass | ||||
| public: // IHandleTypeDispatch
 | ||||
| 	void OnHandleDestroy(HandleType_t type, void *object); | ||||
| public: // IPluginsListener
 | ||||
| 	void OnPluginDestroyed(IPlugin *plugin); | ||||
| 	void OnPluginUnloaded(IPlugin *plugin); | ||||
| public: //IRootConsoleCommand
 | ||||
| 	void OnRootConsoleCommand(const char *command, unsigned int argcount); | ||||
| public: | ||||
| @ -74,8 +74,8 @@ public: | ||||
| 	/**
 | ||||
| 	 * Create a convar and return a handle to it. | ||||
| 	 */ | ||||
| 	Handle_t CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *helpText, | ||||
| 	                      int flags, bool hasMin, float min, bool hasMax, float max); | ||||
| 	Handle_t CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, | ||||
| 	                      const char *description, int flags, bool hasMin, float min, bool hasMax, float max); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Searches for a convar and returns a handle to it | ||||
| @ -85,13 +85,18 @@ public: | ||||
| 	/**
 | ||||
| 	 * Add a function to call when the specified convar changes. | ||||
| 	 */ | ||||
| 	void HookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid); | ||||
| 	void HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Remove a function from the forward that will be called when the specified convar changes. | ||||
| 	 */ | ||||
| 	void UnhookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid); | ||||
| 	void UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction); | ||||
| private: | ||||
| 	/**
 | ||||
| 	 * Adds a convar to a plugin's list. | ||||
| 	 */ | ||||
| 	static void AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Static callback that Valve's ConVar class executes when the convar's value changes. | ||||
| 	 */ | ||||
|  | ||||
| @ -21,9 +21,8 @@ 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}; | ||||
| typedef List<EventHook *> EventHookList; | ||||
| 
 | ||||
| EventManager::EventManager() : m_EventType(0), m_NotifyPlugins(true), m_EventCopy(NULL) | ||||
| { | ||||
| @ -93,12 +92,13 @@ void EventManager::OnHandleDestroy(HandleType_t type, void *object) | ||||
| void EventManager::OnPluginUnloaded(IPlugin *plugin) | ||||
| { | ||||
| 	EventHookList *pHookList; | ||||
| 	EventHookList::iterator iter; | ||||
| 	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++) | ||||
| 		for (iter = pHookList->begin(); iter != pHookList->end(); iter++) | ||||
| 		{ | ||||
| 			pHook = (*iter); | ||||
| 
 | ||||
|  | ||||
| @ -11,8 +11,8 @@ | ||||
| * Version: $Id$ | ||||
| */ | ||||
| 
 | ||||
| #ifndef _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_ | ||||
| #define _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_ | ||||
| #ifndef _INCLUDE_SOURCEMOD_EVENTMANAGER_H_ | ||||
| #define _INCLUDE_SOURCEMOD_EVENTMANAGER_H_ | ||||
| 
 | ||||
| #include "sm_globals.h" | ||||
| #include "sourcemm_api.h" | ||||
| @ -109,4 +109,4 @@ private: | ||||
| 
 | ||||
| extern EventManager g_EventManager; | ||||
| 
 | ||||
| #endif // _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_
 | ||||
| #endif // _INCLUDE_SOURCEMOD_EVENTMANAGER_H_
 | ||||
|  | ||||
| @ -22,6 +22,8 @@ using namespace SourcePawn; | ||||
| 
 | ||||
| #define LANG_SERVER		0 | ||||
| 
 | ||||
| #define IS_STR_FILLED(var) (var[0] != '\0') | ||||
| 
 | ||||
| size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param); | ||||
| const char *stristr(const char *str, const char *substr); | ||||
| unsigned int strncopy(char *dest, const char *src, size_t count); | ||||
|  | ||||
| @ -29,7 +29,7 @@ static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params) | ||||
| 	// While the engine seems to accept a blank convar name, it causes a crash upon server quit
 | ||||
| 	if (name == NULL || strcmp(name, "") == 0) | ||||
| 	{ | ||||
| 		return pContext->ThrowNativeError("Null or blank convar name is not allowed"); | ||||
| 		return pContext->ThrowNativeError("Convar with blank name is not permitted"); | ||||
| 	} | ||||
| 
 | ||||
| 	pContext->LocalToString(params[2], &defaultVal); | ||||
| @ -40,7 +40,14 @@ static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params) | ||||
| 	float min = sp_ctof(params[6]); | ||||
| 	float max = sp_ctof(params[8]); | ||||
| 
 | ||||
| 	return g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max); | ||||
| 	Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max); | ||||
| 
 | ||||
| 	if (hndl == BAD_HANDLE) | ||||
| 	{ | ||||
| 		return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name); | ||||
| 	} | ||||
| 
 | ||||
| 	return hndl; | ||||
| } | ||||
| 
 | ||||
| static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params) | ||||
| @ -49,12 +56,6 @@ static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params) | ||||
| 
 | ||||
| 	pContext->LocalToString(params[1], &name); | ||||
| 
 | ||||
| 	// While the engine seems to accept a blank convar name, it causes a crash upon server quit
 | ||||
| 	if (name == NULL || strcmp(name, "") == 0) | ||||
| 	{ | ||||
| 		return BAD_HANDLE; | ||||
| 	} | ||||
| 
 | ||||
| 	return g_ConVarManager.FindConVar(name); | ||||
| } | ||||
| 
 | ||||
| @ -70,7 +71,14 @@ static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params | ||||
| 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); | ||||
| 	} | ||||
| 
 | ||||
| 	g_ConVarManager.HookConVarChange(pContext, pConVar, static_cast<funcid_t>(params[2])); | ||||
| 	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]); | ||||
| 
 | ||||
| 	if (!pFunction) | ||||
| 	{ | ||||
| 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); | ||||
| 	} | ||||
| 
 | ||||
| 	g_ConVarManager.HookConVarChange(pConVar, pFunction); | ||||
| 
 | ||||
| 	return 1; | ||||
| } | ||||
| @ -87,7 +95,14 @@ static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *para | ||||
| 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); | ||||
| 	} | ||||
| 
 | ||||
| 	g_ConVarManager.UnhookConVarChange(pContext, pConVar, static_cast<funcid_t>(params[2])); | ||||
| 	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]); | ||||
| 
 | ||||
| 	if (!pFunction) | ||||
| 	{ | ||||
| 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); | ||||
| 	} | ||||
| 
 | ||||
| 	g_ConVarManager.UnhookConVarChange(pConVar, pFunction); | ||||
| 
 | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| @ -1415,7 +1415,6 @@ const char *CPluginManager::GetStatusText(PluginStatus st) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #define IS_STR_FILLED(var) (var[0] != '\0') | ||||
| void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argcount) | ||||
| { | ||||
| 	if (argcount >= 3) | ||||
| @ -1432,7 +1431,7 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc | ||||
| 				g_RootMenu.ConsolePrint("[SM] No plugins loaded"); | ||||
| 				return; | ||||
| 			} else { | ||||
| 				g_RootMenu.ConsolePrint("[SM] Displaying %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : ""); | ||||
| 				g_RootMenu.ConsolePrint("[SM] Listing %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : ""); | ||||
| 			} | ||||
| 
 | ||||
| 			IPluginIterator *iter = GetPluginIterator(); | ||||
|  | ||||
| @ -209,7 +209,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 description	Optional description of the convar. | ||||
|  * @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. | ||||
| @ -218,7 +218,7 @@ native GetCmdArgString(String:buffer[], maxlength); | ||||
|  * @return				A handle to the newly created convar. If the convar already exists, INVALID_HANDLE is returned. | ||||
|  * @error				Convar name is blank or is the same as an existing console command. | ||||
|  */ | ||||
| native Handle:CreateConVar(const String:name[], const String:defaultValue[], const String:helpText[]="", flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0); | ||||
| native Handle:CreateConVar(const String:name[], const String:defaultValue[], const String:description[]="", flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0); | ||||
| 
 | ||||
| /** | ||||
|  * Searches for a console variable. | ||||
| @ -236,7 +236,7 @@ native Handle:FindConVar(const String:name[]); | ||||
|  * @param newValue		String containing the new value of the convar. | ||||
|  * @noreturn | ||||
|  */ | ||||
| functag OnConVarChanged public(Handle:convar, const String:oldValue[], const String:newValue[]); | ||||
| functag ConVarChanged public(Handle:convar, const String:oldValue[], const String:newValue[]); | ||||
| 
 | ||||
| /** | ||||
|  * Creates a hook for when a console variable's value is changed. | ||||
| @ -246,7 +246,7 @@ functag OnConVarChanged public(Handle:convar, const String:oldValue[], const Str | ||||
|  * @noreturn | ||||
|  * @error				Invalid or corrupt Handle or invalid callback function. | ||||
|  */ | ||||
| native HookConVarChange(Handle:convar, OnConVarChanged:callback); | ||||
| native HookConVarChange(Handle:convar, ConVarChanged:callback); | ||||
| 
 | ||||
| /** | ||||
|  * Removes a hook for when a console variable's value is changed. | ||||
| @ -256,7 +256,7 @@ native HookConVarChange(Handle:convar, OnConVarChanged:callback); | ||||
|  * @noreturn | ||||
|  * @error				Invalid or corrupt Handle, invalid callback function, or no active hook on convar. | ||||
|  */ | ||||
| native UnhookConVarChange(Handle:convar, OnConVarChanged:callback); | ||||
| native UnhookConVarChange(Handle:convar, ConVarChanged:callback); | ||||
| 
 | ||||
| /** | ||||
|  * Returns the boolean value of a console variable. | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user