core/smn_console.cpp
author David Anderson <dvander@alliedmods.net>
Thu Jul 19 03:22:10 2007 +0000 (2007-07-19)
changeset 1134 68e8b8d386ff
parent 1119 9e3486386c04
child 1231 17badaf66ce4
permissions -rw-r--r--
fixed another translator cache issue
dvander@498
     1
/**
ds@653
     2
 * vim: set ts=4 :
dvander@562
     3
 * ===============================================================
dvander@562
     4
 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
dvander@562
     5
 * ===============================================================
dvander@562
     6
 *
dvander@562
     7
 * This file is not open source and may not be copied without explicit
dvander@562
     8
 * written permission of AlliedModders LLC.  This file may not be redistributed 
dvander@562
     9
 * in whole or significant part.
dvander@562
    10
 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
dvander@562
    11
 *
dvander@562
    12
 * Version: $Id$
dvander@562
    13
 */
dvander@498
    14
dvander@498
    15
#include "sm_globals.h"
ds@696
    16
#include "HalfLife2.h"
dvander@498
    17
#include "sourcemm_api.h"
dvander@498
    18
#include "HandleSys.h"
ds@580
    19
#include "ConVarManager.h"
ds@579
    20
#include "ConCmdManager.h"
dvander@514
    21
#include "PluginSys.h"
dvander@518
    22
#include "sm_stringutil.h"
dvander@591
    23
#include "PlayerManager.h"
dvander@893
    24
#include "ChatTriggers.h"
ds@936
    25
#include <inetchannel.h>
ds@936
    26
#include <bitbuf.h>
ds@936
    27
ds@936
    28
#define NET_SETCONVAR	5
dvander@498
    29
ds@714
    30
enum ConVarBounds
ds@714
    31
{
ds@714
    32
	ConVarBound_Upper = 0,
ds@714
    33
	ConVarBound_Lower
ds@714
    34
};
ds@714
    35
dvander@1119
    36
HandleType_t hCmdIterType = 0;
dvander@1119
    37
dvander@1119
    38
struct GlobCmdIter
dvander@1119
    39
{
dvander@1119
    40
	bool started;
dvander@1119
    41
	List<ConCmdInfo *>::iterator iter;
dvander@1119
    42
};
dvander@1119
    43
dvander@1119
    44
class ConsoleHelpers : 
dvander@1119
    45
	public SMGlobalClass,
dvander@1119
    46
	public IHandleTypeDispatch
dvander@1119
    47
{
dvander@1119
    48
public:
dvander@1119
    49
	virtual void OnSourceModAllInitialized()
dvander@1119
    50
	{
dvander@1119
    51
		HandleAccess access;
dvander@1119
    52
		g_HandleSys.InitAccessDefaults(NULL, &access);
dvander@1119
    53
		access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER | HANDLE_RESTRICT_IDENTITY;
dvander@1119
    54
dvander@1119
    55
		hCmdIterType = g_HandleSys.CreateType(NULL, this, 0, NULL, &access, g_pCoreIdent, NULL);
dvander@1119
    56
	}
dvander@1119
    57
	virtual void OnHandleDestroy(HandleType_t type, void *object)
dvander@1119
    58
	{
dvander@1119
    59
		GlobCmdIter *iter = (GlobCmdIter *)object;
dvander@1119
    60
		delete iter;
dvander@1119
    61
	}
dvander@1119
    62
} s_ConsoleHelpers;
dvander@1119
    63
ds@936
    64
static void ReplicateConVar(ConVar *pConVar)
ds@936
    65
{
ds@936
    66
	int maxClients = g_Players.GetMaxClients();
ds@936
    67
ds@936
    68
	char data[256];
ds@936
    69
	bf_write buffer(data, sizeof(data));
ds@936
    70
ds@936
    71
	buffer.WriteUBitLong(NET_SETCONVAR, 5);
ds@936
    72
	buffer.WriteByte(1);
ds@936
    73
	buffer.WriteString(pConVar->GetName());
ds@936
    74
	buffer.WriteString(pConVar->GetString());
ds@936
    75
ds@936
    76
	for (int i = 1; i <= maxClients; i++)
ds@936
    77
	{
ds@936
    78
		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
ds@936
    79
ds@936
    80
		if (pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient())
ds@936
    81
		{
ds@936
    82
			INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(i));
ds@936
    83
			netchan->SendData(buffer);
ds@936
    84
		}
ds@936
    85
	}
ds@936
    86
}
ds@936
    87
ds@936
    88
static void NotifyConVar(ConVar *pConVar)
ds@936
    89
{
ds@936
    90
	IGameEvent *pEvent = gameevents->CreateEvent("server_cvar");
ds@936
    91
	pEvent->SetString("cvarname", pConVar->GetName());
ds@936
    92
	if (pConVar->IsBitSet(FCVAR_PROTECTED))
ds@936
    93
	{
ds@936
    94
		pEvent->SetString("cvarvalue", "***PROTECTED***");
ds@936
    95
	} else {
ds@936
    96
		pEvent->SetString("cvarvalue", pConVar->GetString());
ds@936
    97
	}
ds@936
    98
ds@936
    99
	gameevents->FireEvent(pEvent);
ds@936
   100
}
ds@936
   101
