plugins/basecommands.sp
author David Anderson <dvander@alliedmods.net>
Fri Jul 11 05:14:32 2008 +0000 (2008-07-11)
branchrefac-jit
changeset 2190 880e81f30b5e
parent 2168 c24a6fa957db
permissions -rw-r--r--
GetContext() now returns 'this' as a hack (shouldn't+can't be accessed anyway)
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod Basic Commands Plugin
     5  * Implements basic admin commands.
     6  *
     7  * SourceMod (C)2004-2008 AlliedModders LLC.  All rights reserved.
     8  * =============================================================================
     9  *
    10  * This program is free software; you can redistribute it and/or modify it under
    11  * the terms of the GNU General Public License, version 3.0, as published by the
    12  * Free Software Foundation.
    13  * 
    14  * This program is distributed in the hope that it will be useful, but WITHOUT
    15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    17  * details.
    18  *
    19  * You should have received a copy of the GNU General Public License along with
    20  * this program.  If not, see <http://www.gnu.org/licenses/>.
    21  *
    22  * As a special exception, AlliedModders LLC gives you permission to link the
    23  * code of this program (as well as its derivative 1works) to "Half-Life 2," the
    24  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    25  * by the Valve Corporation.  You must obey the GNU General Public License in
    26  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    27  * this exception to all derivative works.  AlliedModders LLC defines further
    28  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    29  * or <http://www.sourcemod.net/license.php>.
    30  *
    31  * Version: $Id$
    32  */
    33 
    34 #pragma semicolon 1
    35 
    36 #include <sourcemod>
    37 #undef REQUIRE_PLUGIN
    38 #include <adminmenu>
    39 
    40 public Plugin:myinfo =
    41 {
    42 	name = "Basic Commands",
    43 	author = "AlliedModders LLC",
    44 	description = "Basic Admin Commands",
    45 	version = SOURCEMOD_VERSION,
    46 	url = "http://www.sourcemod.net/"
    47 };
    48 
    49 new Handle:hTopMenu = INVALID_HANDLE;
    50 
    51 new Handle:g_MapList;
    52 new Handle:g_ProtectedVars;
    53 
    54 #include "basecommands/kick.sp"
    55 #include "basecommands/reloadadmins.sp"
    56 #include "basecommands/cancelvote.sp"
    57 #include "basecommands/who.sp"
    58 #include "basecommands/map.sp"
    59 #include "basecommands/execcfg.sp"
    60 
    61 public OnPluginStart()
    62 {
    63 	LoadTranslations("common.phrases");
    64 	LoadTranslations("plugin.basecommands");
    65 
    66 	RegAdminCmd("sm_kick", Command_Kick, ADMFLAG_KICK, "sm_kick <#userid|name> [reason]");
    67 	RegAdminCmd("sm_map", Command_Map, ADMFLAG_CHANGEMAP, "sm_map <map>");
    68 	RegAdminCmd("sm_rcon", Command_Rcon, ADMFLAG_RCON, "sm_rcon <args>");
    69 	RegAdminCmd("sm_cvar", Command_Cvar, ADMFLAG_CONVARS, "sm_cvar <cvar> [value]");
    70 	RegAdminCmd("sm_execcfg", Command_ExecCfg, ADMFLAG_CONFIG, "sm_execcfg <filename>");
    71 	RegAdminCmd("sm_who", Command_Who, ADMFLAG_GENERIC, "sm_who [#userid|name]");
    72 	RegAdminCmd("sm_reloadadmins", Command_ReloadAdmins, ADMFLAG_BAN, "sm_reloadadmins");
    73 	RegAdminCmd("sm_cancelvote", Command_CancelVote, ADMFLAG_VOTE, "sm_cancelvote");
    74 	RegConsoleCmd("sm_revote", Command_ReVote);
    75 	
    76 	/* Account for late loading */
    77 	new Handle:topmenu;
    78 	if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE))
    79 	{
    80 		OnAdminMenuReady(topmenu);
    81 	}
    82 	
    83 	g_MapList = CreateMenu(MenuHandler_ChangeMap);
    84 	SetMenuTitle(g_MapList, "Please select a map");
    85 	SetMenuExitBackButton(g_MapList, true);
    86 	
    87 	decl String:mapListPath[PLATFORM_MAX_PATH];
    88 	BuildPath(Path_SM, mapListPath, sizeof(mapListPath), "configs/adminmenu_maplist.ini");
    89 	SetMapListCompatBind("sm_map menu", mapListPath);
    90 	
    91 	g_ProtectedVars = CreateTrie();
    92 	ProtectVar("rcon_password");
    93 	ProtectVar("sm_show_activity");
    94 	ProtectVar("sm_immunity_mode");
    95 }
    96 
    97 public OnMapStart()
    98 {
    99 	ParseConfigs();
   100 }
   101 
   102 public OnConfigsExecuted()
   103 {
   104 	LoadMapList(g_MapList);
   105 }
   106 
   107 ProtectVar(const String:cvar[])
   108 {
   109 	SetTrieValue(g_ProtectedVars, cvar, 1);
   110 }
   111 
   112 bool:IsVarProtected(const String:cvar[])
   113 {
   114 	decl dummy_value;
   115 	return GetTrieValue(g_ProtectedVars, cvar, dummy_value);
   116 }
   117 
   118 public OnAdminMenuReady(Handle:topmenu)
   119 {
   120 	/* Block us from being called twice */
   121 	if (topmenu == hTopMenu)
   122 	{
   123 		return;
   124 	}
   125 	
   126 	/* Save the Handle */
   127 	hTopMenu = topmenu;
   128 	
   129 	/* Build the "Player Commands" category */
   130 	new TopMenuObject:player_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_PLAYERCOMMANDS);
   131 	
   132 	if (player_commands != INVALID_TOPMENUOBJECT)
   133 	{
   134 		AddToTopMenu(hTopMenu, 
   135 			"sm_kick",
   136 			TopMenuObject_Item,
   137 			AdminMenu_Kick,
   138 			player_commands,
   139 			"sm_kick",
   140 			ADMFLAG_KICK);
   141 			
   142 		AddToTopMenu(hTopMenu,
   143 			"sm_who",
   144 			TopMenuObject_Item,
   145 			AdminMenu_Who,
   146 			player_commands,
   147 			"sm_who",
   148 			ADMFLAG_GENERIC);
   149 	}
   150 
   151 	new TopMenuObject:server_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_SERVERCOMMANDS);
   152 
   153 	if (server_commands != INVALID_TOPMENUOBJECT)
   154 	{
   155 		AddToTopMenu(hTopMenu,
   156 			"sm_reloadadmins",
   157 			TopMenuObject_Item,
   158 			AdminMenu_ReloadAdmins,
   159 			server_commands,
   160 			"sm_reloadadmins",
   161 			ADMFLAG_BAN);
   162 			
   163 		AddToTopMenu(hTopMenu,
   164 			"sm_map",
   165 			TopMenuObject_Item,
   166 			AdminMenu_Map,
   167 			server_commands,
   168 			"sm_map",
   169 			ADMFLAG_CHANGEMAP);
   170 			
   171 		AddToTopMenu(hTopMenu,
   172 			"sm_execcfg",
   173 			TopMenuObject_Item,
   174 			AdminMenu_ExecCFG,
   175 			server_commands,
   176 			"sm_execcfg",
   177 			ADMFLAG_CONFIG);		
   178 	}
   179 
   180 	new TopMenuObject:voting_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_VOTINGCOMMANDS);
   181 
   182 	if (voting_commands != INVALID_TOPMENUOBJECT)
   183 	{
   184 		AddToTopMenu(hTopMenu,
   185 			"sm_cancelvote",
   186 			TopMenuObject_Item,
   187 			AdminMenu_CancelVote,
   188 			voting_commands,
   189 			"sm_cancelvote",
   190 			ADMFLAG_VOTE);
   191 	}
   192 }
   193 
   194 public OnLibraryRemoved(const String:name[])
   195 {
   196 	if (strcmp(name, "adminmenu") == 0)
   197 	{
   198 		hTopMenu = INVALID_HANDLE;
   199 	}
   200 }
   201 
   202 #define FLAG_STRINGS		14
   203 new String:g_FlagNames[FLAG_STRINGS][20] =
   204 {
   205 	"res",
   206 	"admin",
   207 	"kick",
   208 	"ban",
   209 	"unban",
   210 	"slay",
   211 	"map",
   212 	"cvars",
   213 	"cfg",
   214 	"chat",
   215 	"vote",
   216 	"pass",
   217 	"rcon",
   218 	"cheat"
   219 };
   220 
   221 CustomFlagsToString(String:buffer[], maxlength, flags)
   222 {
   223 	decl String:joins[6][6];
   224 	new total;
   225 	
   226 	for (new i=_:Admin_Custom1; i<=_:Admin_Custom6; i++)
   227 	{
   228 		if (flags & (1<<i))
   229 		{
   230 			IntToString(i - _:Admin_Custom1 + 1, joins[total++], 6);
   231 		}
   232 	}
   233 	
   234 	ImplodeStrings(joins, total, ",", buffer, maxlength);
   235 	
   236 	return total;
   237 }
   238 
   239 FlagsToString(String:buffer[], maxlength, flags)
   240 {
   241 	decl String:joins[FLAG_STRINGS+1][32];
   242 	new total;
   243 
   244 	for (new i=0; i<FLAG_STRINGS; i++)
   245 	{
   246 		if (flags & (1<<i))
   247 		{
   248 			strcopy(joins[total++], 32, g_FlagNames[i]);
   249 		}
   250 	}
   251 	
   252 	decl String:custom_flags[32];
   253 	if (CustomFlagsToString(custom_flags, sizeof(custom_flags), flags))
   254 	{
   255 		Format(joins[total++], 32, "custom(%s)", custom_flags);
   256 	}
   257 
   258 	ImplodeStrings(joins, total, ", ", buffer, maxlength);
   259 }
   260 
   261 public Action:Command_Cvar(client, args)
   262 {
   263 	if (args < 1)
   264 	{
   265 		if (client == 0)
   266 		{
   267 			ReplyToCommand(client, "[SM] Usage: sm_cvar <cvar|protect> [value]");
   268 		}
   269 		else
   270 		{
   271 			ReplyToCommand(client, "[SM] Usage: sm_cvar <cvar> [value]");
   272 		}
   273 		return Plugin_Handled;
   274 	}
   275 
   276 	decl String:cvarname[64];
   277 	GetCmdArg(1, cvarname, sizeof(cvarname));
   278 	
   279 	if (client == 0 && StrEqual(cvarname, "protect"))
   280 	{
   281 		if (args < 2)
   282 		{
   283 			ReplyToCommand(client, "[SM] Usage: sm_cvar <protect> <cvar>");
   284 			return Plugin_Handled;
   285 		}
   286 		GetCmdArg(2, cvarname, sizeof(cvarname));
   287 		ProtectVar(cvarname);
   288 		ReplyToCommand(client, "[SM] %t", "Cvar is now protected", cvarname);
   289 		return Plugin_Handled;
   290 	}
   291 
   292 	new Handle:hndl = FindConVar(cvarname);
   293 	if (hndl == INVALID_HANDLE)
   294 	{
   295 		ReplyToCommand(client, "[SM] %t", "Unable to find cvar", cvarname);
   296 		return Plugin_Handled;
   297 	}
   298 	
   299 	new bool:allowed = false;
   300 	new client_flags = client == 0 ? ADMFLAG_ROOT : GetUserFlagBits(client);
   301 	
   302 	if (client_flags & ADMFLAG_ROOT)
   303 	{
   304 		allowed = true;
   305 	}
   306 	else
   307 	{
   308 		if (GetConVarFlags(hndl) & FCVAR_PROTECTED)
   309 		{
   310 			allowed = ((client_flags & ADMFLAG_PASSWORD) == ADMFLAG_PASSWORD);
   311 		}
   312 		else if (StrEqual(cvarname, "sv_cheats"))
   313 		{
   314 			allowed = ((client_flags & ADMFLAG_CHEATS) == ADMFLAG_CHEATS);
   315 		}
   316 		else if (!IsVarProtected(cvarname))
   317 		{
   318 			allowed = true;
   319 		}
   320 	}
   321 	
   322 	if (!allowed)
   323 	{
   324 		ReplyToCommand(client, "[SM] %t", "No access to cvar");
   325 		return Plugin_Handled;
   326 	}
   327 
   328 	decl String:value[255];
   329 	if (args < 2)
   330 	{
   331 		GetConVarString(hndl, value, sizeof(value));
   332 
   333 		ReplyToCommand(client, "[SM] %t", "Value of cvar", cvarname, value);
   334 		return Plugin_Handled;
   335 	}
   336 
   337 	GetCmdArg(2, value, sizeof(value));
   338 
   339 	if ((GetConVarFlags(hndl) & FCVAR_PROTECTED) != FCVAR_PROTECTED)
   340 	{
   341 		ShowActivity2(client, "[SM] ", "%t", "Cvar changed", cvarname, value);
   342 	}
   343 	else
   344 	{
   345 		ReplyToCommand(client, "[SM] %t", "Cvar changed", cvarname, value);
   346 	}
   347 
   348 	LogAction(client, -1, "\"%L\" changed cvar (cvar \"%s\") (value \"%s\")", client, cvarname, value);
   349 
   350 	SetConVarString(hndl, value, true);
   351 
   352 	return Plugin_Handled;
   353 }
   354 
   355 public Action:Command_Rcon(client, args)
   356 {
   357 	if (args < 1)
   358 	{
   359 		ReplyToCommand(client, "[SM] Usage: sm_rcon <args>");
   360 		return Plugin_Handled;
   361 	}
   362 
   363 	decl String:argstring[255];
   364 	GetCmdArgString(argstring, sizeof(argstring));
   365 
   366 	LogAction(client, -1, "\"%L\" console command (cmdline \"%s\")", client, argstring);
   367 
   368 	ServerCommand("%s", argstring);
   369 
   370 	return Plugin_Handled;
   371 }
   372 
   373 public Action:Command_ReVote(client, args)
   374 {
   375 	if (client == 0)
   376 	{
   377 		ReplyToCommand(client, "[SM] %t", "Command is in-game only");
   378 		return Plugin_Handled;
   379 	}
   380 	
   381 	if (!IsVoteInProgress())
   382 	{
   383 		ReplyToCommand(client, "[SM] %t", "Vote Not In Progress");
   384 		return Plugin_Handled;
   385 	}
   386 	
   387 	if (!IsClientInVotePool(client))
   388 	{
   389 		ReplyToCommand(client, "[SM] %t", "Cannot participate in vote");
   390 		return Plugin_Handled;
   391 	}
   392 	
   393 	if (!RedrawClientVoteMenu(client))
   394 	{
   395 		ReplyToCommand(client, "[SM] %t", "Cannot change vote");
   396 	}
   397 	
   398 	return Plugin_Handled;
   399 }