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