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