dvander@498
   102
static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params)
dvander@498
   103
{
dvander@498
   104
	char *name, *defaultVal, *helpText;
dvander@498
   105
dvander@498
   106
	pContext->LocalToString(params[1], &name);
dvander@498
   107
dvander@498
   108
	// While the engine seems to accept a blank convar name, it causes a crash upon server quit
dvander@498
   109
	if (name == NULL || strcmp(name, "") == 0)
dvander@498
   110
	{
ds@582
   111
		return pContext->ThrowNativeError("Convar with blank name is not permitted");
dvander@498
   112
	}
dvander@498
   113
dvander@498
   114
	pContext->LocalToString(params[2], &defaultVal);
dvander@498
   115
	pContext->LocalToString(params[3], &helpText);
dvander@498
   116
dvander@498
   117
	bool hasMin = params[5] ? true : false;
dvander@498
   118
	bool hasMax = params[7] ? true : false;
dvander@498
   119
	float min = sp_ctof(params[6]);
dvander@498
   120
	float max = sp_ctof(params[8]);
dvander@498
   121
ds@582
   122
	Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
ds@582
   123
ds@582
   124
	if (hndl == BAD_HANDLE)
ds@582
   125
	{
ds@582
   126
		return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name);
ds@582
   127
	}
ds@582
   128
ds@582
   129
	return hndl;
dvander@498
   130
}
dvander@498
   131
dvander@498
   132
static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params)
dvander@498
   133
{
dvander@498
   134
	char *name;
dvander@498
   135
dvander@498
   136
	pContext->LocalToString(params[1], &name);
dvander@498
   137
dvander@498
   138
	return g_ConVarManager.FindConVar(name);
dvander@498
   139
}
dvander@498
   140
dvander@498
   141
static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params)
dvander@498
   142
{
dvander@498
   143
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   144
	HandleError err;
ds@576
   145
	ConVar *pConVar;
dvander@498
   146
ds@576
   147
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   148
		!= HandleError_None)
dvander@498
   149
	{
ds@581
   150
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   151
	}
dvander@498
   152
ds@582
   153
	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
ds@582
   154
ds@582
   155
	if (!pFunction)
ds@582
   156
	{
ds@582
   157
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
ds@582
   158
	}
ds@582
   159
ds@582
   160
	g_ConVarManager.HookConVarChange(pConVar, pFunction);
dvander@498
   161
dvander@498
   162
	return 1;
dvander@498
   163
}
dvander@498
   164
dvander@498
   165
static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *params)
dvander@498
   166
{
dvander@498
   167
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   168
	HandleError err;
ds@576
   169
	ConVar *pConVar;
dvander@498
   170
ds@576
   171
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   172
		!= HandleError_None)
dvander@498
   173
	{
ds@581
   174
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   175
	}
dvander@498
   176
ds@582
   177
	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
ds@582
   178
ds@582
   179
	if (!pFunction)
ds@582
   180
	{
ds@582
   181
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
ds@582
   182
	}
ds@582
   183
ds@582
   184
	g_ConVarManager.UnhookConVarChange(pConVar, pFunction);
dvander@498
   185
dvander@498
   186
	return 1;
dvander@498
   187
}
dvander@498
   188
dvander@498
   189
static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params)
dvander@498
   190
{
dvander@498
   191
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   192
	HandleError err;
ds@576
   193
	ConVar *pConVar;
dvander@498
   194
ds@576
   195
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   196
		!= HandleError_None)
dvander@498
   197
	{
ds@581
   198
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   199
	}
dvander@498
   200
ds@576
   201
	return pConVar->GetBool();
dvander@498
   202
}
dvander@498
   203
dvander@498
   204
static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params)
dvander@498
   205
{
dvander@498
   206
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   207
	HandleError err;
ds@576
   208
	ConVar *pConVar;
dvander@498
   209
ds@576
   210
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   211
		!= HandleError_None)
dvander@498
   212
	{
ds@581
   213
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   214
	}
dvander@498
   215
ds@576
   216
	return pConVar->GetInt();
dvander@498
   217
}
dvander@498
   218
dvander@498
   219
/* This handles both SetConVarBool() and SetConVarInt() */
dvander@498
   220
static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params)
dvander@498
   221
{
dvander@498
   222
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   223
	HandleError err;
ds@576
   224
	ConVar *pConVar;
dvander@498
   225
ds@576
   226
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   227
		!= HandleError_None)
dvander@498
   228
	{
ds@581
   229
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   230
	}
dvander@498
   231
ds@576
   232
	pConVar->SetValue(params[2]);
dvander@498
   233
