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