1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_console.cpp Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,1307 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "sm_globals.h"
1.36 +#include "HalfLife2.h"
1.37 +#include "sourcemm_api.h"
1.38 +#include "HandleSys.h"
1.39 +#include "ConVarManager.h"
1.40 +#include "ConCmdManager.h"
1.41 +#include "PluginSys.h"
1.42 +#include "sm_stringutil.h"
1.43 +#include "PlayerManager.h"
1.44 +#include "ChatTriggers.h"
1.45 +#include "AdminCache.h"
1.46 +#include <inetchannel.h>
1.47 +#include <bitbuf.h>
1.48 +#include <sm_trie_tpl.h>
1.49 +
1.50 +#define NET_SETCONVAR 5
1.51 +
1.52 +enum ConVarBounds
1.53 +{
1.54 + ConVarBound_Upper = 0,
1.55 + ConVarBound_Lower
1.56 +};
1.57 +
1.58 +HandleType_t hCmdIterType = 0;
1.59 +HandleType_t htConCmdIter = 0;
1.60 +
1.61 +struct GlobCmdIter
1.62 +{
1.63 + bool started;
1.64 + List<ConCmdInfo *>::iterator iter;
1.65 +};
1.66 +
1.67 +struct ConCmdIter
1.68 +{
1.69 + const ConCommandBase *pLast;
1.70 +};
1.71 +
1.72 +class ConsoleHelpers :
1.73 + public SMGlobalClass,
1.74 + public IHandleTypeDispatch
1.75 +{
1.76 +public:
1.77 + virtual void OnSourceModAllInitialized()
1.78 + {
1.79 + HandleAccess access;
1.80 +
1.81 + g_HandleSys.InitAccessDefaults(NULL, &access);
1.82 +
1.83 + htConCmdIter = g_HandleSys.CreateType("ConCmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
1.84 +
1.85 + access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER | HANDLE_RESTRICT_IDENTITY;
1.86 +
1.87 + hCmdIterType = g_HandleSys.CreateType("CmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
1.88 + }
1.89 + virtual void OnHandleDestroy(HandleType_t type, void *object)
1.90 + {
1.91 + if (type == hCmdIterType)
1.92 + {
1.93 + GlobCmdIter *iter = (GlobCmdIter *)object;
1.94 + delete iter;
1.95 + }
1.96 + else if (type == htConCmdIter)
1.97 + {
1.98 + ConCmdIter *iter = (ConCmdIter * )object;
1.99 + delete iter;
1.100 + }
1.101 + }
1.102 + virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
1.103 + {
1.104 + if (type == htConCmdIter)
1.105 + {
1.106 + *pSize = sizeof(ConCmdIter);
1.107 + return true;
1.108 + }
1.109 + else if (type == hCmdIterType)
1.110 + {
1.111 + *pSize = sizeof(GlobCmdIter);
1.112 + return true;
1.113 + }
1.114 + return false;
1.115 + }
1.116 +} s_ConsoleHelpers;
1.117 +
1.118 +class CommandFlagsHelper : public IConCommandTracker
1.119 +{
1.120 +public:
1.121 + void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
1.122 + {
1.123 + m_CmdFlags.remove(name);
1.124 + }
1.125 + bool GetFlags(const char *name, int *flags)
1.126 + {
1.127 + ConCommandBase **ppCmd;
1.128 + ConCommandBase *pCmd;
1.129 + if ((ppCmd=m_CmdFlags.retrieve(name)))
1.130 + {
1.131 + TrackConCommandBase((*ppCmd), this);
1.132 + *flags = (*ppCmd)->GetFlags();
1.133 + return true;
1.134 + }
1.135 + else if ((pCmd=FindConCommandBase(name)))
1.136 + {
1.137 + m_CmdFlags.insert(name, pCmd);
1.138 + TrackConCommandBase(pCmd, this);
1.139 + *flags = pCmd->GetFlags();
1.140 + return true;
1.141 + }
1.142 + else
1.143 + {
1.144 + return false;
1.145 + }
1.146 + }
1.147 + bool SetFlags(const char *name, int flags)
1.148 + {
1.149 + ConCommandBase **ppCmd;
1.150 + ConCommandBase *pCmd;
1.151 + if ((ppCmd=m_CmdFlags.retrieve(name)))
1.152 + {
1.153 + (*ppCmd)->SetFlags(flags);
1.154 + TrackConCommandBase((*ppCmd), this);
1.155 + return true;
1.156 + }
1.157 + else if ((pCmd=FindConCommandBase(name)))
1.158 + {
1.159 + m_CmdFlags.insert(name, pCmd);
1.160 + pCmd->SetFlags(flags);
1.161 + TrackConCommandBase(pCmd, this);
1.162 + return true;
1.163 + }
1.164 + else
1.165 + {
1.166 + return false;
1.167 + }
1.168 + }
1.169 +private:
1.170 + KTrie<ConCommandBase *> m_CmdFlags;
1.171 +} s_CommandFlagsHelper;
1.172 +
1.173 +static void ReplicateConVar(ConVar *pConVar)
1.174 +{
1.175 + int maxClients = g_Players.GetMaxClients();
1.176 +
1.177 + char data[256];
1.178 + bf_write buffer(data, sizeof(data));
1.179 +
1.180 + buffer.WriteUBitLong(NET_SETCONVAR, 5);
1.181 + buffer.WriteByte(1);
1.182 + buffer.WriteString(pConVar->GetName());
1.183 + buffer.WriteString(pConVar->GetString());
1.184 +
1.185 + for (int i = 1; i <= maxClients; i++)
1.186 + {
1.187 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
1.188 +
1.189 + if (pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient())
1.190 + {
1.191 + INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(i));
1.192 + netchan->SendData(buffer);
1.193 + }
1.194 + }
1.195 +}
1.196 +
1.197 +static void NotifyConVar(ConVar *pConVar)
1.198 +{
1.199 + IGameEvent *pEvent = gameevents->CreateEvent("server_cvar");
1.200 + pEvent->SetString("cvarname", pConVar->GetName());
1.201 + if (IsFlagSet(pConVar, FCVAR_PROTECTED))
1.202 + {
1.203 + pEvent->SetString("cvarvalue", "***PROTECTED***");
1.204 + }
1.205 + else
1.206 + {
1.207 + pEvent->SetString("cvarvalue", pConVar->GetString());
1.208 + }
1.209 +
1.210 + gameevents->FireEvent(pEvent);
1.211 +}
1.212 +
1.213 +static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params)
1.214 +{
1.215 + char *name, *defaultVal, *helpText;
1.216 +
1.217 + pContext->LocalToString(params[1], &name);
1.218 +
1.219 + // While the engine seems to accept a blank convar name, it causes a crash upon server quit
1.220 + if (name == NULL || strcmp(name, "") == 0)
1.221 + {
1.222 + return pContext->ThrowNativeError("Convar with blank name is not permitted");
1.223 + }
1.224 +
1.225 + pContext->LocalToString(params[2], &defaultVal);
1.226 + pContext->LocalToString(params[3], &helpText);
1.227 +
1.228 + bool hasMin = params[5] ? true : false;
1.229 + bool hasMax = params[7] ? true : false;
1.230 + float min = sp_ctof(params[6]);
1.231 + float max = sp_ctof(params[8]);
1.232 +
1.233 + Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
1.234 +
1.235 + if (hndl == BAD_HANDLE)
1.236 + {
1.237 + return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same might already exist.", name);
1.238 + }
1.239 +
1.240 + return hndl;
1.241 +}
1.242 +
1.243 +static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params)
1.244 +{
1.245 + char *name;
1.246 +
1.247 + pContext->LocalToString(params[1], &name);
1.248 +
1.249 + return g_ConVarManager.FindConVar(name);
1.250 +}
1.251 +
1.252 +static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params)
1.253 +{
1.254 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.255 + HandleError err;
1.256 + ConVar *pConVar;
1.257 +
1.258 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.259 + != HandleError_None)
1.260 + {
1.261 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.262 + }
1.263 +
1.264 + IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
1.265 +
1.266 + if (!pFunction)
1.267 + {
1.268 + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
1.269 + }
1.270 +
1.271 + g_ConVarManager.HookConVarChange(pConVar, pFunction);
1.272 +
1.273 + return 1;
1.274 +}
1.275 +
1.276 +static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *params)
1.277 +{
1.278 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.279 + HandleError err;
1.280 + ConVar *pConVar;
1.281 +
1.282 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.283 + != HandleError_None)
1.284 + {
1.285 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.286 + }
1.287 +
1.288 + IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
1.289 +
1.290 + if (!pFunction)
1.291 + {
1.292 + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
1.293 + }
1.294 +
1.295 + g_ConVarManager.UnhookConVarChange(pConVar, pFunction);
1.296 +
1.297 + return 1;
1.298 +}
1.299 +
1.300 +static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params)
1.301 +{
1.302 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.303 + HandleError err;
1.304 + ConVar *pConVar;
1.305 +
1.306 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.307 + != HandleError_None)
1.308 + {
1.309 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.310 + }
1.311 +
1.312 + return pConVar->GetBool();
1.313 +}
1.314 +
1.315 +static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params)
1.316 +{
1.317 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.318 + HandleError err;
1.319 + ConVar *pConVar;
1.320 +
1.321 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.322 + != HandleError_None)
1.323 + {
1.324 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.325 + }
1.326 +
1.327 + return pConVar->GetInt();
1.328 +}
1.329 +
1.330 +/* This handles both SetConVarBool() and SetConVarInt() */
1.331 +static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params)
1.332 +{
1.333 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.334 + HandleError err;
1.335 + ConVar *pConVar;
1.336 +
1.337 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.338 + != HandleError_None)
1.339 + {
1.340 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.341 + }
1.342 +
1.343 + pConVar->SetValue(params[2]);
1.344 +
1.345 + /* Should we replicate it? */
1.346 + if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
1.347 + {
1.348 + ReplicateConVar(pConVar);
1.349 + }
1.350 +
1.351 + /* Should we notify clients? */
1.352 + if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
1.353 + {
1.354 + NotifyConVar(pConVar);
1.355 + }
1.356 +
1.357 + return 1;
1.358 +}
1.359 +
1.360 +static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params)
1.361 +{
1.362 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.363 + HandleError err;
1.364 + ConVar *pConVar;
1.365 +
1.366 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.367 + != HandleError_None)
1.368 + {
1.369 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.370 + }
1.371 +
1.372 + float value = pConVar->GetFloat();
1.373 +
1.374 + return sp_ftoc(value);
1.375 +}
1.376 +
1.377 +static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params)
1.378 +{
1.379 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.380 + HandleError err;
1.381 + ConVar *pConVar;
1.382 +
1.383 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.384 + != HandleError_None)
1.385 + {
1.386 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.387 + }
1.388 +
1.389 + float value = sp_ctof(params[2]);
1.390 + pConVar->SetValue(value);
1.391 +
1.392 + /* Should we replicate it? */
1.393 + if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
1.394 + {
1.395 + ReplicateConVar(pConVar);
1.396 + }
1.397 +
1.398 + /* Should we notify clients? */
1.399 + if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
1.400 + {
1.401 + NotifyConVar(pConVar);
1.402 + }
1.403 +
1.404 + return 1;
1.405 +}
1.406 +
1.407 +static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params)
1.408 +{
1.409 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.410 + HandleError err;
1.411 + ConVar *pConVar;
1.412 +
1.413 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.414 + != HandleError_None)
1.415 + {
1.416 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.417 + }
1.418 +
1.419 + pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL);
1.420 +
1.421 + return 1;
1.422 +}
1.423 +
1.424 +static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
1.425 +{
1.426 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.427 + HandleError err;
1.428 + ConVar *pConVar;
1.429 +
1.430 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.431 + != HandleError_None)
1.432 + {
1.433 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.434 + }
1.435 +
1.436 + char *value;
1.437 + pContext->LocalToString(params[2], &value);
1.438 +
1.439 + pConVar->SetValue(value);
1.440 +
1.441 + /* Should we replicate it? */
1.442 + if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
1.443 + {
1.444 + ReplicateConVar(pConVar);
1.445 + }
1.446 +
1.447 + /* Should we notify clients? */
1.448 + if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
1.449 + {
1.450 + NotifyConVar(pConVar);
1.451 + }
1.452 +
1.453 + return 1;
1.454 +}
1.455 +
1.456 +static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params)
1.457 +{
1.458 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.459 + HandleError err;
1.460 + ConVar *pConVar;
1.461 +
1.462 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.463 + != HandleError_None)
1.464 + {
1.465 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.466 + }
1.467 +
1.468 + pConVar->Revert();
1.469 +
1.470 + /* Should we replicate it? */
1.471 + if (params[2] && IsFlagSet(pConVar, FCVAR_REPLICATED))
1.472 + {
1.473 + ReplicateConVar(pConVar);
1.474 + }
1.475 +
1.476 + /* Should we notify clients? */
1.477 + if (params[3] && IsFlagSet(pConVar, FCVAR_NOTIFY))
1.478 + {
1.479 + NotifyConVar(pConVar);
1.480 + }
1.481 +
1.482 + return 1;
1.483 +}
1.484 +
1.485 +static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
1.486 +{
1.487 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.488 + HandleError err;
1.489 + ConVar *pConVar;
1.490 +
1.491 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.492 + != HandleError_None)
1.493 + {
1.494 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.495 + }
1.496 +
1.497 + return pConVar->GetFlags();
1.498 +}
1.499 +
1.500 +static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
1.501 +{
1.502 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.503 + HandleError err;
1.504 + ConVar *pConVar;
1.505 +
1.506 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.507 + != HandleError_None)
1.508 + {
1.509 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.510 + }
1.511 +
1.512 + pConVar->SetFlags(params[2]);
1.513 +
1.514 + return 1;
1.515 +}
1.516 +
1.517 +static cell_t sm_GetConVarBounds(IPluginContext *pContext, const cell_t *params)
1.518 +{
1.519 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.520 + HandleError err;
1.521 + ConVar *pConVar;
1.522 +
1.523 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.524 + != HandleError_None)
1.525 + {
1.526 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.527 + }
1.528 +
1.529 + cell_t *addr;
1.530 + bool hasBound;
1.531 + float bound;
1.532 +
1.533 + switch (params[2])
1.534 + {
1.535 + case ConVarBound_Upper:
1.536 + hasBound = pConVar->GetMax(bound);
1.537 + break;
1.538 + case ConVarBound_Lower:
1.539 + hasBound = pConVar->GetMin(bound);
1.540 + break;
1.541 + default:
1.542 + return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
1.543 + }
1.544 +
1.545 + pContext->LocalToPhysAddr(params[3], &addr);
1.546 + *addr = sp_ftoc(bound);
1.547 +
1.548 + return hasBound;
1.549 +}
1.550 +
1.551 +static cell_t sm_SetConVarBounds(IPluginContext *pContext, const cell_t *params)
1.552 +{
1.553 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.554 + HandleError err;
1.555 + ConVar *pConVar;
1.556 +
1.557 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.558 + != HandleError_None)
1.559 + {
1.560 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.561 + }
1.562 +
1.563 + switch (params[2])
1.564 + {
1.565 + case ConVarBound_Upper:
1.566 + pConVar->SetMax(params[3] ? true : false, sp_ctof(params[4]));
1.567 + break;
1.568 + case ConVarBound_Lower:
1.569 + pConVar->SetMin(params[3] ? true : false, sp_ctof(params[4]));
1.570 + break;
1.571 + default:
1.572 + return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
1.573 + }
1.574 +
1.575 + return 1;
1.576 +}
1.577 +
1.578 +static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params)
1.579 +{
1.580 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.581 + HandleError err;
1.582 + ConVar *pConVar;
1.583 +
1.584 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.585 + != HandleError_None)
1.586 + {
1.587 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.588 + }
1.589 +
1.590 + pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL);
1.591 +
1.592 + return 1;
1.593 +}
1.594 +
1.595 +static bool s_QueryAlreadyWarned = false;
1.596 +
1.597 +static cell_t sm_QueryClientConVar(IPluginContext *pContext, const cell_t *params)
1.598 +{
1.599 + CPlayer *pPlayer;
1.600 + char *name;
1.601 + IPluginFunction *pCallback;
1.602 +
1.603 + if (!g_ConVarManager.IsQueryingSupported())
1.604 + {
1.605 + if (!s_QueryAlreadyWarned)
1.606 + {
1.607 + s_QueryAlreadyWarned = true;
1.608 + return pContext->ThrowNativeError("Game does not support client convar querying (one time warning)");
1.609 + }
1.610 +
1.611 + return 0;
1.612 + }
1.613 +
1.614 + pPlayer = g_Players.GetPlayerByIndex(params[1]);
1.615 +
1.616 + if (!pPlayer)
1.617 + {
1.618 + return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1.619 + }
1.620 +
1.621 + if (!pPlayer->IsConnected())
1.622 + {
1.623 + return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1.624 + }
1.625 +
1.626 + /* Trying a query on a bot results in callback not be fired, so don't bother */
1.627 + if (pPlayer->IsFakeClient())
1.628 + {
1.629 + return 0;
1.630 + }
1.631 +
1.632 + pContext->LocalToString(params[2], &name);
1.633 + pCallback = pContext->GetFunctionById(params[3]);
1.634 +
1.635 + if (!pCallback)
1.636 + {
1.637 + return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
1.638 + }
1.639 +
1.640 + return g_ConVarManager.QueryClientConVar(pPlayer->GetEdict(), name, pCallback, params[4]);
1.641 +}
1.642 +
1.643 +static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
1.644 +{
1.645 + char *name,*help;
1.646 + IPluginFunction *pFunction;
1.647 +
1.648 + pContext->LocalToString(params[1], &name);
1.649 + pContext->LocalToString(params[3], &help);
1.650 + pFunction = pContext->GetFunctionById(params[2]);
1.651 +
1.652 + if (!pFunction)
1.653 + {
1.654 + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
1.655 + }
1.656 +
1.657 + if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4]))
1.658 + {
1.659 + return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
1.660 + }
1.661 +
1.662 + return 1;
1.663 +}
1.664 +
1.665 +static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
1.666 +{
1.667 + char *name,*help;
1.668 + IPluginFunction *pFunction;
1.669 +
1.670 + pContext->LocalToString(params[1], &name);
1.671 + pContext->LocalToString(params[3], &help);
1.672 + pFunction = pContext->GetFunctionById(params[2]);
1.673 +
1.674 + if (!pFunction)
1.675 + {
1.676 + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
1.677 + }
1.678 +
1.679 + if (!g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4]))
1.680 + {
1.681 + return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
1.682 + }
1.683 +
1.684 + return 1;
1.685 +}
1.686 +
1.687 +static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
1.688 +{
1.689 + char *name,*help;
1.690 + const char *group;
1.691 + IPluginFunction *pFunction;
1.692 + FlagBits flags = params[3];
1.693 + int cmdflags = params[6];
1.694 +
1.695 + pContext->LocalToString(params[1], &name);
1.696 + pContext->LocalToString(params[4], &help);
1.697 + pContext->LocalToString(params[5], (char **)&group);
1.698 + pFunction = pContext->GetFunctionById(params[2]);
1.699 +
1.700 + if (group[0] == '\0')
1.701 + {
1.702 + CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.703 + group = pPlugin->GetFilename();
1.704 + }
1.705 +
1.706 + if (!pFunction)
1.707 + {
1.708 + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
1.709 + }
1.710 +
1.711 + if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags))
1.712 + {
1.713 + return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
1.714 + }
1.715 +
1.716 + return 1;
1.717 +}
1.718 +
1.719 +static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
1.720 +{
1.721 + const CCommand *pCmd = g_HL2.PeekCommandStack();
1.722 +
1.723 + if (!pCmd)
1.724 + {
1.725 + return pContext->ThrowNativeError("No command callback available");
1.726 + }
1.727 +
1.728 + return pCmd->ArgC() - 1;
1.729 +}
1.730 +
1.731 +static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
1.732 +{
1.733 + const CCommand *pCmd = g_HL2.PeekCommandStack();
1.734 +
1.735 + if (!pCmd)
1.736 + {
1.737 + return pContext->ThrowNativeError("No command callback available");
1.738 + }
1.739 +
1.740 + size_t length;
1.741 +
1.742 + const char *arg = pCmd->Arg(params[1]);
1.743 +
1.744 + pContext->StringToLocalUTF8(params[2], params[3], arg ? arg : "", &length);
1.745 +
1.746 + return (cell_t)length;
1.747 +}
1.748 +
1.749 +static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params)
1.750 +{
1.751 + const CCommand *pCmd = g_HL2.PeekCommandStack();
1.752 +
1.753 + if (!pCmd)
1.754 + {
1.755 + return pContext->ThrowNativeError("No command callback available");
1.756 + }
1.757 +
1.758 + const char *args = pCmd->ArgS();
1.759 + size_t length;
1.760 +
1.761 + if (!args)
1.762 + {
1.763 + args = "";
1.764 + }
1.765 +
1.766 + pContext->StringToLocalUTF8(params[1], params[2], args, &length);
1.767 +
1.768 + return (cell_t)length;
1.769 +}
1.770 +
1.771 +static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params)
1.772 +{
1.773 + char buffer[1024];
1.774 + char *fmt;
1.775 + int arg = 2;
1.776 +
1.777 + pCtx->LocalToString(params[1], &fmt);
1.778 + size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
1.779 +
1.780 + buffer[res++] = '\n';
1.781 + buffer[res] = '\0';
1.782 +
1.783 + META_CONPRINT(buffer);
1.784 +
1.785 + return 1;
1.786 +}
1.787 +
1.788 +static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
1.789 +{
1.790 + int index = params[1];
1.791 + if ((index < 0) || (index > g_Players.GetMaxClients()))
1.792 + {
1.793 + return pCtx->ThrowNativeError("Client index %d is invalid", index);
1.794 + }
1.795 +
1.796 + CPlayer *pPlayer = NULL;
1.797 + if (index != 0)
1.798 + {
1.799 + pPlayer = g_Players.GetPlayerByIndex(index);
1.800 + if (!pPlayer->IsInGame())
1.801 + {
1.802 + return pCtx->ThrowNativeError("Client %d is not in game", index);
1.803 + }
1.804 +
1.805 + /* Silent fail on bots, engine will crash */
1.806 + if (pPlayer->IsFakeClient())
1.807 + {
1.808 + return 0;
1.809 + }
1.810 + }
1.811 +
1.812 + char buffer[1024];
1.813 + char *fmt;
1.814 + int arg = 3;
1.815 +
1.816 + pCtx->LocalToString(params[2], &fmt);
1.817 + size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
1.818 +
1.819 + buffer[res++] = '\n';
1.820 + buffer[res] = '\0';
1.821 +
1.822 + if (index != 0)
1.823 + {
1.824 + engine->ClientPrintf(pPlayer->GetEdict(), buffer);
1.825 + } else {
1.826 + META_CONPRINT(buffer);
1.827 + }
1.828 +
1.829 + return 1;
1.830 +}
1.831 +
1.832 +static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
1.833 +{
1.834 + g_SourceMod.SetGlobalTarget(LANG_SERVER);
1.835 +
1.836 + char buffer[1024];
1.837 + size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
1.838 +
1.839 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.840 + {
1.841 + return 0;
1.842 + }
1.843 +
1.844 + /* One byte for null terminator, one for newline */
1.845 + buffer[len++] = '\n';
1.846 + buffer[len] = '\0';
1.847 +
1.848 + engine->ServerCommand(buffer);
1.849 +
1.850 + return 1;
1.851 +}
1.852 +
1.853 +static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
1.854 +{
1.855 + g_SourceMod.SetGlobalTarget(LANG_SERVER);
1.856 +
1.857 + char buffer[1024];
1.858 + size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
1.859 +
1.860 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.861 + {
1.862 + return 0;
1.863 + }
1.864 +
1.865 + /* One byte for null terminator, one for newline */
1.866 + buffer[len++] = '\n';
1.867 + buffer[len] = '\0';
1.868 +
1.869 + InsertServerCommand(buffer);
1.870 +
1.871 + return 1;
1.872 +}
1.873 +
1.874 +static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params)
1.875 +{
1.876 + engine->ServerExecute();
1.877 +
1.878 + return 1;
1.879 +}
1.880 +
1.881 +static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
1.882 +{
1.883 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1.884 +
1.885 + if (!pPlayer)
1.886 + {
1.887 + return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1.888 + }
1.889 +
1.890 + if (!pPlayer->IsConnected())
1.891 + {
1.892 + return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1.893 + }
1.894 +
1.895 + g_SourceMod.SetGlobalTarget(params[1]);
1.896 +
1.897 + char buffer[256];
1.898 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.899 +
1.900 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.901 + {
1.902 + return 0;
1.903 + }
1.904 +
1.905 + engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
1.906 +
1.907 + return 1;
1.908 +}
1.909 +
1.910 +static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
1.911 +{
1.912 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1.913 +
1.914 + if (!pPlayer)
1.915 + {
1.916 + return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1.917 + }
1.918 +
1.919 + if (!pPlayer->IsConnected())
1.920 + {
1.921 + return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1.922 + }
1.923 +
1.924 + char buffer[256];
1.925 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.926 +
1.927 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.928 + {
1.929 + return 0;
1.930 + }
1.931 +
1.932 + serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
1.933 +
1.934 + return 1;
1.935 +}
1.936 +
1.937 +static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params)
1.938 +{
1.939 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1.940 +
1.941 + if (!pPlayer)
1.942 + {
1.943 + return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1.944 + }
1.945 +
1.946 + if (!pPlayer->IsConnected())
1.947 + {
1.948 + return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1.949 + }
1.950 +
1.951 + char buffer[256];
1.952 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.953 +
1.954 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.955 + {
1.956 + return 0;
1.957 + }
1.958 +
1.959 + g_HL2.AddToFakeCliCmdQueue(params[1], engine->GetPlayerUserId(pPlayer->GetEdict()), buffer);
1.960 +
1.961 + return 1;
1.962 +}
1.963 +
1.964 +static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
1.965 +{
1.966 + g_SourceMod.SetGlobalTarget(params[1]);
1.967 +
1.968 + /* Build the format string */
1.969 + char buffer[1024];
1.970 + size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
1.971 +
1.972 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.973 + {
1.974 + return 0;
1.975 + }
1.976 +
1.977 + /* If we're printing to the server, shortcut out */
1.978 + if (params[1] == 0)
1.979 + {
1.980 + /* Print */
1.981 + buffer[len++] = '\n';
1.982 + buffer[len] = '\0';
1.983 + META_CONPRINT(buffer);
1.984 + return 1;
1.985 + }
1.986 +
1.987 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1.988 +
1.989 + if (!pPlayer)
1.990 + {
1.991 + return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1.992 + }
1.993 +
1.994 + if (!pPlayer->IsConnected())
1.995 + {
1.996 + return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1.997 + }
1.998 +
1.999 + g_SourceMod.SetGlobalTarget(params[1]);
1.1000 +
1.1001 + unsigned int replyto = g_ChatTriggers.GetReplyTo();
1.1002 + if (replyto == SM_REPLY_CONSOLE)
1.1003 + {
1.1004 + buffer[len++] = '\n';
1.1005 + buffer[len] = '\0';
1.1006 + engine->ClientPrintf(pPlayer->GetEdict(), buffer);
1.1007 + } else if (replyto == SM_REPLY_CHAT) {
1.1008 + if (len >= 191)
1.1009 + {
1.1010 + len = 191;
1.1011 + }
1.1012 + buffer[len] = '\0';
1.1013 + g_HL2.TextMsg(params[1], HUD_PRINTTALK, buffer);
1.1014 + }
1.1015 +
1.1016 + return 1;
1.1017 +}
1.1018 +
1.1019 +static cell_t GetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
1.1020 +{
1.1021 + return g_ChatTriggers.GetReplyTo();
1.1022 +}
1.1023 +
1.1024 +static cell_t SetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
1.1025 +{
1.1026 + return g_ChatTriggers.SetReplyTo(params[1]);
1.1027 +}
1.1028 +
1.1029 +static cell_t GetCommandIterator(IPluginContext *pContext, const cell_t *params)
1.1030 +{
1.1031 + GlobCmdIter *iter = new GlobCmdIter;
1.1032 + iter->started = false;
1.1033 +
1.1034 + Handle_t hndl = g_HandleSys.CreateHandle(hCmdIterType, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.1035 + if (hndl == BAD_HANDLE)
1.1036 + {
1.1037 + delete iter;
1.1038 + }
1.1039 +
1.1040 + return hndl;
1.1041 +}
1.1042 +
1.1043 +static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params)
1.1044 +{
1.1045 + GlobCmdIter *iter;
1.1046 + HandleError err;
1.1047 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.1048 +
1.1049 + if ((err = g_HandleSys.ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
1.1050 + != HandleError_None)
1.1051 + {
1.1052 + return pContext->ThrowNativeError("Invalid GlobCmdIter Handle %x", params[1]);
1.1053 + }
1.1054 +
1.1055 + const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
1.1056 +
1.1057 + if (!iter->started)
1.1058 + {
1.1059 + iter->iter = cmds.begin();
1.1060 + iter->started = true;
1.1061 + }
1.1062 +
1.1063 + while (iter->iter != cmds.end()
1.1064 + && !(*(iter->iter))->sourceMod)
1.1065 + {
1.1066 + iter->iter++;
1.1067 + }
1.1068 +
1.1069 + if (iter->iter == cmds.end())
1.1070 + {
1.1071 + return 0;
1.1072 + }
1.1073 +
1.1074 + ConCmdInfo *pInfo = (*(iter->iter));
1.1075 +
1.1076 + pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetName(), NULL);
1.1077 + pContext->StringToLocalUTF8(params[5], params[6], pInfo->pCmd->GetHelpText(), NULL);
1.1078 +
1.1079 + cell_t *addr;
1.1080 + pContext->LocalToPhysAddr(params[4], &addr);
1.1081 + *addr = pInfo->admin.eflags;
1.1082 +
1.1083 + iter->iter++;
1.1084 +
1.1085 + return 1;
1.1086 +}
1.1087 +
1.1088 +static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params)
1.1089 +{
1.1090 + if (params[1] == 0)
1.1091 + {
1.1092 + return 1;
1.1093 + }
1.1094 +
1.1095 + char *cmd;
1.1096 + pContext->LocalToString(params[2], &cmd);
1.1097 +
1.1098 + /* Auto-detect a command if we can */
1.1099 + FlagBits bits = params[3];
1.1100 + bool found_command = false;
1.1101 + if (params[0] < 4 || !params[4])
1.1102 + {
1.1103 + found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits);
1.1104 + }
1.1105 +
1.1106 + if (!found_command)
1.1107 + {
1.1108 + g_Admins.GetCommandOverride(cmd, Override_Command, &bits);
1.1109 + }
1.1110 +
1.1111 + return g_ConCmds.CheckCommandAccess(params[1], cmd, bits) ? 1 : 0;
1.1112 +}
1.1113 +
1.1114 +static cell_t IsChatTrigger(IPluginContext *pContext, const cell_t *params)
1.1115 +{
1.1116 + return g_ChatTriggers.IsChatTrigger() ? 1 : 0;
1.1117 +}
1.1118 +
1.1119 +static cell_t SetCommandFlags(IPluginContext *pContext, const cell_t *params)
1.1120 +{
1.1121 + char *name;
1.1122 + pContext->LocalToString(params[1], &name);
1.1123 +
1.1124 + return (s_CommandFlagsHelper.SetFlags(name, params[2])) ? 1 : 0;
1.1125 +}
1.1126 +
1.1127 +static cell_t GetCommandFlags(IPluginContext *pContext, const cell_t *params)
1.1128 +{
1.1129 + char *name;
1.1130 + int flags;
1.1131 + pContext->LocalToString(params[1], &name);
1.1132 +
1.1133 + return (s_CommandFlagsHelper.GetFlags(name, &flags)) ? flags : -1;
1.1134 +}
1.1135 +
1.1136 +static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params)
1.1137 +{
1.1138 + Handle_t hndl;
1.1139 + ConCmdIter *pIter;
1.1140 + cell_t *pIsCmd, *pFlags;
1.1141 + const ConCommandBase *pConCmd;
1.1142 + const char *desc;
1.1143 +
1.1144 + pContext->LocalToPhysAddr(params[3], &pIsCmd);
1.1145 + pContext->LocalToPhysAddr(params[4], &pFlags);
1.1146 +
1.1147 + pConCmd = icvar->GetCommands();
1.1148 +
1.1149 + if (pConCmd == NULL)
1.1150 + {
1.1151 + return BAD_HANDLE;
1.1152 + }
1.1153 +
1.1154 + pContext->StringToLocalUTF8(params[1], params[2], pConCmd->GetName(), NULL);
1.1155 + *pIsCmd = pConCmd->IsCommand() ? 1 : 0;
1.1156 + *pFlags = pConCmd->GetFlags();
1.1157 +
1.1158 + if (params[6])
1.1159 + {
1.1160 + desc = pConCmd->GetHelpText();
1.1161 + pContext->StringToLocalUTF8(params[5], params[6], (desc && desc[0]) ? desc : "", NULL);
1.1162 + }
1.1163 +
1.1164 + pIter = new ConCmdIter;
1.1165 + pIter->pLast = pConCmd;
1.1166 +
1.1167 + if ((hndl = g_HandleSys.CreateHandle(htConCmdIter, pIter, pContext->GetIdentity(), g_pCoreIdent, NULL))
1.1168 + == BAD_HANDLE)
1.1169 + {
1.1170 + delete pIter;
1.1171 + return BAD_HANDLE;
1.1172 + }
1.1173 +
1.1174 + return hndl;
1.1175 +}
1.1176 +
1.1177 +static cell_t FindNextConCommand(IPluginContext *pContext, const cell_t *params)
1.1178 +{
1.1179 + HandleError err;
1.1180 + ConCmdIter *pIter;
1.1181 + cell_t *pIsCmd, *pFlags;
1.1182 + const char *desc;
1.1183 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.1184 +
1.1185 + if ((err = g_HandleSys.ReadHandle(params[1], htConCmdIter, &sec, (void **)&pIter)) != HandleError_None)
1.1186 + {
1.1187 + return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
1.1188 + }
1.1189 +
1.1190 + if (pIter->pLast == NULL)
1.1191 + {
1.1192 + return 0;
1.1193 + }
1.1194 +
1.1195 + if ((pIter->pLast = pIter->pLast->GetNext()) == NULL)
1.1196 + {
1.1197 + return 0;
1.1198 + }
1.1199 +
1.1200 + pContext->LocalToPhysAddr(params[4], &pIsCmd);
1.1201 + pContext->LocalToPhysAddr(params[5], &pFlags);
1.1202 +
1.1203 + pContext->StringToLocalUTF8(params[2], params[3], pIter->pLast->GetName(), NULL);
1.1204 + *pIsCmd = pIter->pLast->IsCommand() ? 1 : 0;
1.1205 + *pFlags = pIter->pLast->GetFlags();
1.1206 +
1.1207 + if (params[7])
1.1208 + {
1.1209 + desc = pIter->pLast->GetHelpText();
1.1210 + pContext->StringToLocalUTF8(params[6], params[7], (desc && desc[0]) ? desc : "", NULL);
1.1211 + }
1.1212 +
1.1213 + return 1;
1.1214 +}
1.1215 +
1.1216 +static cell_t SendConVarValue(IPluginContext *pContext, const cell_t *params)
1.1217 +{
1.1218 + Handle_t hndl = static_cast<Handle_t>(params[2]);
1.1219 + HandleError err;
1.1220 + ConVar *pConVar;
1.1221 +
1.1222 + char *value;
1.1223 + pContext->LocalToString(params[3], &value);
1.1224 +
1.1225 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1.1226 + != HandleError_None)
1.1227 + {
1.1228 + return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1.1229 + }
1.1230 +
1.1231 + char data[256];
1.1232 + bf_write buffer(data, sizeof(data));
1.1233 +
1.1234 + buffer.WriteUBitLong(NET_SETCONVAR, 5);
1.1235 + buffer.WriteByte(1);
1.1236 + buffer.WriteString(pConVar->GetName());
1.1237 + buffer.WriteString(value);
1.1238 +
1.1239 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1.1240 +
1.1241 + if (!pPlayer)
1.1242 + {
1.1243 + return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1.1244 + }
1.1245 +
1.1246 + if (!pPlayer->IsConnected())
1.1247 + {
1.1248 + return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1.1249 + }
1.1250 +
1.1251 + if (pPlayer->IsFakeClient())
1.1252 + {
1.1253 + return pContext->ThrowNativeError("Client %d is fake and cannot be targeted", params[1]);
1.1254 + }
1.1255 +
1.1256 + INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(params[1]));
1.1257 + netchan->SendData(buffer);
1.1258 +
1.1259 + return 1;
1.1260 +}
1.1261 +
1.1262 +REGISTER_NATIVES(consoleNatives)
1.1263 +{
1.1264 + {"CreateConVar", sm_CreateConVar},
1.1265 + {"FindConVar", sm_FindConVar},
1.1266 + {"HookConVarChange", sm_HookConVarChange},
1.1267 + {"UnhookConVarChange", sm_UnhookConVarChange},
1.1268 + {"GetConVarBool", sm_GetConVarBool},
1.1269 + {"SetConVarBool", sm_SetConVarNum},
1.1270 + {"GetConVarInt", sm_GetConVarInt},
1.1271 + {"SetConVarInt", sm_SetConVarNum},
1.1272 + {"GetConVarFloat", sm_GetConVarFloat},
1.1273 + {"SetConVarFloat", sm_SetConVarFloat},
1.1274 + {"GetConVarString", sm_GetConVarString},
1.1275 + {"SetConVarString", sm_SetConVarString},
1.1276 + {"GetConVarFlags", sm_GetConVarFlags},
1.1277 + {"SetConVarFlags", sm_SetConVarFlags},
1.1278 + {"ResetConVar", sm_ResetConVar},
1.1279 + {"GetConVarName", sm_GetConVarName},
1.1280 + {"GetConVarBounds", sm_GetConVarBounds},
1.1281 + {"SetConVarBounds", sm_SetConVarBounds},
1.1282 + {"QueryClientConVar", sm_QueryClientConVar},
1.1283 + {"RegServerCmd", sm_RegServerCmd},
1.1284 + {"RegConsoleCmd", sm_RegConsoleCmd},
1.1285 + {"GetCmdArgString", sm_GetCmdArgString},
1.1286 + {"GetCmdArgs", sm_GetCmdArgs},
1.1287 + {"GetCmdArg", sm_GetCmdArg},
1.1288 + {"PrintToServer", sm_PrintToServer},
1.1289 + {"PrintToConsole", sm_PrintToConsole},
1.1290 + {"RegAdminCmd", sm_RegAdminCmd},
1.1291 + {"ServerCommand", sm_ServerCommand},
1.1292 + {"InsertServerCommand", sm_InsertServerCommand},
1.1293 + {"ServerExecute", sm_ServerExecute},
1.1294 + {"ClientCommand", sm_ClientCommand},
1.1295 + {"FakeClientCommand", FakeClientCommand},
1.1296 + {"ReplyToCommand", ReplyToCommand},
1.1297 + {"GetCmdReplySource", GetCmdReplyTarget},
1.1298 + {"SetCmdReplySource", SetCmdReplyTarget},
1.1299 + {"GetCommandIterator", GetCommandIterator},
1.1300 + {"ReadCommandIterator", ReadCommandIterator},
1.1301 + {"CheckCommandAccess", CheckCommandAccess},
1.1302 + {"FakeClientCommandEx", FakeClientCommandEx},
1.1303 + {"IsChatTrigger", IsChatTrigger},
1.1304 + {"SetCommandFlags", SetCommandFlags},
1.1305 + {"GetCommandFlags", GetCommandFlags},
1.1306 + {"FindFirstConCommand", FindFirstConCommand},
1.1307 + {"FindNextConCommand", FindNextConCommand},
1.1308 + {"SendConVarValue", SendConVarValue},
1.1309 + {NULL, NULL}
1.1310 +};