ds@936
   234
	/* Should we replicate it? */
ds@936
   235
	if (params[3] && pConVar->IsBitSet(FCVAR_REPLICATED))
ds@936
   236
	{
ds@936
   237
		ReplicateConVar(pConVar);
ds@936
   238
	}
ds@936
   239
ds@936
   240
	/* Should we notify clients? */
ds@936
   241
	if (params[4] && pConVar->IsBitSet(FCVAR_NOTIFY))
ds@936
   242
	{
ds@936
   243
		NotifyConVar(pConVar);
ds@936
   244
	}
ds@936
   245
dvander@498
   246
	return 1;
dvander@498
   247
}
dvander@498
   248
dvander@498
   249
static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params)
dvander@498
   250
{
dvander@498
   251
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   252
	HandleError err;
ds@576
   253
	ConVar *pConVar;
dvander@498
   254
ds@576
   255
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   256
		!= HandleError_None)
dvander@498
   257
	{
ds@581
   258
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   259
	}
dvander@498
   260
	
ds@576
   261
	float value = pConVar->GetFloat();
dvander@498
   262
dvander@498
   263
	return sp_ftoc(value);
dvander@498
   264
}
dvander@498
   265
dvander@498
   266
static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params)
dvander@498
   267
{
dvander@498
   268
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   269
	HandleError err;
ds@576
   270
	ConVar *pConVar;
dvander@498
   271
ds@576
   272
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   273
		!= HandleError_None)
dvander@498
   274
	{
ds@581
   275
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   276
	}
dvander@498
   277
dvander@498
   278
	float value = sp_ctof(params[2]);
ds@576
   279
	pConVar->SetValue(value);
dvander@498
   280
ds@936
   281
	/* Should we replicate it? */
ds@936
   282
	if (params[3] && pConVar->IsBitSet(FCVAR_REPLICATED))
ds@936
   283
	{
ds@936
   284
		ReplicateConVar(pConVar);
ds@936
   285
	}
ds@936
   286
ds@936
   287
	/* Should we notify clients? */
ds@936
   288
	if (params[4] && pConVar->IsBitSet(FCVAR_NOTIFY))
ds@936
   289
	{
ds@936
   290
		NotifyConVar(pConVar);
ds@936
   291
	}
ds@936
   292
dvander@498
   293
	return 1;
dvander@498
   294
}
dvander@498
   295
dvander@498
   296
static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params)
dvander@498
   297
{
dvander@498
   298
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   299
	HandleError err;
ds@576
   300
	ConVar *pConVar;
dvander@498
   301
ds@576
   302
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   303
		!= HandleError_None)
dvander@498
   304
	{
ds@581
   305
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   306
	}
dvander@498
   307
ds@576
   308
	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL);
dvander@498
   309
dvander@498
   310
	return 1;
dvander@498
   311
}
dvander@498
   312
dvander@498
   313
static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
dvander@498
   314
{
dvander@498
   315
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   316
	HandleError err;
ds@576
   317
	ConVar *pConVar;
dvander@498
   318
ds@576
   319
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   320
		!= HandleError_None)
dvander@498
   321
	{
ds@581
   322
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   323
	}
dvander@498
   324
dvander@498
   325
	char *value;
dvander@498
   326
	pContext->LocalToString(params[2], &value);
dvander@498
   327
ds@576
   328
	pConVar->SetValue(value);
dvander@498
   329
ds@936
   330
	/* Should we replicate it? */
ds@936
   331
	if (params[3] && pConVar->IsBitSet(FCVAR_REPLICATED))
ds@936
   332
	{
ds@936
   333
		ReplicateConVar(pConVar);
ds@936
   334
	}
ds@936
   335
ds@936
   336
	/* Should we notify clients? */
ds@936
   337
	if (params[4] && pConVar->IsBitSet(FCVAR_NOTIFY))
ds@936
   338
	{
ds@936
   339
		NotifyConVar(pConVar);
ds@936
   340
	}
ds@936
   341
dvander@498
   342
	return 1;
dvander@498
   343
}
dvander@498
   344
dvander@498
   345
static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
dvander@498
   346
{
dvander@498
   347
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   348
	HandleError err;
ds@576
   349
	ConVar *pConVar;
dvander@498
   350
ds@576
   351
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   352
		!= HandleError_None)
dvander@498
   353
	{
ds@581
   354
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   355
	}
dvander@498
   356
ds@576
   357
	return pConVar->GetFlags();
dvander@498
   358
}
dvander@498
   359
dvander@498
   360
static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
dvander@498
   361
{
dvander@498
   362
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   363
	HandleError err;
ds@576
   364
	ConVar *pConVar;
dvander@498
   365
ds@576
   366
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   367
		!= HandleError_None)
dvander@498
   368
	{
ds@581
   369
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   370
	}
dvander@498
   371
ds@576
   372
	pConVar->SetFlags(params[2]);
dvander@498
   373
dvander@498
   374
	return 1;
