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