core/smn_console.cpp
author David Anderson <dvander@alliedmods.net>
Mon Sep 07 21:29:18 2009 -0700 (2009-09-07)
changeset 2798 6dd90eaa0593
parent 2684 a802f5cebe28
child 2800 74c32429908e
permissions -rw-r--r--
Fixed invalid array access in PluginSys (bug 3933, r=pred).
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "sm_globals.h"
    33 #include "HalfLife2.h"
    34 #include "sourcemm_api.h"
    35 #include "HandleSys.h"
    36 #include "ConVarManager.h"
    37 #include "ConCmdManager.h"
    38 #include "PluginSys.h"
    39 #include "sm_stringutil.h"
    40 #include "PlayerManager.h"
    41 #include "ChatTriggers.h"
    42 #include "AdminCache.h"
    43 #include <inetchannel.h>
    44 #include <bitbuf.h>
    45 #include <sm_trie_tpl.h>
    46 
    47 #if SOURCE_ENGINE == SE_LEFT4DEAD
    48 #define NET_SETCONVAR	6
    49 #else
    50 #define NET_SETCONVAR	5
    51 #endif
    52 
    53 enum ConVarBounds
    54 {
    55 	ConVarBound_Upper = 0,
    56 	ConVarBound_Lower
    57 };
    58 
    59 HandleType_t hCmdIterType = 0;
    60 HandleType_t htConCmdIter = 0;
    61 
    62 struct GlobCmdIter
    63 {
    64 	bool started;
    65 	List<ConCmdInfo *>::iterator iter;
    66 };
    67 
    68 struct ConCmdIter
    69 {
    70 #if SOURCE_ENGINE == SE_LEFT4DEAD
    71 	ICvarIteratorInternal *pLast;
    72 #else
    73 	const ConCommandBase *pLast;
    74 #endif
    75 };
    76 
    77 class ConsoleHelpers : 
    78 	public SMGlobalClass,
    79 	public IHandleTypeDispatch
    80 {
    81 public:
    82 	virtual void OnSourceModAllInitialized()
    83 	{
    84 		HandleAccess access;
    85 
    86 		g_HandleSys.InitAccessDefaults(NULL, &access);
    87 
    88 		htConCmdIter = g_HandleSys.CreateType("ConCmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
    89 
    90 		access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER | HANDLE_RESTRICT_IDENTITY;
    91 
    92 		hCmdIterType = g_HandleSys.CreateType("CmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
    93 	}
    94 	virtual void OnHandleDestroy(HandleType_t type, void *object)
    95 	{
    96 		if (type == hCmdIterType)
    97 		{
    98 			GlobCmdIter *iter = (GlobCmdIter *)object;
    99 			delete iter;
   100 		}
   101 		else if (type == htConCmdIter)
   102 		{
   103 			ConCmdIter *iter = (ConCmdIter * )object;
   104 #if SOURCE_ENGINE == SE_LEFT4DEAD
   105 			// ICvarIteratorInternal has no virtual destructor
   106 			g_pMemAlloc->Free(iter->pLast);
   107 #endif
   108 			delete iter;
   109 		}
   110 	}
   111 	virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
   112 	{
   113 		if (type == htConCmdIter)
   114 		{
   115 			*pSize = sizeof(ConCmdIter);
   116 			return true;
   117 		}
   118 		else if (type == hCmdIterType)
   119 		{
   120 			*pSize = sizeof(GlobCmdIter);
   121 			return true;
   122 		}
   123 		return false;
   124 	}
   125 } s_ConsoleHelpers;
   126 
   127 class CommandFlagsHelper : public IConCommandTracker
   128 {
   129 public:
   130 	void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
   131 	{
   132 		m_CmdFlags.remove(name);
   133 	}
   134 	bool GetFlags(const char *name, int *flags)
   135 	{
   136 		ConCommandBase **ppCmd;
   137 		ConCommandBase *pCmd;
   138 		if ((ppCmd=m_CmdFlags.retrieve(name)))
   139 		{
   140 			TrackConCommandBase((*ppCmd), this);
   141 			*flags = (*ppCmd)->GetFlags();
   142 			return true;
   143 		}
   144 		else if ((pCmd=FindCommandBase(name)))
   145 		{
   146 			m_CmdFlags.insert(name, pCmd);
   147 			TrackConCommandBase(pCmd, this);
   148 			*flags = pCmd->GetFlags();
   149 			return true;
   150 		}
   151 		else
   152 		{
   153 			return false;
   154 		}
   155 	}
   156 	bool SetFlags(const char *name, int flags)
   157 	{
   158 		ConCommandBase **ppCmd;
   159 		ConCommandBase *pCmd;
   160 		if ((ppCmd=m_CmdFlags.retrieve(name)))
   161 		{
   162 			(*ppCmd)->SetFlags(flags);
   163 			TrackConCommandBase((*ppCmd), this);
   164 			return true;
   165 		}
   166 		else if ((pCmd=FindCommandBase(name)))
   167 		{
   168 			m_CmdFlags.insert(name, pCmd);
   169 			pCmd->SetFlags(flags);
   170 			TrackConCommandBase(pCmd, this);
   171 			return true;
   172 		}
   173 		else
   174 		{
   175 			return false;
   176 		}
   177 	}
   178 private:
   179 	KTrie<ConCommandBase *> m_CmdFlags;
   180 } s_CommandFlagsHelper;
   181 
   182 #if SOURCE_ENGINE >= SE_ORANGEBOX
   183 static void ReplicateConVar(ConVar *pConVar)
   184 {
   185 	int maxClients = g_Players.GetMaxClients();
   186 
   187 	char data[256];
   188 	bf_write buffer(data, sizeof(data));
   189 
   190 	buffer.WriteUBitLong(NET_SETCONVAR, 5);
   191 	buffer.WriteByte(1);
   192 	buffer.WriteString(pConVar->GetName());
   193 	buffer.WriteString(pConVar->GetString());
   194 
   195 	for (int i = 1; i <= maxClients; i++)
   196 	{
   197 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
   198 
   199 		if (pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient())
   200 		{
   201 			INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(i));
   202 			netchan->SendData(buffer);
   203 		}
   204 	}
   205 }
   206 
   207 static void NotifyConVar(ConVar *pConVar)
   208 {
   209 	IGameEvent *pEvent = gameevents->CreateEvent("server_cvar");
   210 	pEvent->SetString("cvarname", pConVar->GetName());
   211 	if (IsFlagSet(pConVar, FCVAR_PROTECTED))
   212 	{
   213 		pEvent->SetString("cvarvalue", "***PROTECTED***");
   214 	}
   215 	else
   216 	{
   217 		pEvent->SetString("cvarvalue", pConVar->GetString());
   218 	}
   219 
   220 	gameevents->FireEvent(pEvent);
   221 }
   222 #endif
   223 
   224 static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params)
   225 {
   226 	char *name, *defaultVal, *helpText;
   227 
   228 	pContext->LocalToString(params[1], &name);
   229 
   230 	// While the engine seems to accept a blank convar name, it causes a crash upon server quit
   231 	if (name == NULL || strcmp(name, "") == 0)
   232 	{
   233 		return pContext->ThrowNativeError("Convar with blank name is not permitted");
   234 	}
   235 
   236 	pContext->LocalToString(params[2], &defaultVal);
   237 	pContext->LocalToString(params[3], &helpText);
   238 
   239 	bool hasMin = params[5] ? true : false;
   240 	bool hasMax = params[7] ? true : false;
   241 	float min = sp_ctof(params[6]);
   242 	float max = sp_ctof(params[8]);
   243 
   244 	Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
   245 
   246 	if (hndl == BAD_HANDLE)
   247 	{
   248 		return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same might already exist.", name);
   249 	}
   250 
   251 	return hndl;
   252 }
   253 
   254 static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params)
   255 {
   256 	char *name;
   257 
   258 	pContext->LocalToString(params[1], &name);
   259 
   260 	return g_ConVarManager.FindConVar(name);
   261 }
   262 
   263 static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params)
   264 {
   265 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   266 	HandleError err;
   267 	ConVar *pConVar;
   268 
   269 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   270 		!= HandleError_None)
   271 	{
   272 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   273 	}
   274 
   275 	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
   276 
   277 	if (!pFunction)
   278 	{
   279 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   280 	}
   281 
   282 	g_ConVarManager.HookConVarChange(pConVar, pFunction);
   283 
   284 	return 1;
   285 }
   286 
   287 static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *params)
   288 {
   289 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   290 	HandleError err;
   291 	ConVar *pConVar;
   292 
   293 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   294 		!= HandleError_None)
   295 	{
   296 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   297 	}
   298 
   299 	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
   300 
   301 	if (!pFunction)
   302 	{
   303 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   304 	}
   305 
   306 	g_ConVarManager.UnhookConVarChange(pConVar, pFunction);
   307 
   308 	return 1;
   309 }
   310 
   311 static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params)
   312 {
   313 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   314 	HandleError err;
   315 	ConVar *pConVar;
   316 
   317 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   318 		!= HandleError_None)
   319 	{
   320 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   321 	}
   322 
   323 	return pConVar->GetBool();
   324 }
   325 
   326 static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params)
   327 {
   328 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   329 	HandleError err;
   330 	ConVar *pConVar;
   331 
   332 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   333 		!= HandleError_None)
   334 	{
   335 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   336 	}
   337 
   338 	return pConVar->GetInt();
   339 }
   340 
   341 /* This handles both SetConVarBool() and SetConVarInt() */
   342 static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params)
   343 {
   344 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   345 	HandleError err;
   346 	ConVar *pConVar;
   347 
   348 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   349 		!= HandleError_None)
   350 	{
   351 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   352 	}
   353 
   354 	pConVar->SetValue(params[2]);
   355 
   356 #if SOURCE_ENGINE >= SE_ORANGEBOX
   357 	/* Should we replicate it? */
   358 	if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
   359 	{
   360 		ReplicateConVar(pConVar);
   361 	}
   362 
   363 	/* Should we notify clients? */
   364 	if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
   365 	{
   366 		NotifyConVar(pConVar);
   367 	}
   368 #endif
   369 
   370 	return 1;
   371 }
   372 
   373 static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params)
   374 {
   375 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   376 	HandleError err;
   377 	ConVar *pConVar;
   378 
   379 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   380 		!= HandleError_None)
   381 	{
   382 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   383 	}
   384 	
   385 	float value = pConVar->GetFloat();
   386 
   387 	return sp_ftoc(value);
   388 }
   389 
   390 static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params)
   391 {
   392 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   393 	HandleError err;
   394 	ConVar *pConVar;
   395 
   396 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   397 		!= HandleError_None)
   398 	{
   399 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   400 	}
   401 
   402 	float value = sp_ctof(params[2]);
   403 	pConVar->SetValue(value);
   404 
   405 #if SOURCE_ENGINE >= SE_ORANGEBOX
   406 	/* Should we replicate it? */
   407 	if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
   408 	{
   409 		ReplicateConVar(pConVar);
   410 	}
   411 
   412 	/* Should we notify clients? */
   413 	if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
   414 	{
   415 		NotifyConVar(pConVar);
   416 	}
   417 #endif
   418 
   419 	return 1;
   420 }
   421 
   422 static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params)
   423 {
   424 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   425 	HandleError err;
   426 	ConVar *pConVar;
   427 
   428 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   429 		!= HandleError_None)
   430 	{
   431 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   432 	}
   433 
   434 	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL);
   435 
   436 	return 1;
   437 }
   438 
   439 static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
   440 {
   441 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   442 	HandleError err;
   443 	ConVar *pConVar;
   444 
   445 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   446 		!= HandleError_None)
   447 	{
   448 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   449 	}
   450 
   451 	char *value;
   452 	pContext->LocalToString(params[2], &value);
   453 
   454 	pConVar->SetValue(value);
   455 
   456 #if SOURCE_ENGINE >= SE_ORANGEBOX
   457 	/* Should we replicate it? */
   458 	if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
   459 	{
   460 		ReplicateConVar(pConVar);
   461 	}
   462 
   463 	/* Should we notify clients? */
   464 	if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
   465 	{
   466 		NotifyConVar(pConVar);
   467 	}
   468 #endif
   469 
   470 	return 1;
   471 }
   472 
   473 static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params)
   474 {
   475 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   476 	HandleError err;
   477 	ConVar *pConVar;
   478 
   479 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   480 		!= HandleError_None)
   481 	{
   482 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   483 	}
   484 
   485 	pConVar->Revert();
   486 	
   487 #if SOURCE_ENGINE >= SE_ORANGEBOX
   488 	/* Should we replicate it? */
   489 	if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
   490 	{
   491 		ReplicateConVar(pConVar);
   492 	}
   493 
   494 	/* Should we notify clients? */
   495 	if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
   496 	{
   497 		NotifyConVar(pConVar);
   498 	}
   499 #endif
   500 
   501 	return 1;
   502 }
   503 
   504 static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
   505 {
   506 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   507 	HandleError err;
   508 	ConVar *pConVar;
   509 
   510 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   511 		!= HandleError_None)
   512 	{
   513 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   514 	}
   515 
   516 	return pConVar->GetFlags();
   517 }
   518 
   519 static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
   520 {
   521 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   522 	HandleError err;
   523 	ConVar *pConVar;
   524 
   525 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   526 		!= HandleError_None)
   527 	{
   528 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   529 	}
   530 
   531 	pConVar->SetFlags(params[2]);
   532 
   533 	return 1;
   534 }
   535 
   536 static cell_t sm_GetConVarBounds(IPluginContext *pContext, const cell_t *params)
   537 {
   538 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   539 	HandleError err;
   540 	ConVar *pConVar;
   541 
   542 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   543 		!= HandleError_None)
   544 	{
   545 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   546 	}
   547 
   548 	cell_t *addr;
   549 	bool hasBound;
   550 	float bound;
   551 
   552 	switch (params[2])
   553 	{
   554 	case ConVarBound_Upper:
   555 		hasBound = pConVar->GetMax(bound);
   556 		break;
   557 	case ConVarBound_Lower:
   558 		hasBound = pConVar->GetMin(bound);
   559 		break;
   560 	default:
   561 		return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
   562 	}
   563 	
   564 	pContext->LocalToPhysAddr(params[3], &addr);
   565 	*addr = sp_ftoc(bound);
   566 
   567 	return hasBound;
   568 }
   569 
   570 static cell_t sm_SetConVarBounds(IPluginContext *pContext, const cell_t *params)
   571 {
   572 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   573 	HandleError err;
   574 	ConVar *pConVar;
   575 
   576 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   577 		!= HandleError_None)
   578 	{
   579 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   580 	}
   581 
   582 	switch (params[2])
   583 	{
   584 	case ConVarBound_Upper:
   585 		pConVar->SetMax(params[3] ? true : false, sp_ctof(params[4]));
   586 		break;
   587 	case ConVarBound_Lower:
   588 		pConVar->SetMin(params[3] ? true : false, sp_ctof(params[4]));
   589 		break;
   590 	default:
   591 		return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
   592 	}
   593 
   594 	return 1;
   595 }
   596 
   597 static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params)
   598 {
   599 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   600 	HandleError err;
   601 	ConVar *pConVar;
   602 
   603 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
   604 		!= HandleError_None)
   605 	{
   606 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   607 	}
   608 
   609 	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL);
   610 
   611 	return 1;
   612 }
   613 
   614 static bool s_QueryAlreadyWarned = false;
   615 
   616 static cell_t sm_QueryClientConVar(IPluginContext *pContext, const cell_t *params)
   617 {
   618 	CPlayer *pPlayer;
   619 	char *name;
   620 	IPluginFunction *pCallback;
   621 
   622 	if (!g_ConVarManager.IsQueryingSupported())
   623 	{
   624 		if (!s_QueryAlreadyWarned)
   625 		{
   626 			s_QueryAlreadyWarned = true;
   627 			return pContext->ThrowNativeError("Game does not support client convar querying (one time warning)");
   628 		}
   629 
   630 		return 0;
   631 	}
   632 
   633 	pPlayer = g_Players.GetPlayerByIndex(params[1]);
   634 
   635 	if (!pPlayer)
   636 	{
   637 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
   638 	}
   639 
   640 	if (!pPlayer->IsConnected())
   641 	{
   642 		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
   643 	}
   644 
   645 	/* Trying a query on a bot results in callback not be fired, so don't bother */
   646 	if (pPlayer->IsFakeClient())
   647 	{
   648 		return 0;
   649 	}
   650 
   651 	pContext->LocalToString(params[2], &name);
   652 	pCallback = pContext->GetFunctionById(params[3]);
   653 
   654 	if (!pCallback)
   655 	{
   656 		return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
   657 	}
   658 
   659 	return g_ConVarManager.QueryClientConVar(pPlayer->GetEdict(), name, pCallback, params[4]);
   660 }
   661 
   662 static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
   663 {
   664 	char *name,*help;
   665 	IPluginFunction *pFunction;
   666 
   667 	pContext->LocalToString(params[1], &name);
   668 	pContext->LocalToString(params[3], &help);
   669 	pFunction = pContext->GetFunctionById(params[2]);
   670 
   671 	if (!pFunction)
   672 	{
   673 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   674 	}
   675 
   676 	if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4]))
   677 	{
   678 		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
   679 	}
   680 
   681 	return 1;
   682 }
   683 
   684 static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
   685 {
   686 	char *name,*help;
   687 	IPluginFunction *pFunction;
   688 
   689 	pContext->LocalToString(params[1], &name);
   690 	pContext->LocalToString(params[3], &help);
   691 	pFunction = pContext->GetFunctionById(params[2]);
   692 
   693 	if (!pFunction)
   694 	{
   695 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   696 	}
   697 
   698 	if (!g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4]))
   699 	{
   700 		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
   701 	}
   702 
   703 	return 1;
   704 }
   705 
   706 static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
   707 {
   708 	char *name,*help;
   709 	const char *group;
   710 	IPluginFunction *pFunction;
   711 	FlagBits flags = params[3];
   712 	int cmdflags = params[6];
   713 
   714 	pContext->LocalToString(params[1], &name);
   715 	pContext->LocalToString(params[4], &help);
   716 	pContext->LocalToString(params[5], (char **)&group);
   717 	pFunction = pContext->GetFunctionById(params[2]);
   718 
   719 	if (group[0] == '\0')
   720 	{
   721 		CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   722 		group = pPlugin->GetFilename();
   723 	}
   724 
   725 	if (!pFunction)
   726 	{
   727 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   728 	}
   729 
   730 	if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags))
   731 	{
   732 		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
   733 	}
   734 
   735 	return 1;
   736 }
   737 
   738 static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
   739 {
   740 	const CCommand *pCmd = g_HL2.PeekCommandStack();
   741 
   742 	if (!pCmd)
   743 	{
   744 		return pContext->ThrowNativeError("No command callback available");
   745 	}
   746 
   747 	return pCmd->ArgC() - 1;
   748 }
   749 
   750 static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
   751 {
   752 	const CCommand *pCmd = g_HL2.PeekCommandStack();
   753 
   754 	if (!pCmd)
   755 	{
   756 		return pContext->ThrowNativeError("No command callback available");
   757 	}
   758 
   759 	size_t length;
   760 
   761 	const char *arg = pCmd->Arg(params[1]);
   762 	
   763 	pContext->StringToLocalUTF8(params[2], params[3], arg ? arg : "", &length);
   764 
   765 	return (cell_t)length;
   766 }
   767 
   768 static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params)
   769 {
   770 	const CCommand *pCmd = g_HL2.PeekCommandStack();
   771 
   772 	if (!pCmd)
   773 	{
   774 		return pContext->ThrowNativeError("No command callback available");
   775 	}
   776 
   777 	const char *args = pCmd->ArgS();
   778 	size_t length;
   779 
   780 	if (!args)
   781 	{
   782 		args = "";
   783 	}
   784 
   785 	pContext->StringToLocalUTF8(params[1], params[2], args, &length);
   786 
   787 	return (cell_t)length;
   788 }
   789 
   790 static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params)
   791 {
   792 	char buffer[1024];
   793 	char *fmt;
   794 	int arg = 2;
   795 
   796 	pCtx->LocalToString(params[1], &fmt);
   797 	size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
   798 
   799 	buffer[res++] = '\n';
   800 	buffer[res] = '\0';
   801 
   802 	META_CONPRINT(buffer);
   803 
   804 	return 1;
   805 }
   806 
   807 static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
   808 {
   809 	int index = params[1];
   810 	if ((index < 0) || (index > g_Players.GetMaxClients()))
   811 	{
   812 		return pCtx->ThrowNativeError("Client index %d is invalid", index);
   813 	}
   814 
   815 	CPlayer *pPlayer = NULL;
   816 	if (index != 0)
   817 	{
   818 		pPlayer = g_Players.GetPlayerByIndex(index);
   819 		if (!pPlayer->IsInGame())
   820 		{
   821 			return pCtx->ThrowNativeError("Client %d is not in game", index);
   822 		}
   823 		
   824 		/* Silent fail on bots, engine will crash */
   825 		if (pPlayer->IsFakeClient())
   826 		{
   827 			return 0;
   828 		}
   829 	}
   830 
   831 	char buffer[1024];
   832 	char *fmt;
   833 	int arg = 3;
   834 
   835 	pCtx->LocalToString(params[2], &fmt);
   836 	size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
   837 
   838 	buffer[res++] = '\n';
   839 	buffer[res] = '\0';
   840 
   841 	if (index != 0)
   842 	{
   843 		engine->ClientPrintf(pPlayer->GetEdict(), buffer);
   844 	} else {
   845 		META_CONPRINT(buffer);
   846 	}
   847 
   848 	return 1;
   849 }
   850 
   851 static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
   852 {
   853 	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   854 
   855 	char buffer[1024];
   856 	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
   857 
   858 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   859 	{
   860 		return 0;
   861 	}
   862 
   863 	/* One byte for null terminator, one for newline */
   864 	buffer[len++] = '\n';
   865 	buffer[len] = '\0';
   866 
   867 	engine->ServerCommand(buffer);
   868 
   869 	return 1;
   870 }
   871 
   872 static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
   873 {
   874 	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   875 
   876 	char buffer[1024];
   877 	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
   878 
   879 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   880 	{
   881 		return 0;
   882 	}
   883 
   884 	/* One byte for null terminator, one for newline */
   885 	buffer[len++] = '\n';
   886 	buffer[len] = '\0';
   887 
   888 	InsertServerCommand(buffer);
   889 
   890 	return 1;
   891 }
   892 
   893 static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params)
   894 {
   895 	engine->ServerExecute();
   896 
   897 	return 1;
   898 }
   899 
   900 static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
   901 {
   902 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   903 
   904 	if (!pPlayer)
   905 	{
   906 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
   907 	}
   908 
   909 	if (!pPlayer->IsConnected())
   910 	{
   911 		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
   912 	}
   913 
   914 	g_SourceMod.SetGlobalTarget(params[1]);
   915 
   916 	char buffer[256];
   917 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   918 
   919 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   920 	{
   921 		return 0;
   922 	}
   923 
   924 	engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
   925 
   926 	return 1;
   927 }
   928 
   929 static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
   930 {
   931 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   932 
   933 	if (!pPlayer)
   934 	{
   935 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
   936 	}
   937 
   938 	if (!pPlayer->IsConnected())
   939 	{
   940 		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
   941 	}
   942 
   943 	char buffer[256];
   944 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   945 
   946 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   947 	{
   948 		return 0;
   949 	}
   950 
   951 	serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
   952 
   953 	return 1;
   954 }
   955 
   956 static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params)
   957 {
   958 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   959 
   960 	if (!pPlayer)
   961 	{
   962 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
   963 	}
   964 
   965 	if (!pPlayer->IsConnected())
   966 	{
   967 		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
   968 	}
   969 
   970 	char buffer[256];
   971 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   972 
   973 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   974 	{
   975 		return 0;
   976 	}
   977 
   978 	g_HL2.AddToFakeCliCmdQueue(params[1], engine->GetPlayerUserId(pPlayer->GetEdict()), buffer);
   979 
   980 	return 1;
   981 }
   982 
   983 static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
   984 {
   985 	g_SourceMod.SetGlobalTarget(params[1]);
   986 
   987 	/* Build the format string */
   988 	char buffer[1024];
   989 	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
   990 
   991 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   992 	{
   993 		return 0;
   994 	}
   995 
   996 	/* If we're printing to the server, shortcut out */
   997 	if (params[1] == 0)
   998 	{
   999 		/* Print */
  1000 		buffer[len++] = '\n';
  1001 		buffer[len] = '\0';
  1002 		META_CONPRINT(buffer);
  1003 		return 1;
  1004 	}
  1005 
  1006 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
  1007 
  1008 	if (!pPlayer)
  1009 	{
  1010 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
  1011 	}
  1012 
  1013 	if (!pPlayer->IsConnected())
  1014 	{
  1015 		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
  1016 	}
  1017 
  1018 	g_SourceMod.SetGlobalTarget(params[1]);
  1019 
  1020 	unsigned int replyto = g_ChatTriggers.GetReplyTo();
  1021 	if (replyto == SM_REPLY_CONSOLE)
  1022 	{
  1023 		buffer[len++] = '\n';
  1024 		buffer[len] = '\0';
  1025 		engine->ClientPrintf(pPlayer->GetEdict(), buffer);
  1026 	} else if (replyto == SM_REPLY_CHAT) {
  1027 		if (len >= 191)
  1028 		{
  1029 			len = 191;
  1030 		}
  1031 		buffer[len] = '\0';
  1032 		g_HL2.TextMsg(params[1], HUD_PRINTTALK, buffer);
  1033 	}
  1034 
  1035 	return 1;
  1036 }
  1037 
  1038 static cell_t GetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
  1039 {
  1040 	return g_ChatTriggers.GetReplyTo();
  1041 }
  1042 
  1043 static cell_t SetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
  1044 {
  1045 	return g_ChatTriggers.SetReplyTo(params[1]);
  1046 }
  1047 
  1048 static cell_t GetCommandIterator(IPluginContext *pContext, const cell_t *params)
  1049 {
  1050 	GlobCmdIter *iter = new GlobCmdIter;
  1051 	iter->started = false;
  1052 
  1053 	Handle_t hndl = g_HandleSys.CreateHandle(hCmdIterType, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
  1054 	if (hndl == BAD_HANDLE)
  1055 	{
  1056 		delete iter;
  1057 	}
  1058 
  1059 	return hndl;
  1060 }
  1061 
  1062 static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params)
  1063 {
  1064 	GlobCmdIter *iter;
  1065 	HandleError err;
  1066 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
  1067 
  1068 	if ((err = g_HandleSys.ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
  1069 		!= HandleError_None)
  1070 	{
  1071 		return pContext->ThrowNativeError("Invalid GlobCmdIter Handle %x", params[1]);
  1072 	}
  1073 
  1074 	const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
  1075 
  1076 	if (!iter->started)
  1077 	{
  1078 		iter->iter = cmds.begin();
  1079 		iter->started = true;
  1080 	}
  1081 
  1082 	while (iter->iter != cmds.end()
  1083 			&& !(*(iter->iter))->sourceMod)
  1084 	{
  1085 		iter->iter++;
  1086 	}
  1087 
  1088 	if (iter->iter == cmds.end())
  1089 	{
  1090 		return 0;
  1091 	}
  1092 
  1093 	ConCmdInfo *pInfo = (*(iter->iter));
  1094 
  1095 	pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetName(), NULL);
  1096 	pContext->StringToLocalUTF8(params[5], params[6], pInfo->pCmd->GetHelpText(), NULL);
  1097 	
  1098 	cell_t *addr;
  1099 	pContext->LocalToPhysAddr(params[4], &addr);
  1100 	*addr = pInfo->admin.eflags;
  1101 
  1102 	iter->iter++;
  1103 
  1104 	return 1;
  1105 }
  1106 
  1107 static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params)
  1108 {
  1109 	if (params[1] == 0)
  1110 	{
  1111 		return 1;
  1112 	}
  1113 
  1114 	char *cmd;
  1115 	pContext->LocalToString(params[2], &cmd);
  1116 
  1117 	/* Auto-detect a command if we can */
  1118 	FlagBits bits = params[3];
  1119 	bool found_command = false;
  1120 	if (params[0] < 4 || !params[4])
  1121 	{
  1122 		found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits);
  1123 	}
  1124 	
  1125 	if (!found_command)
  1126 	{
  1127 		g_Admins.GetCommandOverride(cmd, Override_Command, &bits);
  1128 	}
  1129 
  1130 	return g_ConCmds.CheckCommandAccess(params[1], cmd, bits) ? 1 : 0;
  1131 }
  1132 
  1133 static cell_t IsChatTrigger(IPluginContext *pContext, const cell_t *params)
  1134 {
  1135 	return g_ChatTriggers.IsChatTrigger() ? 1 : 0;
  1136 }
  1137 
  1138 static cell_t SetCommandFlags(IPluginContext *pContext, const cell_t *params)
  1139 {
  1140 	char *name;
  1141 	pContext->LocalToString(params[1], &name);
  1142 
  1143 	return (s_CommandFlagsHelper.SetFlags(name, params[2])) ? 1 : 0;
  1144 }
  1145 
  1146 static cell_t GetCommandFlags(IPluginContext *pContext, const cell_t *params)
  1147 {
  1148 	char *name;
  1149 	int flags;
  1150 	pContext->LocalToString(params[1], &name);
  1151 
  1152 	return (s_CommandFlagsHelper.GetFlags(name, &flags)) ? flags : -1;
  1153 }
  1154 
  1155 static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params)
  1156 {
  1157 	Handle_t hndl;
  1158 	ConCmdIter *pIter;
  1159 	cell_t *pIsCmd, *pFlags;
  1160 	const ConCommandBase *pConCmd;
  1161 	const char *desc;
  1162 
  1163 	pContext->LocalToPhysAddr(params[3], &pIsCmd);
  1164 	pContext->LocalToPhysAddr(params[4], &pFlags);
  1165 
  1166 #if SOURCE_ENGINE == SE_LEFT4DEAD
  1167 	ICvarIteratorInternal *cvarIter = icvar->FactoryInternalIterator();
  1168 	cvarIter->SetFirst();
  1169 	if (!cvarIter->IsValid())
  1170 	{
  1171 		return BAD_HANDLE;
  1172 	}
  1173 	pConCmd = cvarIter->Get();
  1174 #else
  1175 	pConCmd = icvar->GetCommands();
  1176 	if (pConCmd == NULL)
  1177 	{
  1178 		return BAD_HANDLE;
  1179 	}
  1180 #endif
  1181 
  1182 	pContext->StringToLocalUTF8(params[1], params[2], pConCmd->GetName(), NULL);
  1183 	*pIsCmd = pConCmd->IsCommand() ? 1 : 0;
  1184 	*pFlags = pConCmd->GetFlags();
  1185 
  1186 	if (params[6])
  1187 	{
  1188 		desc = pConCmd->GetHelpText();
  1189 		pContext->StringToLocalUTF8(params[5], params[6], (desc && desc[0]) ? desc : "", NULL);
  1190 	}
  1191 
  1192 	pIter = new ConCmdIter;
  1193 #if SOURCE_ENGINE == SE_LEFT4DEAD
  1194 	pIter->pLast = cvarIter;
  1195 #else
  1196 	pIter->pLast = pConCmd;
  1197 #endif
  1198 
  1199 	if ((hndl = g_HandleSys.CreateHandle(htConCmdIter, pIter, pContext->GetIdentity(), g_pCoreIdent, NULL))
  1200 		== BAD_HANDLE)
  1201 	{
  1202 		delete pIter;
  1203 		return BAD_HANDLE;
  1204 	}
  1205 
  1206 	return hndl;
  1207 }
  1208 
  1209 static cell_t FindNextConCommand(IPluginContext *pContext, const cell_t *params)
  1210 {
  1211 	HandleError err;
  1212 	ConCmdIter *pIter;
  1213 	cell_t *pIsCmd, *pFlags;
  1214 	const char *desc;
  1215 	const ConCommandBase *pConCmd;
  1216 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
  1217 
  1218 	if ((err = g_HandleSys.ReadHandle(params[1], htConCmdIter, &sec, (void **)&pIter)) != HandleError_None)
  1219 	{
  1220 		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
  1221 	}
  1222 
  1223 	if (pIter->pLast == NULL)
  1224 	{
  1225 		return 0;
  1226 	}
  1227 
  1228 #if SOURCE_ENGINE == SE_LEFT4DEAD
  1229 	ICvarIteratorInternal *cvarIter = pIter->pLast;
  1230 	cvarIter->Next();
  1231 	if (!cvarIter->IsValid())
  1232 	{
  1233 		return 0;
  1234 	}
  1235 	pConCmd = cvarIter->Get();
  1236 #else
  1237 	pConCmd = pIter->pLast->GetNext();
  1238 	if (pConCmd == NULL)
  1239 	{
  1240 		return 0;
  1241 	}
  1242 	pIter->pLast = pConCmd;
  1243 #endif
  1244 
  1245 	pContext->LocalToPhysAddr(params[4], &pIsCmd);
  1246 	pContext->LocalToPhysAddr(params[5], &pFlags);
  1247 
  1248 	pContext->StringToLocalUTF8(params[2], params[3], pConCmd->GetName(), NULL);
  1249 	*pIsCmd = pConCmd->IsCommand() ? 1 : 0;
  1250 	*pFlags = pConCmd->GetFlags();
  1251 
  1252 	if (params[7])
  1253 	{
  1254 		desc = pConCmd->GetHelpText();
  1255 		pContext->StringToLocalUTF8(params[6], params[7], (desc && desc[0]) ? desc : "", NULL);
  1256 	}
  1257 
  1258 	return 1;
  1259 }
  1260 
  1261 static cell_t SendConVarValue(IPluginContext *pContext, const cell_t *params)
  1262 {
  1263 	Handle_t hndl = static_cast<Handle_t>(params[2]);
  1264 	HandleError err;
  1265 	ConVar *pConVar;
  1266 
  1267 	char *value;
  1268 	pContext->LocalToString(params[3], &value);
  1269 
  1270 	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
  1271 		!= HandleError_None)
  1272 	{
  1273 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
  1274 	}
  1275 
  1276 	char data[256];
  1277 	bf_write buffer(data, sizeof(data));
  1278 
  1279 	buffer.WriteUBitLong(NET_SETCONVAR, 5);
  1280 	buffer.WriteByte(1);
  1281 	buffer.WriteString(pConVar->GetName());
  1282 	buffer.WriteString(value);
  1283 
  1284 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
  1285 
  1286 	if (!pPlayer)
  1287 	{
  1288 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
  1289 	}
  1290 
  1291 	if (!pPlayer->IsConnected())
  1292 	{
  1293 		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
  1294 	}
  1295 
  1296 	if (pPlayer->IsFakeClient())
  1297 	{
  1298 		return pContext->ThrowNativeError("Client %d is fake and cannot be targeted", params[1]);
  1299 	}
  1300 
  1301 	INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(params[1]));
  1302 	netchan->SendData(buffer);
  1303 
  1304 	return 1;
  1305 }
  1306 
  1307 static cell_t AddServerTag(IPluginContext *pContext, const cell_t *params)
  1308 {
  1309 	return 0;
  1310 }
  1311 
  1312 static cell_t RemoveServerTag(IPluginContext *pContext, const cell_t *params)
  1313 {
  1314 	return 0;
  1315 }
  1316 
  1317 REGISTER_NATIVES(consoleNatives)
  1318 {
  1319 	{"CreateConVar",		sm_CreateConVar},
  1320 	{"FindConVar",			sm_FindConVar},
  1321 	{"HookConVarChange",	sm_HookConVarChange},
  1322 	{"UnhookConVarChange",	sm_UnhookConVarChange},
  1323 	{"GetConVarBool",		sm_GetConVarBool},
  1324 	{"SetConVarBool",		sm_SetConVarNum},
  1325 	{"GetConVarInt",		sm_GetConVarInt},
  1326 	{"SetConVarInt",		sm_SetConVarNum},
  1327 	{"GetConVarFloat",		sm_GetConVarFloat},
  1328 	{"SetConVarFloat",		sm_SetConVarFloat},
  1329 	{"GetConVarString",		sm_GetConVarString},
  1330 	{"SetConVarString",		sm_SetConVarString},
  1331 	{"GetConVarFlags",		sm_GetConVarFlags},
  1332 	{"SetConVarFlags",		sm_SetConVarFlags},
  1333 	{"ResetConVar",			sm_ResetConVar},
  1334 	{"GetConVarName",		sm_GetConVarName},
  1335 	{"GetConVarBounds",		sm_GetConVarBounds},
  1336 	{"SetConVarBounds",		sm_SetConVarBounds},
  1337 	{"QueryClientConVar",	sm_QueryClientConVar},
  1338 	{"RegServerCmd",		sm_RegServerCmd},
  1339 	{"RegConsoleCmd",		sm_RegConsoleCmd},
  1340 	{"GetCmdArgString",		sm_GetCmdArgString},
  1341 	{"GetCmdArgs",			sm_GetCmdArgs},
  1342 	{"GetCmdArg",			sm_GetCmdArg},
  1343 	{"PrintToServer",		sm_PrintToServer},
  1344 	{"PrintToConsole",		sm_PrintToConsole},
  1345 	{"RegAdminCmd",			sm_RegAdminCmd},
  1346 	{"ServerCommand",		sm_ServerCommand},
  1347 	{"InsertServerCommand",	sm_InsertServerCommand},
  1348 	{"ServerExecute",		sm_ServerExecute},
  1349 	{"ClientCommand",		sm_ClientCommand},
  1350 	{"FakeClientCommand",	FakeClientCommand},
  1351 	{"ReplyToCommand",		ReplyToCommand},
  1352 	{"GetCmdReplySource",	GetCmdReplyTarget},
  1353 	{"SetCmdReplySource",	SetCmdReplyTarget},
  1354 	{"GetCommandIterator",	GetCommandIterator},
  1355 	{"ReadCommandIterator",	ReadCommandIterator},
  1356 	{"CheckCommandAccess",	CheckCommandAccess},
  1357 	{"FakeClientCommandEx",	FakeClientCommandEx},
  1358 	{"IsChatTrigger",		IsChatTrigger},
  1359 	{"SetCommandFlags",		SetCommandFlags},
  1360 	{"GetCommandFlags",		GetCommandFlags},
  1361 	{"FindFirstConCommand",	FindFirstConCommand},
  1362 	{"FindNextConCommand",	FindNextConCommand},
  1363 	{"SendConVarValue",		SendConVarValue},
  1364 	{"AddServerTag",		AddServerTag},
  1365 	{"RemoveServerTag",		RemoveServerTag},
  1366 	{NULL,					NULL}
  1367 };