dvander@498
   375
}
dvander@498
   376
ds@714
   377
static cell_t sm_GetConVarBounds(IPluginContext *pContext, const cell_t *params)
dvander@498
   378
{
dvander@498
   379
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   380
	HandleError err;
ds@576
   381
	ConVar *pConVar;
dvander@498
   382
ds@576
   383
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   384
		!= HandleError_None)
dvander@498
   385
	{
ds@581
   386
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   387
	}
dvander@498
   388
dvander@498
   389
	cell_t *addr;
ds@714
   390
	bool hasBound;
ds@714
   391
	float bound;
dvander@498
   392
ds@714
   393
	switch (params[2])
ds@714
   394
	{
ds@714
   395
	case ConVarBound_Upper:
ds@714
   396
		hasBound = pConVar->GetMax(bound);
ds@714
   397
		break;
ds@714
   398
	case ConVarBound_Lower:
ds@714
   399
		hasBound = pConVar->GetMin(bound);
ds@714
   400
		break;
ds@714
   401
	default:
ds@714
   402
		return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
ds@714
   403
	}
ds@714
   404
	
ds@714
   405
	pContext->LocalToPhysAddr(params[3], &addr);
ds@714
   406
	*addr = sp_ftoc(bound);
dvander@498
   407
ds@714
   408
	return hasBound;
dvander@498
   409
}
dvander@498
   410
ds@714
   411
static cell_t sm_SetConVarBounds(IPluginContext *pContext, const cell_t *params)
dvander@498
   412
{
dvander@498
   413
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   414
	HandleError err;
ds@576
   415
	ConVar *pConVar;
dvander@498
   416
ds@576
   417
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   418
		!= HandleError_None)
dvander@498
   419
	{
ds@581
   420
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   421
	}
dvander@498
   422
ds@714
   423
	switch (params[2])
ds@714
   424
	{
ds@714
   425
	case ConVarBound_Upper:
ds@714
   426
		pConVar->SetMax(params[3] ? true : false, sp_ctof(params[4]));
ds@714
   427
		break;
ds@714
   428
	case ConVarBound_Lower:
ds@714
   429
		pConVar->SetMin(params[3] ? true : false, sp_ctof(params[4]));
ds@714
   430
		break;
ds@714
   431
	default:
ds@714
   432
		return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
ds@714
   433
	}
dvander@498
   434
ds@714
   435
	return 1;
dvander@498
   436
}
dvander@498
   437
dvander@498
   438
static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params)
dvander@498
   439
{
dvander@498
   440
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   441
	HandleError err;
ds@576
   442
	ConVar *pConVar;
dvander@498
   443
ds@576
   444
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   445
		!= HandleError_None)
dvander@498
   446
	{
ds@581
   447
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   448
	}
dvander@498
   449
ds@576
   450
	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL);
dvander@498
   451
dvander@498
   452
	return 1;
dvander@498
   453
}
dvander@498
   454
dvander@498
   455
static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params)
dvander@498
   456
{
dvander@498
   457
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@498
   458
	HandleError err;
ds@576
   459
	ConVar *pConVar;
dvander@498
   460
ds@576
   461
	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
dvander@498
   462
		!= HandleError_None)
dvander@498
   463
	{
ds@581
   464
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
dvander@498
   465
	}
dvander@498
   466
ds@576
   467
	pConVar->Revert();
dvander@498
   468
dvander@498
   469
	return 1;
dvander@498
   470
}
dvander@498
   471
ds@696
   472
static bool s_QueryAlreadyWarned = false;
ds@696
   473
ds@696
   474
static cell_t sm_QueryClientConVar(IPluginContext *pContext, const cell_t *params)
ds@696
   475
{
ds@696
   476
	CPlayer *pPlayer;
ds@696
   477
	char *name;
ds@696
   478
	IPluginFunction *pCallback;
ds@696
   479
ds@696
   480
	if (g_IsOriginalEngine)
ds@696
   481
	{
ds@696
   482
		if (!s_QueryAlreadyWarned)
ds@696
   483
		{
ds@696
   484
			s_QueryAlreadyWarned = true;
ds@696
   485
			return pContext->ThrowNativeError("Game does not support client convar querying (one time warning)");
ds@696
   486
		}
ds@696
   487
ds@696
   488
		return 0;
ds@696
   489
	}
ds@696
   490
ds@696
   491
	pPlayer = g_Players.GetPlayerByIndex(params[1]);
ds@696
   492
ds@696
   493
	if (!pPlayer)
ds@696
   494
	{
ds@994
   495
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
ds@696
   496
	}
ds@696
   497
ds@697
   498
	if (!pPlayer->IsConnected())
ds@696
   499
	{
ds@994
   500
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
ds@697
   501
	}
ds@697
   502
ds@697
   503
	/* Trying a query on a bot results in callback not be fired, so don't bother */
ds@697
   504
	if (pPlayer->IsFakeClient())
ds@697
   505
	{
ds@697
   506
		return 0;
ds@696
   507
	}
ds@696
   508
ds@696
   509
	pContext->LocalToString(params[2], &name);
ds@696
   510
	pCallback = pContext->GetFunctionById(params[3]);
ds@696
   511
ds@696
   512
	if (!pCallback)
ds@696
   513
	{
ds@696
   514
		return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
ds@696
   515
	}
ds@696
   516
ds@696
   517
	return g_ConVarManager.QueryClientConVar(pPlayer->GetEdict(), name, pCallback, params[4]);
ds@696
   518
}
ds@696
   519
