core/smn_console.cpp
author David Anderson <dvander@alliedmods.net>
Mon Mar 19 01:44:09 2007 +0000 (2007-03-19)
changeset 647 1e29dcc9ca97
parent 633 ed7944127bb9
child 653 ef60870067ff
permissions -rw-r--r--
fixed a potential bug with kicking players during authorization
     1 /**
     2  * ===============================================================
     3  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     4  * ===============================================================
     5  *
     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
    10  *
    11  * Version: $Id$
    12  */
    13 
    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"
    22 
    23 static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params)
    24 {
    25 	char *name, *defaultVal, *helpText;
    26 
    27 	pContext->LocalToString(params[1], &name);
    28 
    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)
    31 	{
    32 		return pContext->ThrowNativeError("Convar with blank name is not permitted");
    33 	}
    34 
    35 	pContext->LocalToString(params[2], &defaultVal);
    36 	pContext->LocalToString(params[3], &helpText);
    37 
    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]);
    42 
    43 	Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
    44 
    45 	if (hndl == BAD_HANDLE)
    46 	{
    47 		return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name);
    48 	}
    49 
    50 	return hndl;
    51 }
    52 
    53 static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params)
    54 {
    55 	char *name;
    56 
    57 	pContext->LocalToString(params[1], &name);
    58 
    59 	return g_ConVarManager.FindConVar(name);
    60 }
    61 
    62 static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params)
    63 {
    64 	Handle_t hndl = static_cast<Handle_t>(params[1]);
    65 	HandleError err;
    66 	ConVar *pConVar;
    67 
    68 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
    69 		!= HandleError_None)
    70 	{
    71 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
    72 	}
    73 
    74 	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
    75 
    76 	if (!pFunction)
    77 	{
    78 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
    79 	}
    80 
    81 	g_ConVarManager.HookConVarChange(pConVar, pFunction);
    82 
    83 	return 1;
    84 }
    85 
    86 static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *params)
    87 {
    88 	Handle_t hndl = static_cast<Handle_t>(params[1]);
    89 	HandleError err;
    90 	ConVar *pConVar;
    91 
    92 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
    93 		!= HandleError_None)
    94 	{
    95 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
    96 	}
    97 
    98 	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
    99 
   100 	if (!pFunction)
   101 	{
   102 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   103 	}
   104 
   105 	g_ConVarManager.UnhookConVarChange(pConVar, pFunction);
   106 
   107 	return 1;
   108 }
   109 
   110 static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params)
   111 {
   112 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   113 	HandleError err;
   114 	ConVar *pConVar;
   115 
   116 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   117 		!= HandleError_None)
   118 	{
   119 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   120 	}
   121 
   122 	return pConVar->GetBool();
   123 }
   124 
   125 static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params)
   126 {
   127 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   128 	HandleError err;
   129 	ConVar *pConVar;
   130 
   131 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   132 		!= HandleError_None)
   133 	{
   134 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   135 	}
   136 
   137 	return pConVar->GetInt();
   138 }
   139 
   140 /* This handles both SetConVarBool() and SetConVarInt() */
   141 static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params)
   142 {
   143 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   144 	HandleError err;
   145 	ConVar *pConVar;
   146 
   147 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   148 		!= HandleError_None)
   149 	{
   150 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   151 	}
   152 
   153 	pConVar->SetValue(params[2]);
   154 
   155 	return 1;
   156 }
   157 
   158 static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params)
   159 {
   160 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   161 	HandleError err;
   162 	ConVar *pConVar;
   163 
   164 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   165 		!= HandleError_None)
   166 	{
   167 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   168 	}
   169 	
   170 	float value = pConVar->GetFloat();
   171 
   172 	return sp_ftoc(value);
   173 }
   174 
   175 static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params)
   176 {
   177 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   178 	HandleError err;
   179 	ConVar *pConVar;
   180 
   181 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   182 		!= HandleError_None)
   183 	{
   184 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   185 	}
   186 
   187 	float value = sp_ctof(params[2]);
   188 	pConVar->SetValue(value);
   189 
   190 	return 1;
   191 }
   192 
   193 static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params)
   194 {
   195 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   196 	HandleError err;
   197 	ConVar *pConVar;
   198 
   199 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   200 		!= HandleError_None)
   201 	{
   202 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   203 	}
   204 
   205 	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL);
   206 
   207 	return 1;
   208 }
   209 
   210 static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
   211 {
   212 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   213 	HandleError err;
   214 	ConVar *pConVar;
   215 
   216 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   217 		!= HandleError_None)
   218 	{
   219 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   220 	}
   221 
   222 	char *value;
   223 	pContext->LocalToString(params[2], &value);
   224 
   225 	pConVar->SetValue(value);
   226 
   227 	return 1;
   228 }
   229 
   230 static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
   231 {
   232 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   233 	HandleError err;
   234 	ConVar *pConVar;
   235 
   236 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   237 		!= HandleError_None)
   238 	{
   239 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   240 	}
   241 
   242 	return pConVar->GetFlags();
   243 }
   244 
   245 static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
   246 {
   247 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   248 	HandleError err;
   249 	ConVar *pConVar;
   250 
   251 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   252 		!= HandleError_None)
   253 	{
   254 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   255 	}
   256 
   257 	pConVar->SetFlags(params[2]);
   258 
   259 	return 1;
   260 }
   261 
   262 static cell_t sm_GetConVarMin(IPluginContext *pContext, const cell_t *params)
   263 {
   264 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   265 	HandleError err;
   266 	ConVar *pConVar;
   267 
   268 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   269 		!= HandleError_None)
   270 	{
   271 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   272 	}
   273 
   274 	cell_t *addr;
   275 	bool hasMin;
   276 	float min;
   277 
   278 	pContext->LocalToPhysAddr(params[2], &addr);
   279 
   280 	hasMin = pConVar->GetMin(min);
   281 	*addr = sp_ftoc(min);
   282 
   283 	return hasMin;
   284 }
   285 
   286 static cell_t sm_GetConVarMax(IPluginContext *pContext, const cell_t *params)
   287 {
   288 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   289 	HandleError err;
   290 	ConVar *pConVar;
   291 
   292 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   293 		!= HandleError_None)
   294 	{
   295 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   296 	}
   297 
   298 	cell_t *addr;
   299 	bool hasMax;
   300 	float max;
   301 
   302 	pContext->LocalToPhysAddr(params[2], &addr);
   303 
   304 	hasMax = pConVar->GetMax(max);
   305 	*addr = sp_ftoc(max);
   306 
   307 	return hasMax;
   308 }
   309 
   310 static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params)
   311 {
   312 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   313 	HandleError err;
   314 	ConVar *pConVar;
   315 
   316 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   317 		!= HandleError_None)
   318 	{
   319 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   320 	}
   321 
   322 	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL);
   323 
   324 	return 1;
   325 }
   326 
   327 static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params)
   328 {
   329 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   330 	HandleError err;
   331 	ConVar *pConVar;
   332 
   333 	if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
   334 		!= HandleError_None)
   335 	{
   336 		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
   337 	}
   338 
   339 	pConVar->Revert();
   340 
   341 	return 1;
   342 }
   343 
   344 static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
   345 {
   346 	char *name,*help;
   347 	IPluginFunction *pFunction;
   348 
   349 	pContext->LocalToString(params[1], &name);
   350 	pContext->LocalToString(params[3], &help);
   351 	pFunction = pContext->GetFunctionById(params[2]);
   352 
   353 	if (!pFunction)
   354 	{
   355 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   356 	}
   357 
   358 	if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4]))
   359 	{
   360 		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
   361 	}
   362 
   363 	return 1;
   364 }
   365 
   366 static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
   367 {
   368 	char *name,*help;
   369 	IPluginFunction *pFunction;
   370 
   371 	pContext->LocalToString(params[1], &name);
   372 	pContext->LocalToString(params[3], &help);
   373 	pFunction = pContext->GetFunctionById(params[2]);
   374 
   375 	if (!pFunction)
   376 	{
   377 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   378 	}
   379 
   380 	if (!g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4]))
   381 	{
   382 		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
   383 	}
   384 
   385 	return 1;
   386 }
   387 
   388 static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
   389 {
   390 	char *name,*help;
   391 	const char *group;
   392 	IPluginFunction *pFunction;
   393 	FlagBits flags = params[3];
   394 	int cmdflags = params[6];
   395 
   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]);
   400 
   401 	if (group[0] == '\0')
   402 	{
   403 		CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   404 		group = pPlugin->GetFilename();
   405 	}
   406 
   407 	if (!pFunction)
   408 	{
   409 		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
   410 	}
   411 
   412 	if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags))
   413 	{
   414 		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
   415 	}
   416 
   417 	return 1;
   418 }
   419 
   420 static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
   421 {
   422 	return engine->Cmd_Argc() - 1;
   423 }
   424 
   425 static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
   426 {
   427 	const char *arg = engine->Cmd_Argv(params[1]);
   428 	
   429 	pContext->StringToLocalUTF8(params[2], params[3], arg, NULL);
   430 
   431 	return 1;
   432 }
   433 
   434 static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params)
   435 {
   436 	const char *args = engine->Cmd_Args();
   437 
   438 	if (!args)
   439 	{
   440 		args = "";
   441 	}
   442 
   443 	pContext->StringToLocalUTF8(params[1], params[2], args, NULL);
   444 
   445 	return 1;
   446 }
   447 
   448 static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params)
   449 {
   450 	char buffer[1024];
   451 	char *fmt;
   452 	int arg = 2;
   453 
   454 	pCtx->LocalToString(params[1], &fmt);
   455 	size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
   456 
   457 	buffer[res++] = '\n';
   458 	buffer[res] = '\0';
   459 
   460 	META_CONPRINT(buffer);
   461 
   462 	return 1;
   463 }
   464 
   465 static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
   466 {
   467 	int index = params[1];
   468 	if ((index < 0) || (index > g_Players.GetMaxClients()))
   469 	{
   470 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   471 	}
   472 
   473 	CPlayer *pPlayer = NULL;
   474 	if (index != 0)
   475 	{
   476 		pPlayer = g_Players.GetPlayerByIndex(index);
   477 		if (!pPlayer->IsInGame())
   478 		{
   479 			return pCtx->ThrowNativeError("Client %d is not in game", index);
   480 		}
   481 		
   482 		/* Silent fail on bots, engine will crash */
   483 		if (pPlayer->IsFakeClient())
   484 		{
   485 			return 0;
   486 		}
   487 	}
   488 
   489 	char buffer[1024];
   490 	char *fmt;
   491 	int arg = 3;
   492 
   493 	pCtx->LocalToString(params[2], &fmt);
   494 	size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
   495 
   496 	buffer[res++] = '\n';
   497 	buffer[res] = '\0';
   498 
   499 	if (index != 0)
   500 	{
   501 		engine->ClientPrintf(pPlayer->GetEdict(), buffer);
   502 	} else {
   503 		META_CONPRINT(buffer);
   504 	}
   505 
   506 	return 1;
   507 }
   508 
   509 static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
   510 {
   511 	char buffer[1024];
   512 	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
   513 
   514 	/* One byte for null terminator, one for newline */
   515 	buffer[len++] = '\n';
   516 	buffer[len] = '\0';
   517 
   518 	engine->ServerCommand(buffer);
   519 
   520 	return 1;
   521 }
   522 
   523 static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
   524 {
   525 	char buffer[1024];
   526 	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
   527 
   528 	/* One byte for null terminator, one for newline */
   529 	buffer[len++] = '\n';
   530 	buffer[len] = '\0';
   531 
   532 	engine->InsertServerCommand(buffer);
   533 
   534 	return 1;
   535 }
   536 
   537 static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params)
   538 {
   539 	engine->ServerExecute();
   540 
   541 	return 1;
   542 }
   543 
   544 static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
   545 {
   546 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   547 
   548 	if (!pPlayer)
   549 	{
   550 		return pContext->ThrowNativeError("Player %d is not a valid player", params[1]);
   551 	}
   552 
   553 	if (!pPlayer->IsConnected())
   554 	{
   555 		return pContext->ThrowNativeError("Player %d is not connected", params[1]);
   556 	}
   557 
   558 	char buffer[256];
   559 	g_SourceMod.FormatString(buffer, sizeof(buffer)-1, pContext, params, 2);
   560 
   561 	engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
   562 
   563 	return 1;
   564 }
   565 
   566 REGISTER_NATIVES(consoleNatives)
   567 {
   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},
   598 	{NULL,					NULL}
   599 };