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();
438 pContext->StringToLocalUTF8(params[1], params[2], args, NULL);
443 static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params)
449 pCtx->LocalToString(params[1], &fmt);
450 size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
452 buffer[res++] = '\n';
455 META_CONPRINT(buffer);
460 static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
462 int index = params[1];
463 if ((index < 0) || (index > g_Players.GetMaxClients()))
465 return pCtx->ThrowNativeError("Invalid client index %d", index);
468 CPlayer *pPlayer = NULL;
471 pPlayer = g_Players.GetPlayerByIndex(index);
472 if (!pPlayer->IsInGame())
474 return pCtx->ThrowNativeError("Client %d is not in game", index);
477 /* Silent fail on bots, engine will crash */
478 if (pPlayer->IsFakeClient())
488 pCtx->LocalToString(params[2], &fmt);
489 size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
491 buffer[res++] = '\n';
496 engine->ClientPrintf(pPlayer->GetEdict(), buffer);
498 META_CONPRINT(buffer);
504 static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
507 size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
509 /* One byte for null terminator, one for newline */
510 buffer[len++] = '\n';
513 engine->ServerCommand(buffer);
518 static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
521 size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
523 /* One byte for null terminator, one for newline */
524 buffer[len++] = '\n';
527 engine->InsertServerCommand(buffer);
532 static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params)
534 engine->ServerExecute();
539 static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
541 CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
545 return pContext->ThrowNativeError("Player %d is not a valid player", params[1]);
548 if (!pPlayer->IsConnected())
550 return pContext->ThrowNativeError("Player %d is not connected", params[1]);
554 g_SourceMod.FormatString(buffer, sizeof(buffer)-1, pContext, params, 2);
556 engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
561 REGISTER_NATIVES(consoleNatives)
563 {"CreateConVar", sm_CreateConVar},
564 {"FindConVar", sm_FindConVar},
565 {"HookConVarChange", sm_HookConVarChange},
566 {"UnhookConVarChange", sm_UnhookConVarChange},
567 {"GetConVarBool", sm_GetConVarBool},
568 {"SetConVarBool", sm_SetConVarNum},
569 {"GetConVarInt", sm_GetConVarInt},
570 {"SetConVarInt", sm_SetConVarNum},
571 {"GetConVarFloat", sm_GetConVarFloat},
572 {"SetConVarFloat", sm_SetConVarFloat},
573 {"GetConVarString", sm_GetConVarString},
574 {"SetConVarString", sm_SetConVarString},
575 {"GetConVarFlags", sm_GetConVarFlags},
576 {"SetConVarFlags", sm_SetConVarFlags},
577 {"GetConVarName", sm_GetConVarName},
578 {"GetConVarMin", sm_GetConVarMin},
579 {"GetConVarMax", sm_GetConVarMax},
580 {"ResetConVar", sm_ResetConVar},
581 {"RegServerCmd", sm_RegServerCmd},
582 {"RegConsoleCmd", sm_RegConsoleCmd},
583 {"GetCmdArgString", sm_GetCmdArgString},
584 {"GetCmdArgs", sm_GetCmdArgs},
585 {"GetCmdArg", sm_GetCmdArg},
586 {"PrintToServer", sm_PrintToServer},
587 {"PrintToConsole", sm_PrintToConsole},
588 {"RegAdminCmd", sm_RegAdminCmd},
589 {"ServerCommand", sm_ServerCommand},
590 {"InsertServerCommand", sm_InsertServerCommand},
591 {"ServerExecute", sm_ServerExecute},
592 {"ClientCommand", sm_ClientCommand},