dvander@498
   520
static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
dvander@498
   521
{
dvander@498
   522
	char *name,*help;
dvander@498
   523
	IPluginFunction *pFunction;
dvander@498
   524
dvander@498
   525
	pContext->LocalToString(params[1], &name);
dvander@498
   526
	pContext->LocalToString(params[3], &help);
dvander@498
   527
	pFunction = pContext->GetFunctionById(params[2]);
dvander@498
   528
dvander@498
   529
	if (!pFunction)
dvander@498
   530
	{
dvander@498
   531
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
dvander@498
   532
	}
dvander@498
   533
ds@579
   534
	if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4]))
ds@579
   535
	{
ds@579
   536
		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
ds@579
   537
	}
dvander@498
   538
dvander@498
   539
	return 1;
dvander@498
   540
}
dvander@498
   541
dvander@500
   542
static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
dvander@500
   543
{
dvander@500
   544
	char *name,*help;
dvander@500
   545
	IPluginFunction *pFunction;
dvander@500
   546
dvander@500
   547
	pContext->LocalToString(params[1], &name);
dvander@500
   548
	pContext->LocalToString(params[3], &help);
dvander@500
   549
	pFunction = pContext->GetFunctionById(params[2]);
dvander@500
   550
dvander@500
   551
	if (!pFunction)
dvander@500
   552
	{
dvander@500
   553
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
dvander@500
   554
	}
dvander@500
   555
ds@579
   556
	if (!g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4]))
ds@579
   557
	{
ds@579
   558
		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
ds@579
   559
	}
dvander@500
   560
dvander@500
   561
	return 1;
dvander@500
   562
}
dvander@500
   563
dvander@514
   564
static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
dvander@514
   565
{
dvander@514
   566
	char *name,*help;
dvander@514
   567
	const char *group;
dvander@514
   568
	IPluginFunction *pFunction;
dvander@514
   569
	FlagBits flags = params[3];
dvander@514
   570
	int cmdflags = params[6];
dvander@514
   571
dvander@514
   572
	pContext->LocalToString(params[1], &name);
dvander@514
   573
	pContext->LocalToString(params[4], &help);
dvander@514
   574
	pContext->LocalToString(params[5], (char **)&group);
dvander@514
   575
	pFunction = pContext->GetFunctionById(params[2]);
dvander@514
   576
dvander@514
   577
	if (group[0] == '\0')
dvander@514
   578
	{
dvander@514
   579
		CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
dvander@514
   580
		group = pPlugin->GetFilename();
dvander@514
   581
	}
dvander@514
   582
dvander@514
   583
	if (!pFunction)
dvander@514
   584
	{
dvander@514
   585
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
dvander@514
   586
	}
dvander@514
   587
ds@579
   588
	if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags))
ds@579
   589
	{
ds@579
   590
		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
ds@579
   591
	}
dvander@514
   592
dvander@514
   593
	return 1;
dvander@514
   594
}
dvander@514
   595
dvander@517
   596
static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
dvander@517
   597
{
dvander@517
   598
	return engine->Cmd_Argc() - 1;
dvander@517
   599
}
dvander@517
   600
dvander@517
   601
static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
dvander@517
   602
{
dvander@517
   603
	const char *arg = engine->Cmd_Argv(params[1]);
dvander@517
   604
	
dvander@517
   605
	pContext->StringToLocalUTF8(params[2], params[3], arg, NULL);
dvander@517
   606
dvander@517
   607
	return 1;
dvander@517
   608
}
dvander@517
   609
dvander@517
   610
static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params)
dvander@517
   611
{
dvander@517
   612
	const char *args = engine->Cmd_Args();
dvander@517
   613
dvander@633
   614
	if (!args)
dvander@633
   615
	{
dvander@633
   616
		args = "";
dvander@633
   617
	}
dvander@633
   618
dvander@517
   619
	pContext->StringToLocalUTF8(params[1], params[2], args, NULL);
dvander@517
   620
dvander@517
   621
	return 1;
dvander@517
   622
}
dvander@517
   623
dvander@518
   624
