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