plugins/basecommands.sp
author David Anderson <dvander@alliedmods.net>
Fri Sep 14 02:11:10 2007 +0000 (2007-09-14)
changeset 1423 e73b3563f254
parent 1417 79f72a315320
child 1510 de71b8774afc
permissions -rw-r--r--
- added 3 new natives for banning/unbanning and interception
- moved banning commands into new plugin, basebans
- improved quality and input methods of ban commands
- corrected svn props on a few files
- added an IsLANServer() to IGameHelpers API
- completely deprecated and removed old banning forwards
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod Basic Commands Plugin
     5  * Implements basic admin commands.
     6  *
     7  * SourceMod (C)2004-2007 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 works) 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 
    38 public Plugin:myinfo =
    39 {
    40 	name = "Basic Commands",
    41 	author = "AlliedModders LLC",
    42 	description = "Basic Admin Commands",
    43 	version = SOURCEMOD_VERSION,
    44 	url = "http://www.sourcemod.net/"
    45 };
    46 
    47 public OnPluginStart()
    48 {
    49 	LoadTranslations("common.phrases");
    50 
    51 	RegAdminCmd("sm_kick", Command_Kick, ADMFLAG_KICK, "sm_kick <#userid|name> [reason]");
    52 	RegAdminCmd("sm_map", Command_Map, ADMFLAG_CHANGEMAP, "sm_map <map>");
    53 	RegAdminCmd("sm_rcon", Command_Rcon, ADMFLAG_RCON, "sm_rcon <args>");
    54 	RegAdminCmd("sm_cvar", Command_Cvar, ADMFLAG_CONVARS, "sm_cvar <cvar> [value]");
    55 	RegAdminCmd("sm_execcfg", Command_ExecCfg, ADMFLAG_CONFIG, "sm_execcfg <filename>");
    56 	RegAdminCmd("sm_who", Command_Who, ADMFLAG_GENERIC, "sm_who [#userid|name]");
    57 	RegAdminCmd("sm_reloadadmins", Command_ReloadAdmins, ADMFLAG_BAN, "sm_reloadadmins");
    58 	RegAdminCmd("sm_cancelvote", Command_CancelVote, ADMFLAG_VOTE, "sm_cancelvote");
    59 }
    60 
    61 public Action:Command_ReloadAdmins(client, args)
    62 {
    63 	/* Dump it all! */
    64 	DumpAdminCache(AdminCache_Groups, true);
    65 	DumpAdminCache(AdminCache_Overrides, true);
    66 
    67 	LogAction(client, -1, "\"%L\" refreshed the admin cache.", client);
    68 	ReplyToCommand(client, "[SM] %t", "Admin cache refreshed");
    69 
    70 	return Plugin_Handled;
    71 }
    72 
    73 #define FLAG_STRINGS		14
    74 new String:g_FlagNames[FLAG_STRINGS][20] =
    75 {
    76 	"res",
    77 	"admin",
    78 	"kick",
    79 	"ban",
    80 	"unban",
    81 	"slay",
    82 	"map",
    83 	"cvars",
    84 	"cfg",
    85 	"chat",
    86 	"vote",
    87 	"pass",
    88 	"rcon",
    89 	"cheat"
    90 };
    91 
    92 CustomFlagsToString(String:buffer[], maxlength, flags)
    93 {
    94 	decl String:joins[6][6];
    95 	new total;
    96 	
    97 	for (new i=_:Admin_Custom1; i<=_:Admin_Custom6; i++)
    98 	{
    99 		if (flags & (1<<i))
   100 		{
   101 			IntToString(i - _:Admin_Custom1 + 1, joins[total++], 6);
   102 		}
   103 	}
   104 	
   105 	ImplodeStrings(joins, total, ",", buffer, maxlength);
   106 	
   107 	return total;
   108 }
   109 
   110 FlagsToString(String:buffer[], maxlength, flags)
   111 {
   112 	decl String:joins[FLAG_STRINGS+1][32];
   113 	new total;
   114 
   115 	for (new i=0; i<FLAG_STRINGS; i++)
   116 	{
   117 		if (flags & (1<<i))
   118 		{
   119 			strcopy(joins[total++], 32, g_FlagNames[i]);
   120 		}
   121 	}
   122 	
   123 	decl String:custom_flags[32];
   124 	if (CustomFlagsToString(custom_flags, sizeof(custom_flags), flags))
   125 	{
   126 		Format(joins[total++], 32, "custom(%s)", custom_flags);
   127 	}
   128 
   129 	ImplodeStrings(joins, total, ", ", buffer, maxlength);
   130 }
   131 
   132 public Action:Command_Who(client, args)
   133 {
   134 	if (args < 1)
   135 	{
   136 		/* Display header */
   137 		decl String:t_access[16], String:t_name[16];
   138 		Format(t_access, sizeof(t_access), "%t", "Access", client);
   139 		Format(t_name, sizeof(t_name), "%t", "Name", client);
   140 
   141 		PrintToConsole(client, "%-24.23s %s", t_name, t_access);
   142 
   143 		/* List all players */
   144 		new maxClients = GetMaxClients();
   145 		decl String:flagstring[255];
   146 
   147 		for (new i=1; i<=maxClients; i++)
   148 		{
   149 			if (!IsClientInGame(i))
   150 			{
   151 				continue;
   152 			}
   153 			new flags = GetUserFlagBits(i);
   154 			if (flags == 0)
   155 			{
   156 				strcopy(flagstring, sizeof(flagstring), "none");
   157 			} else if (flags & ADMFLAG_ROOT) {
   158 				strcopy(flagstring, sizeof(flagstring), "root");
   159 			} else {
   160 				FlagsToString(flagstring, sizeof(flagstring), flags);
   161 			}
   162 			decl String:name[65];
   163 			GetClientName(i, name, sizeof(name));
   164 			PrintToConsole(client, "%d. %-24.23s %s", i, name, flagstring);
   165 		}
   166 
   167 		if (GetCmdReplySource() == SM_REPLY_TO_CHAT)
   168 		{
   169 			ReplyToCommand(client, "[SM] %t", "See console for output");
   170 		}
   171 
   172 		return Plugin_Handled;
   173 	}
   174 
   175 	decl String:arg[65];
   176 	GetCmdArg(1, arg, sizeof(arg));
   177 
   178 	new clients[2];
   179 	new numClients = SearchForClients(arg, clients, 2);
   180 
   181 	if (numClients == 0)
   182 	{
   183 		ReplyToCommand(client, "[SM] %t", "No matching client");
   184 		return Plugin_Handled;
   185 	} else if (numClients > 1) {
   186 		ReplyToCommand(client, "[SM] %t", "More than one client matches", arg);
   187 		return Plugin_Handled;
   188 	}
   189 
   190 	new flags = GetUserFlagBits(clients[0]);
   191 	decl String:flagstring[255];
   192 	if (flags == 0)
   193 	{
   194 		strcopy(flagstring, sizeof(flagstring), "none");
   195 	} else if (flags & ADMFLAG_ROOT) {
   196 		strcopy(flagstring, sizeof(flagstring), "root");
   197 	} else {
   198 		FlagsToString(flagstring, sizeof(flagstring), flags);
   199 	}
   200 
   201 	ReplyToCommand(client, "[SM] %t: %s", "Access", flagstring);
   202 
   203 	return Plugin_Handled;
   204 }
   205 
   206 public Action:Command_ExecCfg(client, args)
   207 {
   208 	if (args < 1)
   209 	{
   210 		ReplyToCommand(client, "[SM] Usage: sm_execcfg <filename>");
   211 		return Plugin_Handled;
   212 	}
   213 
   214 	new String:path[64] = "cfg/";
   215 	GetCmdArg(1, path[4], sizeof(path)-4);
   216 
   217 	if (!FileExists(path))
   218 	{
   219 		ReplyToCommand(client, "[SM] %t", "Config not found", path[4]);
   220 		return Plugin_Handled;
   221 	}
   222 
   223 	ShowActivity(client, "%t", "Executed config", path[4]);
   224 
   225 	LogAction(client, -1, "\"%L\" executed config (file \"%s\")", client, path[4]);
   226 
   227 	ServerCommand("exec \"%s\"", path[4]);
   228 
   229 	return Plugin_Handled;
   230 }
   231 
   232 public Action:Command_Cvar(client, args)
   233 {
   234 	if (args < 1)
   235 	{
   236 		ReplyToCommand(client, "[SM] Usage: sm_cvar <cvar> [value]");
   237 		return Plugin_Handled;
   238 	}
   239 
   240 	decl String:cvarname[33];
   241 	GetCmdArg(1, cvarname, sizeof(cvarname));
   242 
   243 	new Handle:hndl = FindConVar(cvarname);
   244 	if (hndl == INVALID_HANDLE)
   245 	{
   246 		ReplyToCommand(client, "[SM] %t", "Unable to find cvar", cvarname);
   247 		return Plugin_Handled;
   248 	}
   249 
   250 	new bool:allowed = false;
   251 	if (GetConVarFlags(hndl) & FCVAR_PROTECTED)
   252 	{
   253 		/* If they're root, allow anything */
   254 		if ((GetUserFlagBits(client) & ADMFLAG_ROOT) == ADMFLAG_ROOT)
   255 		{
   256 			allowed = true;
   257 		}
   258 		/* If they're not root, and getting sv_password, see if they have ADMFLAG_PASSWORD */
   259 		else if (StrEqual(cvarname, "sv_password") && (GetUserFlagBits(client) & ADMFLAG_PASSWORD))
   260 		{
   261 			allowed = true;
   262 		}
   263 	}
   264 	/* Do a check for the cheat cvar */
   265 	else if (StrEqual(cvarname, "sv_cheats"))
   266 	{
   267 		if (GetUserFlagBits(client) & ADMFLAG_CHEATS
   268 			|| GetUserFlagBits(client) & ADMFLAG_ROOT)
   269 		{
   270 			allowed = true;
   271 		}
   272 	}
   273 	/* If we drop down to here, it was a normal cvar. */
   274 	else
   275 	{
   276 		allowed = true;
   277 	}
   278 
   279 	if (!allowed)
   280 	{
   281 		ReplyToCommand(client, "[SM] %t", "No access to cvar");
   282 		return Plugin_Handled;
   283 	}
   284 
   285 	decl String:value[255];
   286 	if (args < 2)
   287 	{
   288 		GetConVarString(hndl, value, sizeof(value));
   289 
   290 		ReplyToCommand(client, "[SM] %t", "Value of cvar", cvarname, value);
   291 		return Plugin_Handled;
   292 	}
   293 
   294 	GetCmdArg(2, value, sizeof(value));
   295 
   296 	if ((GetConVarFlags(hndl) & FCVAR_PROTECTED) != FCVAR_PROTECTED)
   297 	{
   298 		ShowActivity(client, "%t", "Cvar changed", cvarname, value);
   299 	} else {
   300 		ReplyToCommand(client, "[SM] %t", "Cvar changed", cvarname, value);
   301 	}
   302 
   303 	LogAction(client, -1, "\"%L\" changed cvar (cvar \"%s\") (value \"%s\")", client, cvarname, value);
   304 
   305 	SetConVarString(hndl, value, true);
   306 
   307 	return Plugin_Handled;
   308 }
   309 
   310 public Action:Command_Rcon(client, args)
   311 {
   312 	if (args < 1)
   313 	{
   314 		ReplyToCommand(client, "[SM] Usage: sm_rcon <args>");
   315 		return Plugin_Handled;
   316 	}
   317 
   318 	decl String:argstring[255];
   319 	GetCmdArgString(argstring, sizeof(argstring));
   320 
   321 	LogAction(client, -1, "\"%L\" console command (cmdline \"%s\")", client, argstring);
   322 
   323 	ServerCommand("%s", argstring);
   324 
   325 	return Plugin_Handled;
   326 }
   327 
   328 public Action:Command_Map(client, args)
   329 {
   330 	if (args < 1)
   331 	{
   332 		ReplyToCommand(client, "[SM] Usage: sm_map <map>");
   333 		return Plugin_Handled;
   334 	}
   335 
   336 	decl String:map[64];
   337 	GetCmdArg(1, map, sizeof(map));
   338 
   339 	if (!IsMapValid(map))
   340 	{
   341 		ReplyToCommand(client, "[SM] %t", "Map was not found", map);
   342 		return Plugin_Handled;
   343 	}
   344 
   345 	ShowActivity(client, "%t", "Changing map", map);
   346 
   347 	LogAction(client, -1, "\"%L\" changed map to \"%s\"", client, map);
   348 
   349 	new Handle:dp;
   350 	CreateDataTimer(3.0, Timer_ChangeMap, dp);
   351 	WritePackString(dp, map);
   352 
   353 	return Plugin_Handled;
   354 }
   355 
   356 public Action:Timer_ChangeMap(Handle:timer, Handle:dp)
   357 {
   358 	decl String:map[65];
   359 
   360 	ResetPack(dp);
   361 	ReadPackString(dp, map, sizeof(map));
   362 
   363 	ServerCommand("changelevel \"%s\"", map);
   364 
   365 	return Plugin_Stop;
   366 }
   367 
   368 public Action:Command_Kick(client, args)
   369 {
   370 	if (args < 1)
   371 	{
   372 		ReplyToCommand(client, "[SM] Usage: sm_kick <#userid|name> [reason]");
   373 		return Plugin_Handled;
   374 	}
   375 
   376 
   377 	decl String:Arguments[256];
   378 	GetCmdArgString(Arguments, sizeof(Arguments));
   379 
   380 	decl String:arg[65];
   381 	new len = BreakString(Arguments, arg, sizeof(arg));
   382 
   383 	new target = FindTarget(client, arg);
   384 	if (target == -1)
   385 	{
   386 		return Plugin_Handled;
   387 	}
   388 
   389 	GetClientName(target, arg, sizeof(arg));
   390 
   391 	if (len == -1)
   392 	{
   393 		/* Safely null terminate */
   394 		len = 0;
   395 		Arguments[0] = '\0';
   396 	}
   397 
   398 	ShowActivity(client, "%t", "Kicked player", arg);
   399 	LogAction(client, target, "\"%L\" kicked \"%L\" (reason \"%s\")", client, target, Arguments[len]);
   400 
   401 	if (Arguments[0] == '\0')
   402 	{
   403 		KickClient(target, "%t", "Kicked by admin");
   404 	}
   405 	else
   406 	{
   407 		KickClient(target, "%s", Arguments[len]);
   408 	}
   409 
   410 	return Plugin_Handled;
   411 }
   412 
   413 public Action:Command_CancelVote(client, args)
   414 {
   415 	if (!IsVoteInProgress())
   416 	{
   417 		ReplyToCommand(client, "[SM] %t", "Vote Not In Progress");
   418 		return Plugin_Handled;
   419 	}
   420 
   421 	ShowActivity(client, "%t", "Cancelled Vote");
   422 	
   423 	CancelVote();
   424 	
   425 	return Plugin_Handled;
   426 }