static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params)
dvander@518
   625
{
dvander@518
   626
	char buffer[1024];
dvander@518
   627
	char *fmt;
dvander@518
   628
	int arg = 2;
dvander@518
   629
dvander@518
   630
	pCtx->LocalToString(params[1], &fmt);
dvander@518
   631
	size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
dvander@518
   632
dvander@518
   633
	buffer[res++] = '\n';
dvander@518
   634
	buffer[res] = '\0';
dvander@518
   635
dvander@518
   636
	META_CONPRINT(buffer);
dvander@518
   637
dvander@518
   638
	return 1;
dvander@518
   639
}
dvander@518
   640
dvander@518
   641
static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
dvander@518
   642
{
dvander@518
   643
	int index = params[1];
dvander@520
   644
	if ((index < 0) || (index > g_Players.GetMaxClients()))
dvander@518
   645
	{
ds@994
   646
		return pCtx->ThrowNativeError("Client index %d is invalid", index);
dvander@518
   647
	}
dvander@518
   648
dvander@520
   649
	CPlayer *pPlayer = NULL;
dvander@520
   650
	if (index != 0)
dvander@518
   651
	{
dvander@520
   652
		pPlayer = g_Players.GetPlayerByIndex(index);
dvander@520
   653
		if (!pPlayer->IsInGame())
dvander@520
   654
		{
dvander@520
   655
			return pCtx->ThrowNativeError("Client %d is not in game", index);
dvander@520
   656
		}
dvander@520
   657
		
dvander@520
   658
		/* Silent fail on bots, engine will crash */
dvander@520
   659
		if (pPlayer->IsFakeClient())
dvander@520
   660
		{
dvander@520
   661
			return 0;
dvander@520
   662
		}
dvander@519
   663
	}
dvander@518
   664
dvander@518
   665
	char buffer[1024];
dvander@518
   666
	char *fmt;
dvander@518
   667
	int arg = 3;
dvander@518
   668
dvander@518
   669
	pCtx->LocalToString(params[2], &fmt);
dvander@518
   670
	size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
dvander@518
   671
dvander@518
   672
	buffer[res++] = '\n';
dvander@518
   673
	buffer[res] = '\0';
dvander@518
   674
dvander@520
   675
	if (index != 0)
dvander@520
   676
	{
dvander@520
   677
		engine->ClientPrintf(pPlayer->GetEdict(), buffer);
dvander@520
   678
	} else {
dvander@520
   679
		META_CONPRINT(buffer);
dvander@520
   680
	}
dvander@518
   681
dvander@518
   682
	return 1;
dvander@518
   683
}
dvander@518
   684
dvander@522
   685
static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
dvander@522
   686
{
dvander@522
   687
	char buffer[1024];
dvander@522
   688
	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
dvander@522
   689
dvander@1011
   690
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1011
   691
dvander@522
   692
	/* One byte for null terminator, one for newline */
dvander@522
   693
	buffer[len++] = '\n';
dvander@522
   694
	buffer[len] = '\0';
dvander@522
   695
dvander@522
   696
	engine->ServerCommand(buffer);
dvander@522
   697
dvander@522
   698
	return 1;
dvander@522
   699
}
dvander@522
   700
dvander@522
   701
static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
dvander@522
   702
{
dvander@522
   703
	char buffer[1024];
dvander@522
   704
	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
dvander@522
   705
dvander@1011
   706
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1011
   707
dvander@522
   708
	/* One byte for null terminator, one for newline */
dvander@522
   709
	buffer[len++] = '\n';
dvander@522
   710
	buffer[len] = '\0';
dvander@522
   711
dvander@522
   712
	engine->InsertServerCommand(buffer);
dvander@522
   713
dvander@522
   714
	return 1;
dvander@522
   715
}
dvander@522
   716
dvander@522
   717
static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params)
dvander@522
   718
{
dvander@522
   719
	engine->ServerExecute();
dvander@522
   720
dvander@522
   721
	return 1;
dvander@522
   722
}
dvander@522
   723
dvander@532
   724
static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
dvander@532
   725
{
dvander@532
   726
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
dvander@532
   727
dvander@532
   728
	if (!pPlayer)
dvander@532
   729
	{
ds@994
   730
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
dvander@532
   731
	}
dvander@532
   732
dvander@532
   733
	if (!pPlayer->IsConnected())
dvander@532
   734
	{
ds@994
   735
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
dvander@532
   736
	}
dvander@532
   737
dvander@1011
   738
	g_SourceMod.SetGlobalTarget(params[1]);
dvander@1011
   739
dvander@532
   740
	char buffer[256];
ds@873
   741
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@532
   742
dvander@532
   743
	engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
dvander@532
   744
dvander@532
   745
	return 1;
dvander@532
   746
}
dvander@532
   747
dvander@893
   748
dvander@893
   749
