2 * ===============================================================
3 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
4 * ===============================================================
6 * This file is not open source and may not be copied without explicit
7 * written permission of AlliedModders LLC. This file may not be redistributed
8 * in whole or significant part.
9 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
14 #include "sm_globals.h"
15 #include "sourcemm_api.h"
16 #include "HandleSys.h"
17 #include "ConVarManager.h"
18 #include "ConCmdManager.h"
19 #include "PluginSys.h"
20 #include "sm_stringutil.h"
21 #include "PlayerManager.h"
23 static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params)
25 char *name, *defaultVal, *helpText;
27 pContext->LocalToString(params[1], &name);
29 // While the engine seems to accept a blank convar name, it causes a crash upon server quit
30 if (name == NULL || strcmp(name, "") == 0)
32 return pContext->ThrowNativeError("Convar with blank name is not permitted");
35 pContext->LocalToString(params[2], &defaultVal);
36 pContext->LocalToString(params[3], &helpText);
38 bool hasMin = params[5] ? true : false;
39 bool hasMax = params[7] ? true : false;
40 float min = sp_ctof(params[6]);
41 float max = sp_ctof(params[8]);
43 Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
45 if (hndl == BAD_HANDLE)
47 return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name);
53 static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params)
57 pContext->LocalToString(params[1], &name);
59 return g_ConVarManager.FindConVar(name);
62 static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params)
64 Handle_t hndl = static_cast<Handle_t>(params[1]);
68 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
71 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
74 IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
78 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
81 g_ConVarManager.HookConVarChange(pConVar, pFunction);
86 static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *params)
88 Handle_t hndl = static_cast<Handle_t>(params[1]);
92 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
95 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
98 IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
102 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
105 g_ConVarManager.UnhookConVarChange(pConVar, pFunction);
110 static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params)
112 Handle_t hndl = static_cast<Handle_t>(params[1]);
116 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
119 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
122 return pConVar->GetBool();
125 static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params)
127 Handle_t hndl = static_cast<Handle_t>(params[1]);
131 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
134 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
137 return pConVar->GetInt();
140 /* This handles both SetConVarBool() and SetConVarInt() */
141 static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params)
143 Handle_t hndl = static_cast<Handle_t>(params[1]);
147 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
150 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
153 pConVar->SetValue(params[2]);
158 static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params)
160 Handle_t hndl = static_cast<Handle_t>(params[1]);
164 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
167 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
170 float value = pConVar->GetFloat();
172 return sp_ftoc(value);
175 static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params)
177 Handle_t hndl = static_cast<Handle_t>(params[1]);
181 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
184 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
187 float value = sp_ctof(params[2]);
188 pConVar->SetValue(value);
193 static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params)
195 Handle_t hndl = static_cast<Handle_t>(params[1]);
199 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
202 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
205 pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL);
210 static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
212 Handle_t hndl = static_cast<Handle_t>(params[1]);
216 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
219 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
223 pContext->LocalToString(params[2], &value);
225 pConVar->SetValue(value);
230 static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
232 Handle_t hndl = static_cast<Handle_t>(params[1]);
236 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
239 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
242 return pConVar->GetFlags();
245 static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
247 Handle_t hndl = static_cast<Handle_t>(params[1]);
251 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
254 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
257 pConVar->SetFlags(params[2]);
262 static cell_t sm_GetConVarMin(IPluginContext *pContext, const cell_t *params)
264 Handle_t hndl = static_cast<Handle_t>(params[1]);
268 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
271 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
278 pContext->LocalToPhysAddr(params[2], &addr);
280 hasMin = pConVar->GetMin(min);
281 *addr = sp_ftoc(min);
286 static cell_t sm_GetConVarMax(IPluginContext *pContext, const cell_t *params)
288 Handle_t hndl = static_cast<Handle_t>(params[1]);
292 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
295 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
302 pContext->LocalToPhysAddr(params[2], &addr);
304 hasMax = pConVar->GetMax(max);
305 *addr = sp_ftoc(max);
310 static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params)
312 Handle_t hndl = static_cast<Handle_t>(params[1]);
316 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
319 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
322 pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL);
327 static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params)
329 Handle_t hndl = static_cast<Handle_t>(params[1]);
333 if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
336 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
344 static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
347 IPluginFunction *pFunction;
349 pContext->LocalToString(params[1], &name);
350 pContext->LocalToString(params[3], &help);
351 pFunction = pContext->GetFunctionById(params[2]);
355 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
358 if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4]))
360 return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
366 static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
369 IPluginFunction *pFunction;
371 pContext->LocalToString(params[1], &name);
372 pContext->LocalToString(params[3], &help);
373 pFunction = pContext->GetFunctionById(params[2]);
377 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
380 if (!g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4]))
382 return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
388 static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
392 IPluginFunction *pFunction;
393 FlagBits flags = params[3];
394 int cmdflags = params[6];
396 pContext->LocalToString(params[1], &name);
397 pContext->LocalToString(params[4], &help);
398 pContext->LocalToString(params[5], (char **)&group);
399 pFunction = pContext->GetFunctionById(params[2]);
401 if (group[0] == '\0')
403 CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
404 group = pPlugin->GetFilename();
409 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
412 if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags))
414 return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
420 static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
422 return engine->Cmd_Argc() - 1;
425 static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
427 const char *arg = engine->Cmd_Argv(params[1]);
429 pContext->StringToLocalUTF8(params[2], params[3], arg, NULL);
434 static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params)
436 const char *args = engine->Cmd_Args();
443 pContext->StringToLocalUTF8(params[1], params[2], args, NULL);
448 static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params)
454 pCtx->LocalToString(params[1], &fmt);
455 size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
457 buffer[res++] = '\n';
460 META_CONPRINT(buffer);
465 static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
467 int index = params[1];
468 if ((index < 0) || (index > g_Players.GetMaxClients()))
470 return pCtx->ThrowNativeError("Invalid client index %d", index);
473 CPlayer *pPlayer = NULL;
476 pPlayer = g_Players.GetPlayerByIndex(index);
477 if (!pPlayer->IsInGame())
479 return pCtx->ThrowNativeError("Client %d is not in game", index);
482 /* Silent fail on bots, engine will crash */
483 if (pPlayer->IsFakeClient())
493 pCtx->LocalToString(params[2], &fmt);
494 size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
496 buffer[res++] = '\n';
501 engine->ClientPrintf(pPlayer->GetEdict(), buffer);
503 META_CONPRINT(buffer);
509 static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
512 size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
514 /* One byte for null terminator, one for newline */
515 buffer[len++] = '\n';
518 engine->ServerCommand(buffer);
523 static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
526 size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
528 /* One byte for null terminator, one for newline */
529 buffer[len++] = '\n';
532 engine->InsertServerCommand(buffer);
537 static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params)
539 engine->ServerExecute();
544 static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
546 CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
550 return pContext->ThrowNativeError("Player %d is not a valid player", params[1]);
553 if (!pPlayer->IsConnected())
555 return pContext->ThrowNativeError("Player %d is not connected", params[1]);
559 g_SourceMod.FormatString(buffer, sizeof(buffer)-1, pContext, params, 2);
561 engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
566 REGISTER_NATIVES(consoleNatives)
568 {"CreateConVar", sm_CreateConVar},
569 {"FindConVar", sm_FindConVar},
570 {"HookConVarChange", sm_HookConVarChange},
571 {"UnhookConVarChange", sm_UnhookConVarChange},
572 {"GetConVarBool", sm_GetConVarBool},
573 {"SetConVarBool", sm_SetConVarNum},
574 {"GetConVarInt", sm_GetConVarInt},
575 {"SetConVarInt", sm_SetConVarNum},
576 {"GetConVarFloat", sm_GetConVarFloat},
577 {"SetConVarFloat", sm_SetConVarFloat},
578 {"GetConVarString", sm_GetConVarString},
579 {"SetConVarString", sm_SetConVarString},
580 {"GetConVarFlags", sm_GetConVarFlags},
581 {"SetConVarFlags", sm_SetConVarFlags},
582 {"GetConVarName", sm_GetConVarName},
583 {"GetConVarMin", sm_GetConVarMin},
584 {"GetConVarMax", sm_GetConVarMax},
585 {"ResetConVar", sm_ResetConVar},
586 {"RegServerCmd", sm_RegServerCmd},
587 {"RegConsoleCmd", sm_RegConsoleCmd},
588 {"GetCmdArgString", sm_GetCmdArgString},
589 {"GetCmdArgs", sm_GetCmdArgs},
590 {"GetCmdArg", sm_GetCmdArg},
591 {"PrintToServer", sm_PrintToServer},
592 {"PrintToConsole", sm_PrintToConsole},
593 {"RegAdminCmd", sm_RegAdminCmd},
594 {"ServerCommand", sm_ServerCommand},
595 {"InsertServerCommand", sm_InsertServerCommand},
596 {"ServerExecute", sm_ServerExecute},
597 {"ClientCommand", sm_ClientCommand},