core/ConVarManager.cpp
changeset 582 00c843a1bb18
parent 580 416aecc7de51
child 583 9fab8343cc15
     1.1 --- a/core/ConVarManager.cpp	Tue Mar 06 07:38:19 2007 +0000
     1.2 +++ b/core/ConVarManager.cpp	Tue Mar 06 23:59:25 2007 +0000
     1.3 @@ -21,9 +21,12 @@
     1.4  
     1.5  ConVarManager g_ConVarManager;
     1.6  
     1.7 +const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
     1.8 +typedef List<const ConVar *> ConVarList;
     1.9 +
    1.10  ConVarManager::ConVarManager() : m_ConVarType(0)
    1.11  {
    1.12 -	// Create a convar lookup trie
    1.13 +	/* Create a convar lookup trie */
    1.14  	m_ConVarCache = sm_trie_create();
    1.15  }
    1.16  
    1.17 @@ -31,10 +34,10 @@
    1.18  {
    1.19  	List<ConVarInfo *>::iterator iter;
    1.20  
    1.21 -	// Destroy our convar lookup trie
    1.22 +	/* Destroy our convar lookup trie */
    1.23  	sm_trie_destroy(m_ConVarCache);
    1.24  
    1.25 -	// Destroy all the ConVarInfo structures
    1.26 +	/* Destroy all the ConVarInfo structures */
    1.27  	for (iter = m_ConVars.begin(); iter != m_ConVars.end(); iter++)
    1.28  	{
    1.29  		delete (*iter);
    1.30 @@ -47,15 +50,15 @@
    1.31  {
    1.32  	HandleAccess sec;
    1.33  
    1.34 -	// Set up access rights for the 'ConVar' handle type
    1.35 +	/* Set up access rights for the 'ConVar' handle type */
    1.36  	sec.access[HandleAccess_Read] = 0;
    1.37  	sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
    1.38  	sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
    1.39  
    1.40 -	// Create the 'ConVar' handle type
    1.41 +	/* Create the 'ConVar' handle type */
    1.42  	m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
    1.43  
    1.44 -	// Add the 'cvars' option to the 'sm' console command
    1.45 +	/* Add the 'convars' option to the 'sm' console command */
    1.46  	g_RootMenu.AddRootConsoleCommand("convars", "View convars created by a plugin", this);
    1.47  }
    1.48  
    1.49 @@ -64,33 +67,33 @@
    1.50  	IChangeableForward *fwd;
    1.51  	List<ConVarInfo *>::iterator i;
    1.52  
    1.53 -	// Iterate list of ConVarInfo structures
    1.54 +	/* Iterate list of ConVarInfo structures */
    1.55  	for (i = m_ConVars.begin(); i != m_ConVars.end(); i++)
    1.56  	{
    1.57  		fwd = (*i)->changeForward;
    1.58  
    1.59 -		// Free any convar-change forwards that still exist
    1.60 +		/* Free any convar-change forwards that still exist */
    1.61  		if (fwd)
    1.62  		{
    1.63  			g_Forwards.ReleaseForward(fwd);
    1.64  		}
    1.65  	}
    1.66  
    1.67 -	// Remove the 'cvars' option from the 'sm' console command
    1.68 +	/* Remove the 'convars' option from the 'sm' console command */
    1.69  	g_RootMenu.RemoveRootConsoleCommand("convars", this);
    1.70  
    1.71 -	// Remove the 'ConVar' handle type
    1.72 +	/* Remove the 'ConVar' handle type */
    1.73  	g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
    1.74  }
    1.75  
    1.76 -void ConVarManager::OnPluginDestroyed(IPlugin *plugin)
    1.77 +void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
    1.78  {
    1.79 -	CVector<ConVar *> *cvarList;
    1.80 +	ConVarList *pConVarList;
    1.81  
    1.82 -	// If plugin has a convar list, free its memory
    1.83 -	if (plugin->GetProperty("ConVarList", reinterpret_cast<void **>(&cvarList), true))
    1.84 +	/* If plugin has a convar list, free its memory */
    1.85 +	if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
    1.86  	{
    1.87 -		delete cvarList;
    1.88 +		delete pConVarList;
    1.89  	}
    1.90  }
    1.91  
    1.92 @@ -99,18 +102,18 @@
    1.93  	ConVarInfo *info;
    1.94  	ConVar *pConVar = static_cast<ConVar *>(object);
    1.95  
    1.96 -	// Find convar in lookup trie
    1.97 +	/* Find convar in lookup trie */
    1.98  	sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info));
    1.99  
   1.100 -	// If convar was created by SourceMod plugin...
   1.101 +	/* If convar was created by SourceMod plugin... */
   1.102  	if (info->sourceMod)
   1.103  	{
   1.104 -		// Delete string allocations
   1.105 +		/* Delete string allocations */
   1.106  		delete [] pConVar->GetName(); 
   1.107  		delete [] pConVar->GetDefault();
   1.108  		delete [] pConVar->GetHelpText();
   1.109  
   1.110 -		// Then unlink it from SourceMM
   1.111 +		/* Then unlink it from SourceMM */
   1.112  		g_SMAPI->UnregisterConCmdBase(g_PLAPI, pConVar);
   1.113  	}
   1.114  }
   1.115 @@ -119,78 +122,80 @@
   1.116  {
   1.117  	if (argcount >= 3)
   1.118  	{
   1.119 -		int id = 1;
   1.120 -
   1.121 -		// Get plugin index that was passed
   1.122 -		int num = atoi(g_RootMenu.GetArgument(2));
   1.123 +		/* Get plugin index that was passed */
   1.124 +		int id = atoi(g_RootMenu.GetArgument(2));
   1.125  		
   1.126 -		// If invalid plugin index...
   1.127 -		if (num < 1 || num > (int)g_PluginSys.GetPluginCount())
   1.128 +		/* Get plugin object */
   1.129 +		CPlugin *plugin = g_PluginSys.GetPluginByOrder(id);
   1.130 +
   1.131 +		if (!plugin)
   1.132  		{
   1.133 -			g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", num);
   1.134 +			g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", id);
   1.135  			return;
   1.136  		}
   1.137  
   1.138 -		// Get plugin object
   1.139 -		CPlugin *pl = g_PluginSys.GetPluginByOrder(num);
   1.140 -
   1.141 -		CVector<ConVar *> *cvarList = NULL;
   1.142 +		/* Get plugin name */
   1.143 +		const sm_plugininfo_t *plinfo = plugin->GetPublicInfo();
   1.144 +		const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : plugin->GetFilename();
   1.145  
   1.146 -		// Get convar list from 'ConVar' property
   1.147 -		pl->GetProperty("ConVar", reinterpret_cast<void **>(&cvarList));
   1.148 +		ConVarList *pConVarList;
   1.149 +		ConVarList::iterator iter;
   1.150  
   1.151 -		// If no cvar list...
   1.152 -		if (cvarList == NULL)
   1.153 +		/* If no convar list... */
   1.154 +		if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
   1.155  		{
   1.156 -			g_RootMenu.ConsolePrint("[SM] No convars for \"%s\"", pl->GetPublicInfo()->name);
   1.157 +			g_RootMenu.ConsolePrint("[SM] No convars found for: %s", plname);
   1.158  			return;
   1.159  		}
   1.160  
   1.161 -		g_RootMenu.ConsolePrint("[SM] Displaying convars for \"%s\"", pl->GetPublicInfo()->name);
   1.162 +		g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
   1.163 +		g_RootMenu.ConsolePrint("  %-32.31s %s", "[Name]", "[Value]");
   1.164  
   1.165 -		// Iterate convar list and display each one
   1.166 -		for (size_t i = 0; i < cvarList->size(); i++, id++)
   1.167 +		/* Iterate convar list and display each one */
   1.168 +		for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
   1.169  		{
   1.170 -			ConVar *pConVar = (*cvarList)[i];
   1.171 -			g_RootMenu.ConsolePrint("  %02d \"%s\" = \"%s\"", id, pConVar->GetName(), pConVar->GetString()); 
   1.172 +			const ConVar *pConVar = (*iter);
   1.173 +			g_RootMenu.ConsolePrint("  %-32.31s %s", pConVar->GetName(), pConVar->GetString()); 
   1.174  		}
   1.175  
   1.176  		return;
   1.177  	}
   1.178  
   1.179 -	// Display usage of subcommand
   1.180 +	/* Display usage of subcommand */
   1.181  	g_RootMenu.ConsolePrint("[SM] Usage: sm convars <plugin #>");
   1.182  }
   1.183  
   1.184 -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)
   1.185 +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)
   1.186  {
   1.187  	ConVar *pConVar = NULL;
   1.188 -	ConVarInfo *info = NULL;
   1.189 -	CVector<ConVar *> *cvarList = NULL;
   1.190 +	ConVarInfo *pInfo = NULL;
   1.191 +	ConVarList *pConVarList = NULL;
   1.192  	Handle_t hndl = 0;
   1.193  
   1.194 -	// Find out if the convar exists already
   1.195 +	/* Find out if the convar exists already */
   1.196  	pConVar = icvar->FindVar(name);
   1.197  
   1.198 -	// If the convar already exists...
   1.199 -	if (pConVar != NULL)
   1.200 +	/* If the convar already exists... */
   1.201 +	if (pConVar)
   1.202  	{
   1.203 -		// First check if we already have a handle to it
   1.204 -		if (sm_trie_retrieve(m_ConVarCache, name, reinterpret_cast<void **>(&info)))
   1.205 +		/* First find out if we already have a handle to it */
   1.206 +		if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo))
   1.207  		{
   1.208 -			// If we do, then return that handle
   1.209 -			return info->handle;
   1.210 +			return pInfo->handle;
   1.211  		} else {
   1.212 -			// If we don't, then create a new handle from the convar
   1.213 +			/* If we don't, then create a new handle from the convar */
   1.214  			hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
   1.215  
   1.216 -			info = new ConVarInfo;
   1.217 -			info->handle = hndl;
   1.218 -			info->sourceMod = false;
   1.219 -			info->changeForward = NULL;
   1.220 -			info->origCallback = pConVar->GetCallback();
   1.221 +			/* Create and initialize ConVarInfo structure */
   1.222 +			pInfo = new ConVarInfo();
   1.223 +			pInfo->handle = hndl;
   1.224 +			pInfo->sourceMod = false;
   1.225 +			pInfo->changeForward = NULL;
   1.226 +			pInfo->origCallback = pConVar->GetCallback();
   1.227  
   1.228 -			m_ConVars.push_back(info);
   1.229 +			/* Insert struct into caches */
   1.230 +			m_ConVars.push_back(pInfo);
   1.231 +			sm_trie_insert(m_ConVarCache, name, pInfo);
   1.232  
   1.233  			return hndl;
   1.234  		}
   1.235 @@ -201,47 +206,33 @@
   1.236  
   1.237  	while (pBase)
   1.238  	{
   1.239 -		if (strcmp(pBase->GetName(), name) == 0)
   1.240 +		if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0)
   1.241  		{
   1.242 -			return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name);
   1.243 +			return BAD_HANDLE;
   1.244  		}
   1.245  
   1.246  		pBase = const_cast<ConCommandBase *>(pBase->GetNext());
   1.247  	}
   1.248  
   1.249 -	// Since we didn't find an existing convar (or concmd with the same name), now we can finally create it!
   1.250 -	pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(helpText), hasMin, min, hasMax, max);
   1.251 -
   1.252 -	// Find plugin creating convar
   1.253 -	IPlugin *pl = g_PluginSys.FindPluginByContext(pContext->GetContext());
   1.254 -
   1.255 -	// Get convar list from 'ConVar' property of plugin
   1.256 -	pl->GetProperty("ConVarList", reinterpret_cast<void **>(&cvarList));
   1.257 +	/* Since an existing convar (or concmd with the same name) was not found , now we can finally create it */
   1.258 +	pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(description), hasMin, min, hasMax, max);
   1.259  
   1.260 -	// If 'ConVar' property doesn't exist...
   1.261 -	if (cvarList == NULL)
   1.262 -	{
   1.263 -		// Then create it
   1.264 -		cvarList = new CVector<ConVar *>;
   1.265 -		pl->SetProperty("ConVarList", cvarList);
   1.266 -	}
   1.267 +	/* Add convar to plugin's list */
   1.268 +	AddConVarToPluginList(pContext, pConVar);
   1.269  
   1.270 -	// Add new convar to plugin's list
   1.271 -	cvarList->push_back(pConVar);
   1.272 -
   1.273 -	// Create a handle from the new convar
   1.274 +	/* Create a handle from the new convar */
   1.275  	hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
   1.276  
   1.277 -	info = new ConVarInfo;
   1.278 -	info->handle = hndl;
   1.279 -	info->sourceMod = true;
   1.280 -	info->changeForward = NULL;
   1.281 -	info->origCallback = NULL;
   1.282 +	/* Create and initialize ConVarInfo structure */
   1.283 +	pInfo = new ConVarInfo();
   1.284 +	pInfo->handle = hndl;
   1.285 +	pInfo->sourceMod = true;
   1.286 +	pInfo->changeForward = NULL;
   1.287 +	pInfo->origCallback = NULL;
   1.288  
   1.289 -	m_ConVars.push_back(info);
   1.290 -
   1.291 -	// Insert the handle into our lookup trie
   1.292 -	sm_trie_insert(m_ConVarCache, name, info);
   1.293 +	/* Insert struct into caches */
   1.294 +	m_ConVars.push_back(pInfo);
   1.295 +	sm_trie_insert(m_ConVarCache, name, pInfo);
   1.296  
   1.297  	return hndl;
   1.298  }
   1.299 @@ -249,159 +240,165 @@
   1.300  Handle_t ConVarManager::FindConVar(const char *name)
   1.301  {
   1.302  	ConVar *pConVar = NULL;
   1.303 -	ConVarInfo *info = NULL;
   1.304 -	Handle_t hndl = 0;
   1.305 +	ConVarInfo *pInfo;
   1.306 +	Handle_t hndl;
   1.307  
   1.308 -	// Search for convar
   1.309 +	/* Search for convar */
   1.310  	pConVar = icvar->FindVar(name);
   1.311  
   1.312 -	// If it doesn't exist, then return an invalid handle
   1.313 -	if (pConVar == NULL)
   1.314 +	/* If it doesn't exist, then return an invalid handle */
   1.315 +	if (!pConVar)
   1.316  	{
   1.317  		return BAD_HANDLE;
   1.318  	}
   1.319  
   1.320 -	// At this point, convar exists, so find out if we already have a handle for it
   1.321 -	if (sm_trie_retrieve(m_ConVarCache, name, reinterpret_cast<void **>(&info)))
   1.322 +	/* At this point, the convar exists. So, find out if we already have a handle */
   1.323 +	if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo))
   1.324  	{
   1.325 -		// If we do, then return that handle
   1.326 -		return info->handle;
   1.327 +		return pInfo->handle;
   1.328  	}
   1.329  
   1.330 -	// If we don't, then create a new handle from the convar
   1.331 +	/* If we don't have a handle, then create a new one */
   1.332  	hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
   1.333  
   1.334 -	info = new ConVarInfo;
   1.335 -	info->handle = hndl;
   1.336 -	info->sourceMod = false;
   1.337 -	info->changeForward = NULL;
   1.338 -	info->origCallback = pConVar->GetCallback();
   1.339 +	/* Create and initilize ConVarInfo structure */
   1.340 +	pInfo = new ConVarInfo();
   1.341 +	pInfo->handle = hndl;
   1.342 +	pInfo->sourceMod = false;
   1.343 +	pInfo->changeForward = NULL;
   1.344 +	pInfo->origCallback = pConVar->GetCallback();
   1.345  
   1.346 -	m_ConVars.push_back(info);
   1.347 -
   1.348 -	// Insert the handle into our cache
   1.349 -	sm_trie_insert(m_ConVarCache, name, info);
   1.350 +	/* Insert struct into our caches */
   1.351 +	m_ConVars.push_back(pInfo);
   1.352 +	sm_trie_insert(m_ConVarCache, name, pInfo);
   1.353  
   1.354  	return hndl;
   1.355  }
   1.356  
   1.357 -void ConVarManager::HookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid)
   1.358 +void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
   1.359  {
   1.360 -	IPluginFunction *func = pContext->GetFunctionById(funcid);
   1.361 -	IChangeableForward *fwd = NULL;
   1.362 -	char fwdName[64];
   1.363 -	ConVarInfo *info = NULL;
   1.364 -
   1.365 -	// This shouldn't happen...
   1.366 -	if (func == NULL)
   1.367 -	{
   1.368 -		pContext->ThrowNativeError("Invalid function specified");
   1.369 -		return;
   1.370 -	}
   1.371 -
   1.372 -	// Create a forward name
   1.373 -	UTIL_Format(fwdName, sizeof(fwdName), "ConVar.%s", pConVar->GetName());
   1.374 +	ConVarInfo *pInfo;
   1.375 +	IChangeableForward *pForward;
   1.376  
   1.377 -	// First find out if the forward already exists
   1.378 -	g_Forwards.FindForward(fwdName, &fwd);
   1.379 -
   1.380 -	// If the forward doesn't exist...
   1.381 -	if (fwd == NULL)
   1.382 +	/* Find the convar in the lookup trie */
   1.383 +	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), (void **)&pInfo))
   1.384  	{
   1.385 -		// This is the forward's parameter type list
   1.386 -		ParamType p[] = {Param_Cell, Param_String, Param_String};
   1.387 +		/* Get the forward */
   1.388 +		pForward = pInfo->changeForward;
   1.389  
   1.390 -		// Create the forward
   1.391 -		fwd = g_Forwards.CreateForwardEx(fwdName, ET_Ignore, 3, p);
   1.392 +		/* If forward does not exist, create it */
   1.393 +		if (!pForward)
   1.394 +		{
   1.395 +			pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
   1.396 +			pInfo->changeForward = pForward;
   1.397  
   1.398 -		// Find the convar in the lookup trie
   1.399 -		if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info)))
   1.400 -		{
   1.401 -			// Set the convar's forward to the newly created one
   1.402 -			info->changeForward = fwd;
   1.403 -
   1.404 -			// Set the convar's callback to our static one
   1.405 +			/* Install our own callback */
   1.406  			pConVar->InstallChangeCallback(OnConVarChanged);
   1.407  		}
   1.408 +
   1.409 +		/* Add function to forward's list */
   1.410 +		pForward->AddFunction(pFunction);
   1.411  	}
   1.412 -
   1.413 -	// Add the function to the forward's list
   1.414 -	fwd->AddFunction(func);
   1.415  }
   1.416  
   1.417 -void ConVarManager::UnhookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid)
   1.418 +void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
   1.419  {
   1.420 -	IPluginFunction *func = pContext->GetFunctionById(funcid);
   1.421 -	IChangeableForward *fwd = NULL;
   1.422 -	ConVarInfo *info = NULL;
   1.423 +	ConVarInfo *pInfo;
   1.424 +	IChangeableForward *pForward;
   1.425 +	IPluginContext *pContext = pFunction->GetParentContext();
   1.426  
   1.427 -	// This shouldn't happen...
   1.428 -	if (func == NULL)
   1.429 +	/* Find the convar in the lookup trie */
   1.430 +	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), (void **)&pInfo))
   1.431  	{
   1.432 -		pContext->ThrowNativeError("Invalid function specified");
   1.433 -		return;
   1.434 -	}
   1.435 +		/* Get the forward */
   1.436 +		pForward = pInfo->changeForward;
   1.437  
   1.438 -	// Find the convar in the lookup trie
   1.439 -	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info)))
   1.440 -	{
   1.441 -		// Get the forward
   1.442 -		fwd = info->changeForward;
   1.443 -
   1.444 -		// If the forward doesn't exist, we can't unhook anything
   1.445 -		if (fwd == NULL)
   1.446 +		/* If the forward doesn't exist, we can't unhook anything */
   1.447 +		if (!pForward)
   1.448  		{
   1.449  			pContext->ThrowNativeError("Convar \"%s\" has no active hook", pConVar->GetName());
   1.450  			return;
   1.451  		}
   1.452  
   1.453 -		// Remove the function from the forward's list
   1.454 -		if (!fwd->RemoveFunction(func))
   1.455 +		/* Remove the function from the forward's list */
   1.456 +		if (!pForward->RemoveFunction(pFunction))
   1.457  		{
   1.458  			pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", pConVar->GetName());
   1.459  			return;
   1.460  		}
   1.461  
   1.462 -		// If the forward now has 0 functions in it...
   1.463 -		if (fwd->GetFunctionCount() == 0)
   1.464 +		/* If the forward now has 0 functions in it... */
   1.465 +		if (pForward->GetFunctionCount() == 0)
   1.466  		{
   1.467 -			// Free this forward
   1.468 -			g_Forwards.ReleaseForward(fwd);
   1.469 -			info->changeForward = NULL;
   1.470 +			/* Free this forward */
   1.471 +			g_Forwards.ReleaseForward(pForward);
   1.472 +			pInfo->changeForward = NULL;
   1.473 +
   1.474 +			/* Put back the original convar callback */
   1.475 +			pConVar->InstallChangeCallback(pInfo->origCallback);
   1.476 +		}
   1.477 +	}
   1.478 +}
   1.479 +
   1.480 +void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar)
   1.481 +{
   1.482 +	ConVarList *pConVarList;
   1.483 +	ConVarList::iterator iter;
   1.484 +	bool inserted = false;
   1.485 +	const char *orig = pConVar->GetName();
   1.486 +
   1.487 +	IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
   1.488  
   1.489 -			// Put the back the original convar callback
   1.490 -			pConVar->InstallChangeCallback(info->origCallback);
   1.491 +	/* Check plugin for an existing convar list */
   1.492 +	if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
   1.493 +	{
   1.494 +		pConVarList = new ConVarList();
   1.495 +		plugin->SetProperty("ConVarList", pConVarList);
   1.496 +	}
   1.497 +
   1.498 +	/* Insert convar into list which is sorted alphabetically */
   1.499 +	for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
   1.500 +	{
   1.501 +		if (strcmp(orig, (*iter)->GetName()) < 0)
   1.502 +		{
   1.503 +			pConVarList->insert(iter, pConVar);
   1.504 +			inserted = true;
   1.505 +			break;
   1.506  		}
   1.507  	}
   1.508 +
   1.509 +	if (!inserted)
   1.510 +	{
   1.511 +		pConVarList->push_back(pConVar);
   1.512 +	}
   1.513  }
   1.514  
   1.515  void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
   1.516  {
   1.517 -	// If the values are the same...
   1.518 +	/* If the values are the same, exit early in order to not trigger callbacks */
   1.519  	if (strcmp(pConVar->GetString(), oldValue) == 0)
   1.520  	{
   1.521 -		// Exit early in order to not trigger callbacks
   1.522  		return;
   1.523  	}
   1.524  
   1.525 -	Trie *cache = g_ConVarManager.GetConVarCache();
   1.526 -	ConVarInfo *info;
   1.527 +	Trie *pCache = g_ConVarManager.GetConVarCache();
   1.528 +	ConVarInfo *pInfo;
   1.529  
   1.530 -	// Find the convar in the lookup trie
   1.531 -	sm_trie_retrieve(cache, pConVar->GetName(), reinterpret_cast<void **>(&info));
   1.532 +	/* Find the convar in the lookup trie */
   1.533 +	sm_trie_retrieve(pCache, pConVar->GetName(), (void **)&pInfo);
   1.534  
   1.535 -	FnChangeCallback origCallback = info->origCallback;
   1.536 -	IChangeableForward *fwd = info->changeForward;
   1.537 +	FnChangeCallback origCallback = pInfo->origCallback;
   1.538 +	IChangeableForward *pForward = pInfo->changeForward;
   1.539  
   1.540 -	// If there was a change callback installed previously, call it
   1.541 +	/* If there was a change callback installed previously, call it */
   1.542  	if (origCallback)
   1.543  	{
   1.544  		origCallback(pConVar, oldValue);
   1.545  	}
   1.546  
   1.547 -	// Now call forwards in plugins that have hooked this
   1.548 -	fwd->PushCell(info->handle);
   1.549 -	fwd->PushString(pConVar->GetString());
   1.550 -	fwd->PushString(oldValue);
   1.551 -	fwd->Execute(NULL);
   1.552 +	/* Now call forwards in plugins that have hooked this */
   1.553 +	pForward->PushCell(pInfo->handle);
   1.554 +	pForward->PushString(oldValue);
   1.555 +	pForward->PushString(pConVar->GetString());
   1.556 +	pForward->Execute(NULL);
   1.557  }