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