From 602b0aa6a5b0415aa9284643eed2b55b15d8fc36 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 1 Oct 2007 18:50:07 +0000 Subject: [PATCH] - added topmenus extension to build - basecommands is slowly getting split into multiple source files now - added experimental api of a potential admin menu design - added experimental admin menu entry to basecommands to kick things off --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401516 --- plugins/adminmenu.sp | 176 ++++++++++++++++++++++++++++++++ plugins/basecommands.sp | 93 +++++++++-------- plugins/basecommands/kick.sp | 124 ++++++++++++++++++++++ plugins/include/adminmenu.inc | 110 ++++++++++++++++++++ tools/builder/PkgCore.cs | 11 +- translations/common.phrases.txt | 20 ++++ 6 files changed, 487 insertions(+), 47 deletions(-) create mode 100644 plugins/adminmenu.sp create mode 100644 plugins/basecommands/kick.sp create mode 100644 plugins/include/adminmenu.inc diff --git a/plugins/adminmenu.sp b/plugins/adminmenu.sp new file mode 100644 index 00000000..99760f5f --- /dev/null +++ b/plugins/adminmenu.sp @@ -0,0 +1,176 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Anti-Flood Plugin + * Protects against chat flooding. + * + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#pragma semicolon 1 + +#include +#include + +public Plugin:myinfo = +{ + name = "Admin Menu", + author = "AlliedModders LLC", + description = "Administration Menu", + version = SOURCEMOD_VERSION, + url = "http://www.sourcemod.net/" +}; + +/* Forwards */ +new Handle:hOnAdminMenuReady = INVALID_HANDLE; +new Handle:hOnAdminMenuCreated = INVALID_HANDLE; + +/* Menus */ +new Handle:hAdminMenu = INVALID_HANDLE; + +/* Top menu objects */ +new TopMenuObject:obj_playercmds = INVALID_TOPMENUOBJECT; + +public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) +{ + CreateNative("GetAdminTopMenu", __GetAdminTopMenu); + CreateNative("AddTargetsToMenu", __AddTargetsToMenu); + RegPluginLibrary("adminmenu"); + return true; +} + +public OnPluginStart() +{ + LoadTranslations("common.phrases"); + + hOnAdminMenuCreated = CreateGlobalForward("OnAdminMenuCreated", ET_Ignore, Param_Cell); + hOnAdminMenuReady = CreateGlobalForward("OnAdminMenuReady", ET_Ignore, Param_Cell); + + RegAdminCmd("sm_admin", Command_DisplayMenu, ADMFLAG_GENERIC, "sm_admin"); +} + +public OnAllPluginsLoaded() +{ + hAdminMenu = CreateTopMenu(CategoryHandler); + + obj_playercmds = AddToTopMenu(hAdminMenu, + "PlayerCommands", + TopMenuObject_Category, + CategoryHandler, + INVALID_TOPMENUOBJECT); + + Call_StartForward(hOnAdminMenuCreated); + Call_PushCell(hAdminMenu); + Call_Finish(); + + Call_StartForward(hOnAdminMenuReady); + Call_PushCell(hAdminMenu); + Call_Finish(); +} + +public CategoryHandler(Handle:topmenu, + TopMenuAction:action, + TopMenuObject:object_id, + param, + String:buffer[], + maxlength) +{ + if (action == TopMenuAction_DrawTitle) + { + if (object_id == INVALID_TOPMENUOBJECT) + { + Format(buffer, maxlength, "%T:", "Admin Menu", param); + } + else if (object_id == obj_playercmds) + { + Format(buffer, maxlength, "%T:", "Player Commands", param); + } + } + else if (action == TopMenuAction_DrawOption) + { + if (object_id == obj_playercmds) + { + Format(buffer, maxlength, "%T", "Player Commands", param); + } + return ITEMDRAW_DEFAULT; + } + + return 0; +} + +public __GetAdminTopMenu(Handle:plugin, numParams) +{ + return _:hAdminMenu; +} + +public __AddTargetsToMenu(Handle:plugin, numParams) +{ + return UTIL_AddTargetsToMenu(GetNativeCell(1), GetNativeCell(2), GetNativeCell(3)); +} + +public Action:Command_DisplayMenu(client, args) +{ + DisplayTopMenu(hAdminMenu, client, TopMenuPosition_Start); + + return Plugin_Handled; +} + +stock UTIL_AddTargetsToMenu(Handle:menu, source_client, bool:in_game_only) +{ + new max_clients = GetMaxClients(); + decl String:user_id[12]; + decl String:name[MAX_NAME_LENGTH]; + decl String:display[MAX_NAME_LENGTH+12]; + + new num_clients; + + for (new i = 1; i <= max_clients; i++) + { + if (!IsClientConnected(i) || IsClientInKickQueue(i)) + { + continue; + } + + if (in_game_only && !IsClientInGame(i)) + { + continue; + } + + if (source_client && !CanUserTarget(source_client, i)) + { + continue; + } + + IntToString(GetClientUserId(i), user_id, sizeof(user_id)); + GetClientName(i, name, sizeof(name)); + Format(display, sizeof(display), "%s (%s)", name, user_id); + AddMenuItem(menu, user_id, display); + num_clients++; + } + + return num_clients; +} diff --git a/plugins/basecommands.sp b/plugins/basecommands.sp index 3c7ce935..2cc119bc 100644 --- a/plugins/basecommands.sp +++ b/plugins/basecommands.sp @@ -34,6 +34,8 @@ #pragma semicolon 1 #include +#undef REQUIRE_PLUGIN +#include public Plugin:myinfo = { @@ -44,6 +46,10 @@ public Plugin:myinfo = url = "http://www.sourcemod.net/" }; +new Handle:hTopMenu = INVALID_HANDLE; + +#include "basecommands/kick.sp" + public OnPluginStart() { LoadTranslations("common.phrases"); @@ -56,6 +62,47 @@ public OnPluginStart() RegAdminCmd("sm_who", Command_Who, ADMFLAG_GENERIC, "sm_who [#userid|name]"); RegAdminCmd("sm_reloadadmins", Command_ReloadAdmins, ADMFLAG_BAN, "sm_reloadadmins"); RegAdminCmd("sm_cancelvote", Command_CancelVote, ADMFLAG_VOTE, "sm_cancelvote"); + + /* Account for late loading */ + new Handle:topmenu; + if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) + { + OnAdminMenuReady(topmenu); + } +} + +public OnAdminMenuReady(Handle:topmenu) +{ + /* Block us from being called twice */ + if (topmenu == hTopMenu) + { + return; + } + + /* Save the Handle */ + hTopMenu = topmenu; + + /* Build the "Player Commands" category */ + new TopMenuObject:player_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_PLAYERCOMMANDS); + + if (player_commands != INVALID_TOPMENUOBJECT) + { + AddToTopMenu(hTopMenu, + "Kick", + TopMenuObject_Item, + AdminMenu_Kick, + player_commands, + "sm_kick", + ADMFLAG_KICK); + } +} + +public OnLibraryRemoved(const String:name[]) +{ + if (strcmp(name, "adminmenu") == 0) + { + hTopMenu = INVALID_HANDLE; + } } public Action:Command_ReloadAdmins(client, args) @@ -365,51 +412,6 @@ public Action:Timer_ChangeMap(Handle:timer, Handle:dp) return Plugin_Stop; } -public Action:Command_Kick(client, args) -{ - if (args < 1) - { - ReplyToCommand(client, "[SM] Usage: sm_kick <#userid|name> [reason]"); - return Plugin_Handled; - } - - - decl String:Arguments[256]; - GetCmdArgString(Arguments, sizeof(Arguments)); - - decl String:arg[65]; - new len = BreakString(Arguments, arg, sizeof(arg)); - - new target = FindTarget(client, arg); - if (target == -1) - { - return Plugin_Handled; - } - - GetClientName(target, arg, sizeof(arg)); - - if (len == -1) - { - /* Safely null terminate */ - len = 0; - Arguments[0] = '\0'; - } - - ShowActivity(client, "%t", "Kicked player", arg); - LogAction(client, target, "\"%L\" kicked \"%L\" (reason \"%s\")", client, target, Arguments[len]); - - if (Arguments[0] == '\0') - { - KickClient(target, "%t", "Kicked by admin"); - } - else - { - KickClient(target, "%s", Arguments[len]); - } - - return Plugin_Handled; -} - public Action:Command_CancelVote(client, args) { if (!IsVoteInProgress()) @@ -424,3 +426,4 @@ public Action:Command_CancelVote(client, args) return Plugin_Handled; } + diff --git a/plugins/basecommands/kick.sp b/plugins/basecommands/kick.sp new file mode 100644 index 00000000..b4b59743 --- /dev/null +++ b/plugins/basecommands/kick.sp @@ -0,0 +1,124 @@ + +PerformKick(client, target, const String:reason[]) +{ + decl String:name[MAX_NAME_LENGTH]; + + GetClientName(target, name, sizeof(name)); + + ShowActivity(client, "%t", "Kicked player", name); + LogAction(client, target, "\"%L\" kicked \"%L\" (reason \"%s\")", client, target, reason); + + if (reason[0] == '\0') + { + KickClient(target, "%t", "Kicked by admin"); + } + else + { + KickClient(target, "%s", reason); + } +} + +DisplayKickMenu(client) +{ + new Handle:menu = CreateMenu(MenuHandler_Kick); + + decl String:title[100]; + Format(title, sizeof(title), "%T:", "Kick player", client); + SetMenuTitle(menu, title); + SetMenuExitBackButton(menu, true); + + AddTargetsToMenu(menu, client, false); + + DisplayMenu(menu, client, MENU_TIME_FOREVER); +} + +public AdminMenu_Kick(Handle:topmenu, + TopMenuAction:action, + TopMenuObject:object_id, + param, + String:buffer[], + maxlength) +{ + if (action == TopMenuAction_DrawOption) + { + Format(buffer, maxlength, "%T", "Kick player", param); + } + else if (action == TopMenuAction_SelectOption) + { + DisplayKickMenu(param); + } +} + +public MenuHandler_Kick(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_End) + { + CloseHandle(menu); + } + else if (action == MenuAction_Cancel) + { + if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE) + { + DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory); + } + } + else if (action == MenuAction_Select) + { + decl String:info[32]; + new userid, target; + + GetMenuItem(menu, param2, info, sizeof(info)); + userid = StringToInt(info); + + if ((target = GetClientOfUserId(userid)) == 0) + { + PrintToChat(param1, "[SM] %t", "Player no longer available"); + } + else if (!CanUserTarget(param1, target)) + { + PrintToChat(param1, "[SM] %t", "Unable to target"); + } + else + { + PerformKick(param1, target, ""); + } + + /* Re-draw the menu if they're still valid */ + if (IsClientInGame(param1) && !IsClientInKickQueue(param1)) + { + DisplayKickMenu(param1); + } + } +} + +public Action:Command_Kick(client, args) +{ + if (args < 1) + { + ReplyToCommand(client, "[SM] Usage: sm_kick <#userid|name> [reason]"); + return Plugin_Handled; + } + + decl String:Arguments[256]; + GetCmdArgString(Arguments, sizeof(Arguments)); + + decl String:arg[65]; + new len = BreakString(Arguments, arg, sizeof(arg)); + + new target = FindTarget(client, arg); + if (target == -1) + { + return Plugin_Handled; + } + + if (len == -1) + { + /* Safely null terminate */ + len = 0; + Arguments[0] = '\0'; + } + + PerformKick(client, target, Arguments[len]); + + return Plugin_Handled; +} diff --git a/plugins/include/adminmenu.inc b/plugins/include/adminmenu.inc new file mode 100644 index 00000000..094d2146 --- /dev/null +++ b/plugins/include/adminmenu.inc @@ -0,0 +1,110 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This file is part of the SourceMod/SourcePawn SDK. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#if defined _adminmenu_included + #endinput +#endif +#define _adminmenu_included + +/* Decide whether topmenus should be required */ +#if !defined REQUIRE_PLUGIN + #if defined REQUIRE_EXTENSIONS + #define TEMP_REQUIRE_EXTENSIONS + #undef REQUIRE_EXTENSIONS +#endif + +#include + +/* Restore old REQUIRE_EXTENSIONS value if necessary */ +#if defined TEMP_REQUIRE_EXTENSIONS + #define REQUIRE_EXTENSIONS + #undef TEMP_REQUIRE_EXTENSIONS +#endif + +/** Category for player commands. */ +#define ADMINMENU_PLAYERCOMMANDS "PlayerCommands" + +/** + * Called when the admin menu is created and 3rd party plugins can grab + * the Handle or add categories. + * + * @param topmenu Handle to the admin menu's TopMenu. + * @noreturn + */ +forward OnAdminMenuCreated(Handle:topmenu); + +/** + * Called when the admin menu is ready to have items added. + * + * @param topmenu Handle to the admin menu's TopMenu. + * @noreturn + */ +forward OnAdminMenuReady(Handle:topmenu); + +/** + * Retrieves the Handle to the admin top menu. + * + * @return Handle to the admin menu's TopMenu, + * or INVALID_HANDLE if not created yet. + */ +native Handle:GetAdminTopMenu(); + +/** + * Adds targets to an admin menu. + * + * Each client is displayed as: name (userid) + * Each item contains the userid as a string for its info. + * + * @param menu Menu Handle. + * @param source_client Source client, or 0 to ignore immunity. + * @param in_game_only True to only select in-game players. + * @return Number of clients added. + */ +native AddTargetsToMenu(Handle:menu, source_client, bool:in_game_only=true); + +/* DO NOT EDIT BELOW THIS LINE */ + +public SharedPlugin:__pl_adminmenu = +{ + name = "adminmenu", + file = "adminmenu.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +public __pl_adminmenu_SetNTVOptional() +{ + MarkNativeAsOptional("GetAdminTopMenu"); +} diff --git a/tools/builder/PkgCore.cs b/tools/builder/PkgCore.cs index 9e59b490..8c98617e 100644 --- a/tools/builder/PkgCore.cs +++ b/tools/builder/PkgCore.cs @@ -29,7 +29,7 @@ namespace builder */ public override string [] GetFolders() { - string [] folders = new string[16]; + string [] folders = new string[17]; folders[0] = "addons/sourcemod/bin"; folders[1] = "addons/sourcemod/plugins/disabled"; @@ -47,6 +47,7 @@ namespace builder folders[13] = "addons/sourcemod/configs/sql-init-scripts/mysql"; folders[14] = "addons/sourcemod/configs/sql-init-scripts/sqlite"; folders[15] = "addons/sourcemod/extensions/games"; + folders[16] = "addons/sourcemod/scripting/basecommands"; return folders; } @@ -93,6 +94,7 @@ namespace builder builder.CopyFolder(this, "public/licenses", "addons/sourcemod", null); builder.CopyFolder(this, "plugins/admin-flatfile", "addons/sourcemod/scripting/admin-flatfile", null); builder.CopyFolder(this, "plugins/testsuite", "addons/sourcemod/scripting/testsuite", null); + builder.CopyFolder(this, "plugins/basecommands", "addons/sourcemod/scripting/basecommands", null); } /** @@ -100,7 +102,7 @@ namespace builder */ public override Library [] GetLibraries() { - Library [] libs = new Library[9]; + Library [] libs = new Library[10]; for (int i=0; i