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