static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
dvander@893
   750
{
dvander@893
   751
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
dvander@893
   752
dvander@893
   753
	if (!pPlayer)
dvander@893
   754
	{
ds@994
   755
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
dvander@893
   756
	}
dvander@893
   757
dvander@893
   758
	if (!pPlayer->IsConnected())
dvander@893
   759
	{
ds@994
   760
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
dvander@893
   761
	}
dvander@893
   762
dvander@893
   763
	char buffer[256];
dvander@893
   764
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@893
   765
dvander@893
   766
	unsigned int old = g_ChatTriggers.SetReplyTo(SM_REPLY_CONSOLE);
dvander@893
   767
	serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
dvander@893
   768
	g_ChatTriggers.SetReplyTo(old);
dvander@893
   769
dvander@893
   770
	return 1;
dvander@893
   771
}
dvander@893
   772
dvander@893
   773
static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
dvander@893
   774
{
dvander@1011
   775
	g_SourceMod.SetGlobalTarget(params[1]);
dvander@1011
   776
dvander@893
   777
	/* Build the format string */
dvander@893
   778
	char buffer[1024];
dvander@893
   779
	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
dvander@893
   780
dvander@893
   781
	/* If we're printing to the server, shortcut out */
dvander@893
   782
	if (params[1] == 0)
dvander@893
   783
	{
dvander@893
   784
		/* Print */
dvander@893
   785
		buffer[len++] = '\n';
dvander@893
   786
		buffer[len] = '\0';
dvander@893
   787
		META_CONPRINT(buffer);
dvander@893
   788
		return 1;
dvander@893
   789
	}
dvander@893
   790
dvander@893
   791
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
dvander@893
   792
dvander@893
   793
	if (!pPlayer)
dvander@893
   794
	{
dvander@893
   795
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
dvander@893
   796
	}
dvander@893
   797
dvander@893
   798
	if (!pPlayer->IsConnected())
dvander@893
   799
	{
dvander@893
   800
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
dvander@893
   801
	}
dvander@893
   802
dvander@910
   803
	g_SourceMod.SetGlobalTarget(params[1]);
dvander@910
   804
dvander@893
   805
	unsigned int replyto = g_ChatTriggers.GetReplyTo();
dvander@893
   806
	if (replyto == SM_REPLY_CONSOLE)
dvander@893
   807
	{
dvander@893
   808
		buffer[len++] = '\n';
dvander@893
   809
		buffer[len] = '\0';
dvander@893
   810
		engine->ClientPrintf(pPlayer->GetEdict(), buffer);
dvander@893
   811
	} else if (replyto == SM_REPLY_CHAT) {
dvander@893
   812
		if (len >= 191)
dvander@893
   813
		{
dvander@893
   814
			len = 191;
dvander@893
   815
		}
dvander@893
   816
		buffer[len] = '\0';
dvander@893
   817
		g_HL2.TextMsg(params[1], HUD_PRINTTALK, buffer);
dvander@893
   818
	}
dvander@893
   819
dvander@893
   820
	return 1;
dvander@893
   821
}
dvander@893
   822
dvander@923
   823
static cell_t GetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
dvander@923
   824
{
dvander@923
   825
	return g_ChatTriggers.GetReplyTo();
dvander@923
   826
}
dvander@923
   827
dvander@1071
   828
static cell_t SetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
dvander@1071
   829
{
dvander@1071
   830
	return g_ChatTriggers.SetReplyTo(params[1]);
dvander@1071
   831
}
dvander@1071
   832
dvander@1119
   833
static cell_t GetCommandIterator(IPluginContext *pContext, const cell_t *params)
dvander@1119
   834
{
dvander@1119
   835
	GlobCmdIter *iter = new GlobCmdIter;
dvander@1119
   836
	iter->started = false;
dvander@1119
   837
dvander@1119
   838
	Handle_t hndl = g_HandleSys.CreateHandle(hCmdIterType, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@1119
   839
	if (hndl == BAD_HANDLE)
dvander@1119
   840
	{
dvander@1119
   841
		delete iter;
dvander@1119
   842
	}
dvander@1119
   843
dvander@1119
   844
	return hndl;
dvander@1119
   845
}
dvander@1119
   846
dvander@1119
   847
static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params)
dvander@1119
   848
{
dvander@1119
   849
	GlobCmdIter *iter;
dvander@1119
   850
	HandleError err;
dvander@1119
   851
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1119
   852
dvander@1119
   853
	if ((err = g_HandleSys.ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
dvander@1119
   854
		!= HandleError_None)
dvander@1119
   855
	{
dvander@1119
   856
		return pContext->ThrowNativeError("Invalid GlobCmdIter Handle %x", params[1]);
dvander@1119
   857
	}
dvander@1119
   858
dvander@1119
   859
	const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
dvander@1119
   860
dvander@1119
   861
	if (!iter->started)
dvander@1119
   862
	{
dvander@1119
   863
		iter->iter = cmds.begin();
dvander@1119
   864
		iter->started = true;
dvander@1119
   865
	}
dvander@1119
   866
dvander@1119
   867
	while (iter->iter != cmds.end()
dvander@1119
   868
			&& !(*(iter->iter))->sourceMod)
dvander@1119
   869
	{
dvander@1119
   870
		iter->iter++;
dvander@1119
   871
	}
dvander@1119
   872
dvander@1119
   873
	if (iter->iter == cmds.end())
dvander@1119
   874
	{
dvander@1119
   875
		return 0;
dvander@1119
   876
	}
dvander@1119
   877
dvander@1119
   878
	ConCmdInfo *pInfo = (*(iter->iter));
dvander@1119
   879
dvander@1119
   880
	pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetName(), NULL);
dvander@1119
   881
	pContext->StringToLocalUTF8(params[5], params[6], pInfo->pCmd->GetHelpText(), NULL);
dvander@1119
   882
	
dvander@1119
   883
	cell_t *addr;
dvander@1119
   884
	pContext->LocalToPhysAddr(params[4], &addr);
dvander@1119
   885
	*addr = pInfo->admin.eflags;
dvander@1119
   886
dvander@1119
   887
	iter->iter++;
dvander@1119
   888
dvander@1119
   889
	return 1;
dvander@1119
   890
}
dvander@1119
   891
