Many things:
authorScott Ehlert <ds@alliedmods.net>
Tue Mar 06 23:59:25 2007 +0000 (2007-03-06)
changeset 58200c843a1bb18
parent 581 5716b2117a50
child 583 9fab8343cc15
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
core/ConCmdManager.cpp
core/ConVarManager.cpp
core/ConVarManager.h
core/EventManager.cpp
core/EventManager.h
core/sm_stringutil.h
core/smn_console.cpp
core/systems/PluginSys.cpp
plugins/include/console.inc
     1.1 --- a/core/ConCmdManager.cpp	Tue Mar 06 07:38:19 2007 +0000
     1.2 +++ b/core/ConCmdManager.cpp	Tue Mar 06 23:59:25 2007 +0000
     1.3 @@ -741,15 +741,18 @@
     1.4  			return;
     1.5  		}
     1.6  
     1.7 +		const sm_plugininfo_t *plinfo = pPlugin->GetPublicInfo();
     1.8 +		const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : pPlugin->GetFilename();
     1.9 +
    1.10  		CmdList *pList;
    1.11  		if (!pPlugin->GetProperty("CommandList", (void **)&pList))
    1.12  		{
    1.13 -			g_RootMenu.ConsolePrint("[SM] No commands found for %s", pPlugin->GetFilename());
    1.14 +			g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
    1.15  			return;
    1.16  		}
    1.17  		if (!pList->size())
    1.18  		{
    1.19 -			g_RootMenu.ConsolePrint("[SM] No commands found for %s", pPlugin->GetFilename());
    1.20 +			g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
    1.21  			return;
    1.22  		}
    1.23  
    1.24 @@ -757,10 +760,11 @@
    1.25  		const char *type = NULL;
    1.26  		const char *name;
    1.27  		const char *help;
    1.28 -		g_RootMenu.ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
    1.29 +		g_RootMenu.ConsolePrint("[SM] Listing %d commands for: %s", pList->size(), plname);
    1.30 +		g_RootMenu.ConsolePrint("  %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
    1.31  		for (iter=pList->begin();
    1.32  			 iter!=pList->end();
    1.33 -			 iter++)
    1.34 +			 iter++, id++)
    1.35  		{
    1.36  			PlCmdInfo &cmd = (*iter);
    1.37  			if (cmd.type == Cmd_Server)
    1.38 @@ -778,7 +782,7 @@
    1.39  			} else {
    1.40  				help = cmd.pInfo->pCmd->GetHelpText();
    1.41  			}
    1.42 -			g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);		
    1.43 +			g_RootMenu.ConsolePrint("  %-17.16s %-12.11s %s", name, type, help);		
    1.44  		}
    1.45  
    1.46  		return;
     2.1 --- a/core/ConVarManager.cpp	Tue Mar 06 07:38:19 2007 +0000
     2.2 +++ b/core/ConVarManager.cpp	Tue Mar 06 23:59:25 2007 +0000
     2.3 @@ -21,9 +21,12 @@
     2.4  
     2.5  ConVarManager g_ConVarManager;
     2.6  
     2.7 +const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
     2.8 +typedef List<const ConVar *> ConVarList;
     2.9 +
    2.10  ConVarManager::ConVarManager() : m_ConVarType(0)
    2.11  {
    2.12 -	// Create a convar lookup trie
    2.13 +	/* Create a convar lookup trie */
    2.14  	m_ConVarCache = sm_trie_create();
    2.15  }
    2.16  
    2.17 @@ -31,10 +34,10 @@
    2.18  {
    2.19  	List<ConVarInfo *>::iterator iter;
    2.20  
    2.21 -	// Destroy our convar lookup trie
    2.22 +	/* Destroy our convar lookup trie */
    2.23  	sm_trie_destroy(m_ConVarCache);
    2.24  
    2.25 -	// Destroy all the ConVarInfo structures
    2.26 +	/* Destroy all the ConVarInfo structures */
    2.27  	for (iter = m_ConVars.begin(); iter != m_ConVars.end(); iter++)
    2.28  	{
    2.29  		delete (*iter);
    2.30 @@ -47,15 +50,15 @@
    2.31  {
    2.32  	HandleAccess sec;
    2.33  
    2.34 -	// Set up access rights for the 'ConVar' handle type
    2.35 +	/* Set up access rights for the 'ConVar' handle type */
    2.36  	sec.access[HandleAccess_Read] = 0;
    2.37  	sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
    2.38  	sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
    2.39  
    2.40 -	// Create the 'ConVar' handle type
    2.41 +	/* Create the 'ConVar' handle type */
    2.42  	m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
    2.43  
    2.44 -	// Add the 'cvars' option to the 'sm' console command
    2.45 +	/* Add the 'convars' option to the 'sm' console command */
    2.46  	g_RootMenu.AddRootConsoleCommand("convars", "View convars created by a plugin", this);
    2.47  }
    2.48  
    2.49 @@ -64,33 +67,33 @@
    2.50  	IChangeableForward *fwd;
    2.51  	List<ConVarInfo *>::iterator i;
    2.52  
    2.53 -	// Iterate list of ConVarInfo structures
    2.54 +	/* Iterate list of ConVarInfo structures */
    2.55  	for (i = m_ConVars.begin(); i != m_ConVars.end(); i++)
    2.56  	{
    2.57  		fwd = (*i)->changeForward;
    2.58  
    2.59 -		// Free any convar-change forwards that still exist
    2.60 +		/* Free any convar-change forwards that still exist */
    2.61  		if (fwd)
    2.62  		{
    2.63  			g_Forwards.ReleaseForward(fwd);
    2.64  		}
    2.65  	}
    2.66  
    2.67 -	// Remove the 'cvars' option from the 'sm' console command
    2.68 +	/* Remove the 'convars' option from the 'sm' console command */
    2.69  	g_RootMenu.RemoveRootConsoleCommand("convars", this);
    2.70  
    2.71 -	// Remove the 'ConVar' handle type
    2.72 +	/* Remove the 'ConVar' handle type */
    2.73  	g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
    2.74  }
    2.75  
    2.76 -void ConVarManager::OnPluginDestroyed(IPlugin *plugin)
    2.77 +void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
    2.78  {
    2.79 -	CVector<ConVar *> *cvarList;
    2.80 +	ConVarList *pConVarList;
    2.81  
    2.82 -	// If plugin has a convar list, free its memory
    2.83 -	if (plugin->GetProperty("ConVarList", reinterpret_cast<void **>(&cvarList), true))
    2.84 +	/* If plugin has a convar list, free its memory */
    2.85 +	if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
    2.86  	{
    2.87 -		delete cvarList;
    2.88 +		delete pConVarList;
    2.89  	}
    2.90  }
    2.91  
    2.92 @@ -99,18 +102,18 @@
    2.93  	ConVarInfo *info;
    2.94  	ConVar *pConVar = static_cast<ConVar *>(object);
    2.95  
    2.96 -	// Find convar in lookup trie
    2.97 +	/* Find convar in lookup trie */
    2.98  	sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info));
    2.99  
   2.100 -	// If convar was created by SourceMod plugin...
   2.101 +	/* If convar was created by SourceMod plugin... */
   2.102  	if (info->sourceMod)
   2.103  	{
   2.104 -		// Delete string allocations
   2.105 +		/* Delete string allocations */
   2.106  		delete [] pConVar->GetName(); 
   2.107  		delete [] pConVar->GetDefault();
   2.108  		delete [] pConVar->GetHelpText();
   2.109  
   2.110 -		// Then unlink it from SourceMM
   2.111 +		/* Then unlink it from SourceMM */
   2.112  		g_SMAPI->UnregisterConCmdBase(g_PLAPI, pConVar);
   2.113  	}
   2.114  }
   2.115 @@ -119,78 +122,80 @@
   2.116  {
   2.117  	if (argcount >= 3)
   2.118  	{
   2.119 -		int id = 1;
   2.120 -
   2.121 -		// Get plugin index that was passed
   2.122 -		int num = atoi(g_RootMenu.GetArgument(2));
   2.123 +		/* Get plugin index that was passed */
   2.124 +		int id = atoi(g_RootMenu.GetArgument(2));
   2.125  		
   2.126 -		// If invalid plugin index...
   2.127 -		if (num < 1 || num > (int)g_PluginSys.GetPluginCount())
   2.128 +		/* Get plugin object */
   2.129 +		CPlugin *plugin = g_PluginSys.GetPluginByOrder(id);
   2.130 +
   2.131 +		if (!plugin)
   2.132  		{
   2.133 -			g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", num);
   2.134 +			g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", id);
   2.135  			return;
   2.136  		}
   2.137  
   2.138 -		// Get plugin object
   2.139 -		CPlugin *pl = g_PluginSys.GetPluginByOrder(num);
   2.140 -
   2.141 -		CVector<ConVar *> *cvarList = NULL;
   2.142 +		/* Get plugin name */
   2.143 +		const sm_plugininfo_t *plinfo = plugin->GetPublicInfo();
   2.144 +		const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : plugin->GetFilename();
   2.145  
   2.146 -		// Get convar list from 'ConVar' property
   2.147 -		pl->GetProperty("ConVar", reinterpret_cast<void **>(&cvarList));
   2.148 +		ConVarList *pConVarList;
   2.149 +		ConVarList::iterator iter;
   2.150  
   2.151 -		// If no cvar list...
   2.152 -		if (cvarList == NULL)
   2.153 +		/* If no convar list... */
   2.154 +		if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
   2.155  		{
   2.156 -			g_RootMenu.ConsolePrint("[SM] No convars for \"%s\"", pl->GetPublicInfo()->name);
   2.157 +			g_RootMenu.ConsolePrint("[SM] No convars found for: %s", plname);
   2.158  			return;
   2.159  		}
   2.160  
   2.161 -		g_RootMenu.ConsolePrint("[SM] Displaying convars for \"%s\"", pl->GetPublicInfo()->name);
   2.162 +		g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
   2.163 +		g_RootMenu.ConsolePrint("  %-32.31s %s", "[Name]", "[Value]");
   2.164  
   2.165 -		// Iterate convar list and display each one
   2.166 -		for (size_t i = 0; i < cvarList->size(); i++, id++)
   2.167 +		/* Iterate convar list and display each one */
   2.168 +		for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
   2.169  		{
   2.170 -			ConVar *pConVar = (*cvarList)[i];
   2.171 -			g_RootMenu.ConsolePrint("  %02d \"%s\" = \"%s\"", id, pConVar->GetName(), pConVar->GetString()); 
   2.172 +			const ConVar *pConVar = (*iter);
   2.173 +			g_RootMenu.ConsolePrint("  %-32.31s %s", pConVar->GetName(), pConVar->GetString()); 
   2.174  		}
   2.175  
   2.176  		return;
   2.177  	}
   2.178  
   2.179 -	// Display usage of subcommand
   2.180 +	/* Display usage of subcommand */
   2.181  	g_RootMenu.ConsolePrint("[SM] Usage: sm convars <plugin #>");
   2.182  }
   2.183  
   2.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)
   2.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)
   2.186  {
   2.187  	ConVar *pConVar = NULL;
   2.188 -	ConVarInfo *info = NULL;
   2.189 -	CVector<ConVar *> *cvarList = NULL;
   2.190 +	ConVarInfo *pInfo = NULL;
   2.191 +	ConVarList *pConVarList = NULL;
   2.192  	Handle_t hndl = 0;
   2.193  
   2.194 -	// Find out if the convar exists already
   2.195 +	/* Find out if the convar exists already */
   2.196  	pConVar = icvar->FindVar(name);
   2.197  
   2.198 -	// If the convar already exists...
   2.199 -	if (pConVar != NULL)
   2.200 +	/* If the convar already exists... */
   2.201 +	if (pConVar)
   2.202  	{
   2.203 -		// First check if we already have a handle to it
   2.204 -		if (sm_trie_retrieve(m_ConVarCache, name, reinterpret_cast<void **>(&info)))
   2.205 +		/* First find out if we already have a handle to it */
   2.206 +		if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo))
   2.207  		{
   2.208 -			// If we do, then return that handle
   2.209 -			return info->handle;
   2.210 +			return pInfo->handle;
   2.211  		} else {
   2.212 -			// If we don't, then create a new handle from the convar
   2.213 +			/* If we don't, then create a new handle from the convar */
   2.214  			hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
   2.215  
   2.216 -			info = new ConVarInfo;
   2.217 -			info->handle = hndl;
   2.218 -			info->sourceMod = false;
   2.219 -			info->changeForward = NULL;
   2.220 -			info->origCallback = pConVar->GetCallback();
   2.221 +			/* Create and initialize ConVarInfo structure */
   2.222 +			pInfo = new ConVarInfo();
   2.223 +			pInfo->handle = hndl;
   2.224 +			pInfo->sourceMod = false;
   2.225 +			pInfo->changeForward = NULL;
   2.226 +			pInfo->origCallback = pConVar->GetCallback();
   2.227  
   2.228 -			m_ConVars.push_back(info);
   2.229 +			/* Insert struct into caches */
   2.230 +			m_ConVars.push_back(pInfo);
   2.231 +			sm_trie_insert(m_ConVarCache, name, pInfo);
   2.232  
   2.233  			return hndl;
   2.234  		}
   2.235 @@ -201,47 +206,33 @@
   2.236  
   2.237  	while (pBase)
   2.238  	{
   2.239 -		if (strcmp(pBase->GetName(), name) == 0)
   2.240 +		if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0)
   2.241  		{
   2.242 -			return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name);
   2.243 +			return BAD_HANDLE;
   2.244  		}
   2.245  
   2.246  		pBase = const_cast<ConCommandBase *>(pBase->GetNext());
   2.247  	}
   2.248  
   2.249 -	// Since we didn't find an existing convar (or concmd with the same name), now we can finally create it!
   2.250 -	pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(helpText), hasMin, min, hasMax, max);
   2.251 -
   2.252 -	// Find plugin creating convar
   2.253 -	IPlugin *pl = g_PluginSys.FindPluginByContext(pContext->GetContext());
   2.254 -
   2.255 -	// Get convar list from 'ConVar' property of plugin
   2.256 -	pl->GetProperty("ConVarList", reinterpret_cast<void **>(&cvarList));
   2.257 +	/* Since an existing convar (or concmd with the same name) was not found , now we can finally create it */
   2.258 +	pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(description), hasMin, min, hasMax, max);
   2.259  
   2.260 -	// If 'ConVar' property doesn't exist...
   2.261 -	if (cvarList == NULL)
   2.262 -	{
   2.263 -		// Then create it
   2.264 -		cvarList = new CVector<ConVar *>;
   2.265 -		pl->SetProperty("ConVarList", cvarList);
   2.266 -	}
   2.267 +	/* Add convar to plugin's list */
   2.268 +	AddConVarToPluginList(pContext, pConVar);
   2.269  
   2.270 -	// Add new convar to plugin's list
   2.271 -	cvarList->push_back(pConVar);
   2.272 -
   2.273 -	// Create a handle from the new convar
   2.274 +	/* Create a handle from the new convar */
   2.275  	hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
   2.276  
   2.277 -	info = new ConVarInfo;
   2.278 -	info->handle = hndl;
   2.279 -	info->sourceMod = true;
   2.280 -	info->changeForward = NULL;
   2.281 -	info->origCallback = NULL;
   2.282 +	/* Create and initialize ConVarInfo structure */
   2.283 +	pInfo = new ConVarInfo();
   2.284 +	pInfo->handle = hndl;
   2.285 +	pInfo->sourceMod = true;
   2.286 +	pInfo->changeForward = NULL;
   2.287 +	pInfo->origCallback = NULL;
   2.288  
   2.289 -	m_ConVars.push_back(info);
   2.290 -
   2.291 -	// Insert the handle into our lookup trie
   2.292 -	sm_trie_insert(m_ConVarCache, name, info);
   2.293 +	/* Insert struct into caches */
   2.294 +	m_ConVars.push_back(pInfo);
   2.295 +	sm_trie_insert(m_ConVarCache, name, pInfo);
   2.296  
   2.297  	return hndl;
   2.298  }
   2.299 @@ -249,159 +240,165 @@
   2.300  Handle_t ConVarManager::FindConVar(const char *name)
   2.301  {
   2.302  	ConVar *pConVar = NULL;
   2.303 -	ConVarInfo *info = NULL;
   2.304 -	Handle_t hndl = 0;
   2.305 +	ConVarInfo *pInfo;
   2.306 +	Handle_t hndl;
   2.307  
   2.308 -	// Search for convar
   2.309 +	/* Search for convar */
   2.310  	pConVar = icvar->FindVar(name);
   2.311  
   2.312 -	// If it doesn't exist, then return an invalid handle
   2.313 -	if (pConVar == NULL)
   2.314 +	/* If it doesn't exist, then return an invalid handle */
   2.315 +	if (!pConVar)
   2.316  	{
   2.317  		return BAD_HANDLE;
   2.318  	}
   2.319  
   2.320 -	// At this point, convar exists, so find out if we already have a handle for it
   2.321 -	if (sm_trie_retrieve(m_ConVarCache, name, reinterpret_cast<void **>(&info)))
   2.322 +	/* At this point, the convar exists. So, find out if we already have a handle */
   2.323 +	if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo))
   2.324  	{
   2.325 -		// If we do, then return that handle
   2.326 -		return info->handle;
   2.327 +		return pInfo->handle;
   2.328  	}
   2.329  
   2.330 -	// If we don't, then create a new handle from the convar
   2.331 +	/* If we don't have a handle, then create a new one */
   2.332  	hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
   2.333  
   2.334 -	info = new ConVarInfo;
   2.335 -	info->handle = hndl;
   2.336 -	info->sourceMod = false;
   2.337 -	info->changeForward = NULL;
   2.338 -	info->origCallback = pConVar->GetCallback();
   2.339 +	/* Create and initilize ConVarInfo structure */
   2.340 +	pInfo = new ConVarInfo();
   2.341 +	pInfo->handle = hndl;
   2.342 +	pInfo->sourceMod = false;
   2.343 +	pInfo->changeForward = NULL;
   2.344 +	pInfo->origCallback = pConVar->GetCallback();
   2.345  
   2.346 -	m_ConVars.push_back(info);
   2.347 -
   2.348 -	// Insert the handle into our cache
   2.349 -	sm_trie_insert(m_ConVarCache, name, info);
   2.350 +	/* Insert struct into our caches */
   2.351 +	m_ConVars.push_back(pInfo);
   2.352 +	sm_trie_insert(m_ConVarCache, name, pInfo);
   2.353  
   2.354  	return hndl;
   2.355  }
   2.356  
   2.357 -void ConVarManager::HookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid)
   2.358 +void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
   2.359  {
   2.360 -	IPluginFunction *func = pContext->GetFunctionById(funcid);
   2.361 -	IChangeableForward *fwd = NULL;
   2.362 -	char fwdName[64];
   2.363 -	ConVarInfo *info = NULL;
   2.364 -
   2.365 -	// This shouldn't happen...
   2.366 -	if (func == NULL)
   2.367 -	{
   2.368 -		pContext->ThrowNativeError("Invalid function specified");
   2.369 -		return;
   2.370 -	}
   2.371 -
   2.372 -	// Create a forward name
   2.373 -	UTIL_Format(fwdName, sizeof(fwdName), "ConVar.%s", pConVar->GetName());
   2.374 +	ConVarInfo *pInfo;
   2.375 +	IChangeableForward *pForward;
   2.376  
   2.377 -	// First find out if the forward already exists
   2.378 -	g_Forwards.FindForward(fwdName, &fwd);
   2.379 -
   2.380 -	// If the forward doesn't exist...
   2.381 -	if (fwd == NULL)
   2.382 +	/* Find the convar in the lookup trie */
   2.383 +	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), (void **)&pInfo))
   2.384  	{
   2.385 -		// This is the forward's parameter type list
   2.386 -		ParamType p[] = {Param_Cell, Param_String, Param_String};
   2.387 +		/* Get the forward */
   2.388 +		pForward = pInfo->changeForward;
   2.389  
   2.390 -		// Create the forward
   2.391 -		fwd = g_Forwards.CreateForwardEx(fwdName, ET_Ignore, 3, p);
   2.392 +		/* If forward does not exist, create it */
   2.393 +		if (!pForward)
   2.394 +		{
   2.395 +			pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
   2.396 +			pInfo->changeForward = pForward;
   2.397  
   2.398 -		// Find the convar in the lookup trie
   2.399 -		if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info)))
   2.400 -		{
   2.401 -			// Set the convar's forward to the newly created one
   2.402 -			info->changeForward = fwd;
   2.403 -
   2.404 -			// Set the convar's callback to our static one
   2.405 +			/* Install our own callback */
   2.406  			pConVar->InstallChangeCallback(OnConVarChanged);
   2.407  		}
   2.408 +
   2.409 +		/* Add function to forward's list */
   2.410 +		pForward->AddFunction(pFunction);
   2.411  	}
   2.412 -
   2.413 -	// Add the function to the forward's list
   2.414 -	fwd->AddFunction(func);
   2.415  }
   2.416  
   2.417 -void ConVarManager::UnhookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid)
   2.418 +void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
   2.419  {
   2.420 -	IPluginFunction *func = pContext->GetFunctionById(funcid);
   2.421 -	IChangeableForward *fwd = NULL;
   2.422 -	ConVarInfo *info = NULL;
   2.423 +	ConVarInfo *pInfo;
   2.424 +	IChangeableForward *pForward;
   2.425 +	IPluginContext *pContext = pFunction->GetParentContext();
   2.426  
   2.427 -	// This shouldn't happen...
   2.428 -	if (func == NULL)
   2.429 +	/* Find the convar in the lookup trie */
   2.430 +	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), (void **)&pInfo))
   2.431  	{
   2.432 -		pContext->ThrowNativeError("Invalid function specified");
   2.433 -		return;
   2.434 -	}
   2.435 +		/* Get the forward */
   2.436 +		pForward = pInfo->changeForward;
   2.437  
   2.438 -	// Find the convar in the lookup trie
   2.439 -	if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info)))
   2.440 -	{
   2.441 -		// Get the forward
   2.442 -		fwd = info->changeForward;
   2.443 -
   2.444 -		// If the forward doesn't exist, we can't unhook anything
   2.445 -		if (fwd == NULL)
   2.446 +		/* If the forward doesn't exist, we can't unhook anything */
   2.447 +		if (!pForward)
   2.448  		{
   2.449  			pContext->ThrowNativeError("Convar \"%s\" has no active hook", pConVar->GetName());
   2.450  			return;
   2.451  		}
   2.452  
   2.453 -		// Remove the function from the forward's list
   2.454 -		if (!fwd->RemoveFunction(func))
   2.455 +		/* Remove the function from the forward's list */
   2.456 +		if (!pForward->RemoveFunction(pFunction))
   2.457  		{
   2.458  			pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", pConVar->GetName());
   2.459  			return;
   2.460  		}
   2.461  
   2.462 -		// If the forward now has 0 functions in it...
   2.463 -		if (fwd->GetFunctionCount() == 0)
   2.464 +		/* If the forward now has 0 functions in it... */
   2.465 +		if (pForward->GetFunctionCount() == 0)
   2.466  		{
   2.467 -			// Free this forward
   2.468 -			g_Forwards.ReleaseForward(fwd);
   2.469 -			info->changeForward = NULL;
   2.470 +			/* Free this forward */
   2.471 +			g_Forwards.ReleaseForward(pForward);
   2.472 +			pInfo->changeForward = NULL;
   2.473 +
   2.474 +			/* Put back the original convar callback */
   2.475 +			pConVar->InstallChangeCallback(pInfo->origCallback);
   2.476 +		}
   2.477 +	}
   2.478 +}
   2.479 +
   2.480 +void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar)
   2.481 +{
   2.482 +	ConVarList *pConVarList;
   2.483 +	ConVarList::iterator iter;
   2.484 +	bool inserted = false;
   2.485 +	const char *orig = pConVar->GetName();
   2.486 +
   2.487 +	IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
   2.488  
   2.489 -			// Put the back the original convar callback
   2.490 -			pConVar->InstallChangeCallback(info->origCallback);
   2.491 +	/* Check plugin for an existing convar list */
   2.492 +	if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
   2.493 +	{
   2.494 +		pConVarList = new ConVarList();
   2.495 +		plugin->SetProperty("ConVarList", pConVarList);
   2.496 +	}
   2.497 +
   2.498 +	/* Insert convar into list which is sorted alphabetically */
   2.499 +	for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
   2.500 +	{
   2.501 +		if (strcmp(orig, (*iter)->GetName()) < 0)
   2.502 +		{
   2.503 +			pConVarList->insert(iter, pConVar);
   2.504 +			inserted = true;
   2.505 +			break;
   2.506  		}
   2.507  	}
   2.508 +
   2.509 +	if (!inserted)
   2.510 +	{
   2.511 +		pConVarList->push_back(pConVar);
   2.512 +	}
   2.513  }
   2.514  
   2.515  void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
   2.516  {
   2.517 -	// If the values are the same...
   2.518 +	/* If the values are the same, exit early in order to not trigger callbacks */
   2.519  	if (strcmp(pConVar->GetString(), oldValue) == 0)
   2.520  	{
   2.521 -		// Exit early in order to not trigger callbacks
   2.522  		return;
   2.523  	}
   2.524  
   2.525 -	Trie *cache = g_ConVarManager.GetConVarCache();
   2.526 -	ConVarInfo *info;
   2.527 +	Trie *pCache = g_ConVarManager.GetConVarCache();
   2.528 +	ConVarInfo *pInfo;
   2.529  
   2.530 -	// Find the convar in the lookup trie
   2.531 -	sm_trie_retrieve(cache, pConVar->GetName(), reinterpret_cast<void **>(&info));
   2.532 +	/* Find the convar in the lookup trie */
   2.533 +	sm_trie_retrieve(pCache, pConVar->GetName(), (void **)&pInfo);
   2.534  
   2.535 -	FnChangeCallback origCallback = info->origCallback;
   2.536 -	IChangeableForward *fwd = info->changeForward;
   2.537 +	FnChangeCallback origCallback = pInfo->origCallback;
   2.538 +	IChangeableForward *pForward = pInfo->changeForward;
   2.539  
   2.540 -	// If there was a change callback installed previously, call it
   2.541 +	/* If there was a change callback installed previously, call it */
   2.542  	if (origCallback)
   2.543  	{
   2.544  		origCallback(pConVar, oldValue);
   2.545  	}
   2.546  
   2.547 -	// Now call forwards in plugins that have hooked this
   2.548 -	fwd->PushCell(info->handle);
   2.549 -	fwd->PushString(pConVar->GetString());
   2.550 -	fwd->PushString(oldValue);
   2.551 -	fwd->Execute(NULL);
   2.552 +	/* Now call forwards in plugins that have hooked this */
   2.553 +	pForward->PushCell(pInfo->handle);
   2.554 +	pForward->PushString(oldValue);
   2.555 +	pForward->PushString(pConVar->GetString());
   2.556 +	pForward->Execute(NULL);
   2.557  }
     3.1 --- a/core/ConVarManager.h	Tue Mar 06 07:38:19 2007 +0000
     3.2 +++ b/core/ConVarManager.h	Tue Mar 06 23:59:25 2007 +0000
     3.3 @@ -51,7 +51,7 @@
     3.4  public: // IHandleTypeDispatch
     3.5  	void OnHandleDestroy(HandleType_t type, void *object);
     3.6  public: // IPluginsListener
     3.7 -	void OnPluginDestroyed(IPlugin *plugin);
     3.8 +	void OnPluginUnloaded(IPlugin *plugin);
     3.9  public: //IRootConsoleCommand
    3.10  	void OnRootConsoleCommand(const char *command, unsigned int argcount);
    3.11  public:
    3.12 @@ -74,8 +74,8 @@
    3.13  	/**
    3.14  	 * Create a convar and return a handle to it.
    3.15  	 */
    3.16 -	Handle_t CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *helpText,
    3.17 -	                      int flags, bool hasMin, float min, bool hasMax, float max);
    3.18 +	Handle_t CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal,
    3.19 +	                      const char *description, int flags, bool hasMin, float min, bool hasMax, float max);
    3.20  
    3.21  	/**
    3.22  	 * Searches for a convar and returns a handle to it
    3.23 @@ -85,14 +85,19 @@
    3.24  	/**
    3.25  	 * Add a function to call when the specified convar changes.
    3.26  	 */
    3.27 -	void HookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid);
    3.28 +	void HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction);
    3.29  
    3.30  	/**
    3.31  	 * Remove a function from the forward that will be called when the specified convar changes.
    3.32  	 */
    3.33 -	void UnhookConVarChange(IPluginContext *pContext, ConVar *pConVar, funcid_t funcid);
    3.34 +	void UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction);
    3.35  private:
    3.36  	/**
    3.37 +	 * Adds a convar to a plugin's list.
    3.38 +	 */
    3.39 +	static void AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar);
    3.40 +
    3.41 +	/**
    3.42  	 * Static callback that Valve's ConVar class executes when the convar's value changes.
    3.43  	 */
    3.44  	static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
     4.1 --- a/core/EventManager.cpp	Tue Mar 06 07:38:19 2007 +0000
     4.2 +++ b/core/EventManager.cpp	Tue Mar 06 23:59:25 2007 +0000
     4.3 @@ -21,10 +21,9 @@
     4.4  
     4.5  SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool);
     4.6  
     4.7 +const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
     4.8  typedef List<EventHook *> EventHookList;
     4.9  
    4.10 -const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
    4.11 -
    4.12  EventManager::EventManager() : m_EventType(0), m_NotifyPlugins(true), m_EventCopy(NULL)
    4.13  {
    4.14  	/* Create an event lookup trie */
    4.15 @@ -93,12 +92,13 @@
    4.16  void EventManager::OnPluginUnloaded(IPlugin *plugin)
    4.17  {
    4.18  	EventHookList *pHookList;
    4.19 +	EventHookList::iterator iter;
    4.20  	EventHook *pHook;
    4.21  
    4.22  	// If plugin has an event hook list...
    4.23  	if (plugin->GetProperty("EventHooks", reinterpret_cast<void **>(&pHookList), true))
    4.24  	{
    4.25 -		for (EventHookList::iterator iter = pHookList->begin(); iter != pHookList->end(); iter++)
    4.26 +		for (iter = pHookList->begin(); iter != pHookList->end(); iter++)
    4.27  		{
    4.28  			pHook = (*iter);
    4.29  
     5.1 --- a/core/EventManager.h	Tue Mar 06 07:38:19 2007 +0000
     5.2 +++ b/core/EventManager.h	Tue Mar 06 23:59:25 2007 +0000
     5.3 @@ -11,8 +11,8 @@
     5.4  * Version: $Id$
     5.5  */
     5.6  
     5.7 -#ifndef _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_
     5.8 -#define _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_
     5.9 +#ifndef _INCLUDE_SOURCEMOD_EVENTMANAGER_H_
    5.10 +#define _INCLUDE_SOURCEMOD_EVENTMANAGER_H_
    5.11  
    5.12  #include "sm_globals.h"
    5.13  #include "sourcemm_api.h"
    5.14 @@ -109,4 +109,4 @@
    5.15  
    5.16  extern EventManager g_EventManager;
    5.17  
    5.18 -#endif // _INCLUDE_SOURCEMOD_CGAMEEVENTMANAGER_H_
    5.19 +#endif // _INCLUDE_SOURCEMOD_EVENTMANAGER_H_
     6.1 --- a/core/sm_stringutil.h	Tue Mar 06 07:38:19 2007 +0000
     6.2 +++ b/core/sm_stringutil.h	Tue Mar 06 23:59:25 2007 +0000
     6.3 @@ -22,6 +22,8 @@
     6.4  
     6.5  #define LANG_SERVER		0
     6.6  
     6.7 +#define IS_STR_FILLED(var) (var[0] != '\0')
     6.8 +
     6.9  size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param);
    6.10  const char *stristr(const char *str, const char *substr);
    6.11  unsigned int strncopy(char *dest, const char *src, size_t count);
     7.1 --- a/core/smn_console.cpp	Tue Mar 06 07:38:19 2007 +0000
     7.2 +++ b/core/smn_console.cpp	Tue Mar 06 23:59:25 2007 +0000
     7.3 @@ -29,7 +29,7 @@
     7.4  	// While the engine seems to accept a blank convar name, it causes a crash upon server quit
     7.5  	if (name == NULL || strcmp(name, "") == 0)
     7.6  	{
     7.7 -		return pContext->ThrowNativeError("Null or blank convar name is not allowed");
     7.8 +		return pContext->ThrowNativeError("Convar with blank name is not permitted");
     7.9  	}
    7.10  
    7.11  	pContext->LocalToString(params[2], &defaultVal);
    7.12 @@ -40,7 +40,14 @@
    7.13  	float min = sp_ctof(params[6]);
    7.14  	float max = sp_ctof(params[8]);
    7.15  
    7.16 -	return g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
    7.17 +	Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
    7.18 +
    7.19 +	if (hndl == BAD_HANDLE)
    7.20 +	{
    7.21 +		return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name);
    7.22 +	}
    7.23 +
    7.24 +	return hndl;
    7.25  }
    7.26  
    7.27  static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params)
    7.28 @@ -49,12 +56,6 @@
    7.29  
    7.30  	pContext->LocalToString(params[1], &name);
    7.31  
    7.32 -	// While the engine seems to accept a blank convar name, it causes a crash upon server quit
    7.33 -	if (name == NULL || strcmp(name, "") == 0)
    7.34 -	{
    7.35 -		return BAD_HANDLE;
    7.36 -	}
    7.37 -
    7.38  	return g_ConVarManager.FindConVar(name);
    7.39  }
    7.40  
    7.41 @@ -70,7 +71,14 @@
    7.42  		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
    7.43  	}
    7.44  
    7.45 -	g_ConVarManager.HookConVarChange(pContext, pConVar, static_cast<funcid_t>(params[2]));
    7.46 +	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
    7.47 +
    7.48 +	if (!pFunction)
    7.49 +	{
    7.50 +		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
    7.51 +	}
    7.52 +
    7.53 +	g_ConVarManager.HookConVarChange(pConVar, pFunction);
    7.54  
    7.55  	return 1;
    7.56  }
    7.57 @@ -87,7 +95,14 @@
    7.58  		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
    7.59  	}
    7.60  
    7.61 -	g_ConVarManager.UnhookConVarChange(pContext, pConVar, static_cast<funcid_t>(params[2]));
    7.62 +	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
    7.63 +
    7.64 +	if (!pFunction)
    7.65 +	{
    7.66 +		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
    7.67 +	}
    7.68 +
    7.69 +	g_ConVarManager.UnhookConVarChange(pConVar, pFunction);
    7.70  
    7.71  	return 1;
    7.72  }
     8.1 --- a/core/systems/PluginSys.cpp	Tue Mar 06 07:38:19 2007 +0000
     8.2 +++ b/core/systems/PluginSys.cpp	Tue Mar 06 23:59:25 2007 +0000
     8.3 @@ -1415,7 +1415,6 @@
     8.4  	}
     8.5  }
     8.6  
     8.7 -#define IS_STR_FILLED(var) (var[0] != '\0')
     8.8  void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argcount)
     8.9  {
    8.10  	if (argcount >= 3)
    8.11 @@ -1432,7 +1431,7 @@
    8.12  				g_RootMenu.ConsolePrint("[SM] No plugins loaded");
    8.13  				return;
    8.14  			} else {
    8.15 -				g_RootMenu.ConsolePrint("[SM] Displaying %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : "");
    8.16 +				g_RootMenu.ConsolePrint("[SM] Listing %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : "");
    8.17  			}
    8.18  
    8.19  			IPluginIterator *iter = GetPluginIterator();
     9.1 --- a/plugins/include/console.inc	Tue Mar 06 07:38:19 2007 +0000
     9.2 +++ b/plugins/include/console.inc	Tue Mar 06 23:59:25 2007 +0000
     9.3 @@ -209,7 +209,7 @@
     9.4   *
     9.5   * @param name			Name of new convar.
     9.6   * @param defaultValue	String containing the default value of new convar.
     9.7 - * @param helpText		Optional description of the convar.
     9.8 + * @param description	Optional description of the convar.
     9.9   * @param flags			Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details.
    9.10   * @param hasMin		Optional boolean that determines if the convar has a minimum value.
    9.11   * @param min			Minimum floating point value that the convar can have if hasMin is true.
    9.12 @@ -218,7 +218,7 @@
    9.13   * @return				A handle to the newly created convar. If the convar already exists, INVALID_HANDLE is returned.
    9.14   * @error				Convar name is blank or is the same as an existing console command.
    9.15   */
    9.16 -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);
    9.17 +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);
    9.18  
    9.19  /**
    9.20   * Searches for a console variable.
    9.21 @@ -236,7 +236,7 @@
    9.22   * @param newValue		String containing the new value of the convar.
    9.23   * @noreturn
    9.24   */
    9.25 -functag OnConVarChanged public(Handle:convar, const String:oldValue[], const String:newValue[]);
    9.26 +functag ConVarChanged public(Handle:convar, const String:oldValue[], const String:newValue[]);
    9.27  
    9.28  /**
    9.29   * Creates a hook for when a console variable's value is changed.
    9.30 @@ -246,7 +246,7 @@
    9.31   * @noreturn
    9.32   * @error				Invalid or corrupt Handle or invalid callback function.
    9.33   */
    9.34 -native HookConVarChange(Handle:convar, OnConVarChanged:callback);
    9.35 +native HookConVarChange(Handle:convar, ConVarChanged:callback);
    9.36  
    9.37  /**
    9.38   * Removes a hook for when a console variable's value is changed.
    9.39 @@ -256,7 +256,7 @@
    9.40   * @noreturn
    9.41   * @error				Invalid or corrupt Handle, invalid callback function, or no active hook on convar.
    9.42   */
    9.43 -native UnhookConVarChange(Handle:convar, OnConVarChanged:callback);
    9.44 +native UnhookConVarChange(Handle:convar, ConVarChanged:callback);
    9.45  
    9.46  /**
    9.47   * Returns the boolean value of a console variable.