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