dvander@1119
   892
static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params)
dvander@1119
   893
{
dvander@1119
   894
	if (params[1] == 0)
dvander@1119
   895
	{
dvander@1119
   896
		return 1;
dvander@1119
   897
	}
dvander@1119
   898
dvander@1119
   899
	char *cmd;
dvander@1119
   900
	pContext->LocalToString(params[2], &cmd);
dvander@1119
   901
dvander@1119
   902
	return g_ConCmds.CheckCommandAccess(params[1], cmd, params[3]) ? 1 : 0;
dvander@1119
   903
}
dvander@1119
   904
dvander@518
   905
REGISTER_NATIVES(consoleNatives)
dvander@498
   906
{
dvander@498
   907
	{"CreateConVar",		sm_CreateConVar},
dvander@498
   908
	{"FindConVar",			sm_FindConVar},
dvander@498
   909
	{"HookConVarChange",	sm_HookConVarChange},
dvander@498
   910
	{"UnhookConVarChange",	sm_UnhookConVarChange},
dvander@498
   911
	{"GetConVarBool",		sm_GetConVarBool},
dvander@498
   912
	{"SetConVarBool",		sm_SetConVarNum},
dvander@498
   913
	{"GetConVarInt",		sm_GetConVarInt},
dvander@498
   914
	{"SetConVarInt",		sm_SetConVarNum},
dvander@498
   915
	{"GetConVarFloat",		sm_GetConVarFloat},
dvander@498
   916
	{"SetConVarFloat",		sm_SetConVarFloat},
dvander@498
   917
	{"GetConVarString",		sm_GetConVarString},
dvander@498
   918
	{"SetConVarString",		sm_SetConVarString},
dvander@498
   919
	{"GetConVarFlags",		sm_GetConVarFlags},
dvander@498
   920
	{"SetConVarFlags",		sm_SetConVarFlags},
dvander@498
   921
	{"GetConVarName",		sm_GetConVarName},
ds@714
   922
	{"GetConVarBounds",		sm_GetConVarBounds},
ds@714
   923
	{"SetConVarBounds",		sm_SetConVarBounds},
dvander@498
   924
	{"ResetConVar",			sm_ResetConVar},
ds@696
   925
	{"QueryClientConVar",	sm_QueryClientConVar},
dvander@498
   926
	{"RegServerCmd",		sm_RegServerCmd},
dvander@500
   927
	{"RegConsoleCmd",		sm_RegConsoleCmd},
dvander@517
   928
	{"GetCmdArgString",		sm_GetCmdArgString},
dvander@517
   929
	{"GetCmdArgs",			sm_GetCmdArgs},
dvander@517
   930
	{"GetCmdArg",			sm_GetCmdArg},
dvander@518
   931
	{"PrintToServer",		sm_PrintToServer},
dvander@518
   932
	{"PrintToConsole",		sm_PrintToConsole},
dvander@520
   933
	{"RegAdminCmd",			sm_RegAdminCmd},
dvander@522
   934
	{"ServerCommand",		sm_ServerCommand},
dvander@522
   935
	{"InsertServerCommand",	sm_InsertServerCommand},
dvander@522
   936
	{"ServerExecute",		sm_ServerExecute},
dvander@532
   937
	{"ClientCommand",		sm_ClientCommand},
dvander@893
   938
	{"FakeClientCommand",	FakeClientCommand},
dvander@893
   939
	{"ReplyToCommand",		ReplyToCommand},
dvander@923
   940
	{"GetCmdReplySource",	GetCmdReplyTarget},
dvander@1077
   941
	{"SetCmdReplySource",	SetCmdReplyTarget},
dvander@1119
   942
	{"GetCommandIterator",	GetCommandIterator},
dvander@1119
   943
	{"ReadCommandIterator",	ReadCommandIterator},
dvander@1119
   944
	{"CheckCommandAccess",	CheckCommandAccess},
dvander@498
   945
	{NULL,					NULL}
dvander@498
   946
};