using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Admin;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using CS2_SimpleAdminApi;
namespace CS2_SimpleAdmin.Menus;
public abstract class BasicMenu
{
///
/// Initializes all menus in the system by registering them with the MenuManager.
///
public static void Initialize()
{
var manager = MenuManager.Instance;
// Players category menus
manager.RegisterMenu("players", "slap", "Slap Player", CreateSlapMenu, "@css/slay");
manager.RegisterMenu("players", "slay", "Slay Player", CreateSlayMenu, "@css/slay");
manager.RegisterMenu("players", "kick", "Kick Player", CreateKickMenu, "@css/kick");
manager.RegisterMenu("players", "warn", "Warn Player", CreateWarnMenu, "@css/kick");
manager.RegisterMenu("players", "ban", "Ban Player", CreateBanMenu, "@css/ban");
manager.RegisterMenu("players", "gag", "Gag Player", CreateGagMenu, "@css/chat");
manager.RegisterMenu("players", "mute", "Mute Player", CreateMuteMenu, "@css/chat");
manager.RegisterMenu("players", "silence", "Silence Player", CreateSilenceMenu, "@css/chat");
manager.RegisterMenu("players", "team", "Force Team", CreateForceTeamMenu, "@css/kick");
// Server category menus
manager.RegisterMenu("server", "plugins", "Manage Plugins", CreatePluginsMenu, "@css/root");
manager.RegisterMenu("server", "changemap", "Change Map", CreateChangeMapMenu, "@css/changemap");
manager.RegisterMenu("server", "restart", "Restart Game", CreateRestartGameMenu, "@css/generic");
manager.RegisterMenu("server", "custom", "Custom Commands", CreateCustomCommandsMenu, "@css/generic");
// Admin category menus
manager.RegisterMenu("admin", "add", "Add Admin", CreateAddAdminMenu, "@css/root");
manager.RegisterMenu("admin", "remove", "Remove Admin", CreateRemoveAdminMenu, "@css/root");
manager.RegisterMenu("admin", "reload", "Reload Admins", CreateReloadAdminsMenu, "@css/root");
}
///
/// Creates menu for slapping players with selectable damage amounts.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the slap menu.
private static MenuBuilder CreateSlapMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var slapMenu = new MenuBuilder(localizer?["sa_slap"] ?? "Slap Player");
var players = Helper.GetValidPlayers().Where(admin.CanTarget);
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
slapMenu.AddSubMenu(playerName, () => CreateSlapDamageMenu(admin, player));
}
return slapMenu.WithBackButton();
}
///
/// Creates damage selection submenu for slapping a specific player.
///
/// The admin player executing the slap.
/// The target player to be slapped.
/// A MenuBuilder instance for the slap damage menu.
private static MenuBuilder CreateSlapDamageMenu(CCSPlayerController admin, CCSPlayerController target)
{
var slapDamageMenu = new MenuBuilder($"Slap: {target.PlayerName}");
var damages = new[] { 0, 1, 5, 10, 50, 100 };
foreach (var damage in damages)
{
slapDamageMenu.AddOption($"{damage} HP", _ =>
{
if (target.IsValid)
{
CS2_SimpleAdmin.Slap(admin, target, damage);
// Keep menu open for consecutive slaps
CreateSlapDamageMenu(admin, target).OpenMenu(admin);
}
});
}
return slapDamageMenu.WithBackButton();
}
///
/// Creates menu for slaying (killing) players.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the slay menu.
private static MenuBuilder CreateSlayMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var slayMenu = new MenuBuilder(localizer?["sa_slay"] ?? "Slay Player");
var players = Helper.GetValidPlayers().Where(admin.CanTarget);
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
slayMenu.AddOption(playerName, _ =>
{
if (player.IsValid)
{
CS2_SimpleAdmin.Slay(admin, player);
}
});
}
return slayMenu.WithBackButton();
}
///
/// Creates menu for kicking players with reason selection.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the kick menu.
private static MenuBuilder CreateKickMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var kickMenu = new MenuBuilder(localizer?["sa_kick"] ?? "Kick Player");
var players = Helper.GetValidPlayers().Where(p => !p.IsBot && admin.CanTarget(p));
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
kickMenu.AddSubMenu(playerName, () => CreateReasonMenu(admin, player, "Kick", PenaltyType.Kick,
(_, _, reason) =>
{
if (player.IsValid)
{
CS2_SimpleAdmin.Instance.Kick(admin, player, reason, admin.PlayerName);
}
}));
}
return kickMenu.WithBackButton();
}
///
/// Creates menu for warning players with duration and reason selection.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the warn menu.
private static MenuBuilder CreateWarnMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var warnMenu = new MenuBuilder(localizer?["sa_warn"] ?? "Warn Player");
var players = Helper.GetValidPlayers().Where(p => !p.IsBot && admin.CanTarget(p));
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
warnMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Warn",
(_, _, duration) => CreateReasonMenu(admin, player, "Warn", PenaltyType.Warn,
(_, _, reason) =>
{
if (player.IsValid)
{
CS2_SimpleAdmin.Instance.Warn(admin, player, duration, reason, admin.PlayerName);
}
})));
}
return warnMenu.WithBackButton();
}
///
/// Creates menu for banning players with duration and reason selection.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the ban menu.
private static MenuBuilder CreateBanMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var banMenu = new MenuBuilder(localizer?["sa_ban"] ?? "Ban Player");
var players = Helper.GetValidPlayers().Where(p => !p.IsBot && admin.CanTarget(p));
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
banMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Ban",
(_, _, duration) => CreateReasonMenu(admin, player, "Ban", PenaltyType.Ban,
(_, _, reason) =>
{
if (player.IsValid)
{
CS2_SimpleAdmin.Instance.Ban(admin, player, duration, reason, admin.PlayerName);
}
})));
}
return banMenu.WithBackButton();
}
///
/// Creates menu for gagging (text chat muting) players with duration and reason selection.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the gag menu.
private static MenuBuilder CreateGagMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var gagMenu = new MenuBuilder(localizer?["sa_gag"] ?? "Gag Player");
var players = Helper.GetValidPlayers().Where(p => !p.IsBot && admin.CanTarget(p));
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
gagMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Gag",
(_, _, duration) => CreateReasonMenu(admin, player, "Gag", PenaltyType.Gag,
(_, _, reason) =>
{
if (player.IsValid)
{
CS2_SimpleAdmin.Instance.Gag(admin, player, duration, reason);
}
})));
}
return gagMenu.WithBackButton();
}
///
/// Creates menu for muting (voice chat muting) players with duration and reason selection.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the mute menu.
private static MenuBuilder CreateMuteMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var muteMenu = new MenuBuilder(localizer?["sa_mute"] ?? "Mute Player");
var players = Helper.GetValidPlayers().Where(p => !p.IsBot && admin.CanTarget(p));
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
muteMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Mute",
(_, _, duration) => CreateReasonMenu(admin, player, "Mute", PenaltyType.Mute,
(_, _, reason) =>
{
if (player.IsValid)
{
CS2_SimpleAdmin.Instance.Mute(admin, player, duration, reason);
}
})));
}
return muteMenu.WithBackButton();
}
///
/// Creates menu for silencing (both text and voice chat muting) players with duration and reason selection.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the silence menu.
private static MenuBuilder CreateSilenceMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var silenceMenu = new MenuBuilder(localizer?["sa_silence"] ?? "Silence Player");
var players = Helper.GetValidPlayers().Where(p => !p.IsBot && admin.CanTarget(p));
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
silenceMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Silence",
(_, _, duration) => CreateReasonMenu(admin, player, "Silence", PenaltyType.Silence,
(_, _, reason) =>
{
if (player.IsValid)
{
CS2_SimpleAdmin.Instance.Silence(admin, player, duration, reason);
}
})));
}
return silenceMenu.WithBackButton();
}
///
/// Creates menu for forcing players to switch teams.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the force team menu.
private static MenuBuilder CreateForceTeamMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var teamMenu = new MenuBuilder(localizer?["sa_team_force"] ?? "Force Team");
var players = Helper.GetValidPlayers().Where(p => admin.CanTarget(p));
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
teamMenu.AddSubMenu(playerName, () => CreateTeamSelectionMenu(admin, player));
}
return teamMenu.WithBackButton();
}
///
/// Creates team selection submenu for forcing a specific player to a team.
///
/// The admin player executing the team change.
/// The target player to be moved.
/// A MenuBuilder instance for the team selection menu.
private static MenuBuilder CreateTeamSelectionMenu(CCSPlayerController admin, CCSPlayerController target)
{
var localizer = CS2_SimpleAdmin._localizer;
var teamSelectionMenu = new MenuBuilder($"Force Team: {target.PlayerName}");
var teams = new[]
{
(localizer?["sa_team_ct"] ?? "CT", "ct", CsTeam.CounterTerrorist),
(localizer?["sa_team_t"] ?? "T", "t", CsTeam.Terrorist),
(localizer?["sa_team_swap"] ?? "Swap", "swap", CsTeam.Spectator),
(localizer?["sa_team_spec"] ?? "Spec", "spec", CsTeam.Spectator)
};
foreach (var (name, teamName, teamNum) in teams)
{
teamSelectionMenu.AddOption(name, _ =>
{
if (target.IsValid)
{
CS2_SimpleAdmin.ChangeTeam(admin, target, teamName, teamNum, true);
}
});
}
return teamSelectionMenu.WithBackButton();
}
///
/// Creates menu for managing server plugins.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the plugins menu.
private static MenuBuilder CreatePluginsMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var pluginsMenu = new MenuBuilder(localizer?["sa_menu_pluginsmanager_title"] ?? "Manage Plugins");
pluginsMenu.AddOption("Open Plugins Manager", _ =>
{
admin.ExecuteClientCommandFromServer("css_pluginsmanager");
});
return pluginsMenu.WithBackButton();
}
///
/// Creates menu for changing the current map (includes default and workshop maps).
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the change map menu.
private static MenuBuilder CreateChangeMapMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var mapMenu = new MenuBuilder(localizer?["sa_changemap"] ?? "Change Map");
// Add default maps
var maps = CS2_SimpleAdmin.Instance.Config.DefaultMaps;
foreach (var map in maps)
{
mapMenu.AddOption(map, _ =>
{
CS2_SimpleAdmin.Instance.ChangeMap(admin, map);
});
}
// Add workshop maps
var wsMaps = CS2_SimpleAdmin.Instance.Config.WorkshopMaps;
foreach (var wsMap in wsMaps)
{
mapMenu.AddOption($"{wsMap.Key} (WS)", _ =>
{
CS2_SimpleAdmin.Instance.ChangeWorkshopMap(admin, wsMap.Value?.ToString() ?? wsMap.Key);
});
}
return mapMenu.WithBackButton();
}
///
/// Creates menu for restarting the current game/round.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the restart game menu.
private static MenuBuilder CreateRestartGameMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var restartMenu = new MenuBuilder(localizer?["sa_restart_game"] ?? "Restart Game");
restartMenu.AddOption("Restart Round", _ =>
{
CS2_SimpleAdmin.RestartGame(admin);
});
return restartMenu.WithBackButton();
}
///
/// Creates menu for executing custom server commands defined in configuration.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the custom commands menu.
private static MenuBuilder CreateCustomCommandsMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var customMenu = new MenuBuilder(localizer?["sa_menu_custom_commands"] ?? "Custom Commands");
var customCommands = CS2_SimpleAdmin.Instance.Config.CustomServerCommands;
foreach (var customCommand in customCommands)
{
if (string.IsNullOrEmpty(customCommand.DisplayName) || string.IsNullOrEmpty(customCommand.Command))
continue;
var steamId = new SteamID(admin.SteamID);
if (!AdminManager.PlayerHasPermissions(steamId, customCommand.Flag))
continue;
customMenu.AddOption(customCommand.DisplayName, _ =>
{
Helper.TryLogCommandOnDiscord(admin, customCommand.Command);
if (customCommand.ExecuteOnClient)
admin.ExecuteClientCommandFromServer(customCommand.Command);
else
Server.ExecuteCommand(customCommand.Command);
});
}
return customMenu.WithBackButton();
}
///
/// Creates menu for adding admin privileges to players.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the add admin menu.
private static MenuBuilder CreateAddAdminMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var addAdminMenu = new MenuBuilder(localizer?["sa_admin_add"] ?? "Add Admin");
var players = Helper.GetValidPlayers().Where(p => !p.IsBot && admin.CanTarget(p));
foreach (var player in players)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
addAdminMenu.AddSubMenu(playerName, () => CreateAdminFlagsMenu(admin, player));
}
return addAdminMenu.WithBackButton();
}
///
/// Creates admin flags selection submenu for granting specific permissions to a player.
///
/// The admin player granting permissions.
/// The target player to receive admin privileges.
/// A MenuBuilder instance for the admin flags menu.
private static MenuBuilder CreateAdminFlagsMenu(CCSPlayerController admin, CCSPlayerController target)
{
var flagsMenu = new MenuBuilder($"Add Admin: {target.PlayerName}");
foreach (var adminFlag in CS2_SimpleAdmin.Instance.Config.MenuConfigs.AdminFlags)
{
var hasFlag = AdminManager.PlayerHasPermissions(target, adminFlag.Flag);
flagsMenu.AddOption(adminFlag.Name, _ =>
{
if (target.IsValid)
{
CS2_SimpleAdmin.AddAdmin(admin, target.SteamID.ToString(), target.PlayerName, adminFlag.Flag, 10);
}
}, hasFlag); // Disabled if player already has this flag
}
return flagsMenu.WithBackButton();
}
///
/// Creates menu for removing admin privileges from players.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the remove admin menu.
private static MenuBuilder CreateRemoveAdminMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var removeAdminMenu = new MenuBuilder(localizer?["sa_admin_remove"] ?? "Remove Admin");
var adminPlayers = Helper.GetValidPlayers().Where(p =>
AdminManager.GetPlayerAdminData(p)?.Flags.Count > 0 &&
p != admin &&
admin.CanTarget(p));
foreach (var player in adminPlayers)
{
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
removeAdminMenu.AddOption(playerName, _ =>
{
if (player.IsValid)
{
CS2_SimpleAdmin.Instance.RemoveAdmin(admin, player.SteamID.ToString());
}
});
}
return removeAdminMenu.WithBackButton();
}
///
/// Creates menu for reloading admin list from database.
///
/// The admin player opening the menu.
/// A MenuBuilder instance for the reload admins menu.
private static MenuBuilder CreateReloadAdminsMenu(CCSPlayerController admin)
{
var localizer = CS2_SimpleAdmin._localizer;
var reloadMenu = new MenuBuilder(localizer?["sa_admin_reload"] ?? "Reload Admins");
reloadMenu.AddOption("Reload Admins", _ =>
{
CS2_SimpleAdmin.Instance.ReloadAdmins(admin);
});
return reloadMenu.WithBackButton();
}
///
/// Creates duration selection submenu for time-based penalties (ban, mute, gag, etc.).
///
/// The admin player selecting duration.
/// The target player for the penalty.
/// The name of the penalty action.
/// Callback action executed when duration is selected.
/// A MenuBuilder instance for the duration menu.
private static MenuBuilder CreateDurationMenu(CCSPlayerController admin, CCSPlayerController player, string actionName,
Action onSelectAction)
{
var durationMenu = new MenuBuilder($"{actionName} Duration: {player.PlayerName}");
foreach (var durationItem in CS2_SimpleAdmin.Instance.Config.MenuConfigs.Durations)
{
durationMenu.AddOption(durationItem.Name, _ =>
{
onSelectAction(admin, player, durationItem.Duration);
});
}
return durationMenu.WithBackButton();
}
///
/// Creates reason selection submenu for penalties with predefined reasons from configuration.
///
/// The admin player selecting reason.
/// The target player for the penalty.
/// The name of the penalty action.
/// The type of penalty to determine which reason list to use.
/// Callback action executed when reason is selected.
/// A MenuBuilder instance for the reason menu.
private static MenuBuilder CreateReasonMenu(CCSPlayerController admin, CCSPlayerController player, string actionName,
PenaltyType penaltyType, Action onSelectAction)
{
var reasonMenu = new MenuBuilder($"{actionName} Reason: {player.PlayerName}");
var reasons = penaltyType switch
{
PenaltyType.Ban => CS2_SimpleAdmin.Instance.Config.MenuConfigs.BanReasons,
PenaltyType.Kick => CS2_SimpleAdmin.Instance.Config.MenuConfigs.KickReasons,
PenaltyType.Mute => CS2_SimpleAdmin.Instance.Config.MenuConfigs.MuteReasons,
PenaltyType.Warn => CS2_SimpleAdmin.Instance.Config.MenuConfigs.WarnReasons,
PenaltyType.Gag or PenaltyType.Silence => CS2_SimpleAdmin.Instance.Config.MenuConfigs.MuteReasons,
_ => CS2_SimpleAdmin.Instance.Config.MenuConfigs.BanReasons
};
foreach (var reason in reasons)
{
reasonMenu.AddOption(reason, _ =>
{
onSelectAction(admin, player, reason);
});
}
return reasonMenu.WithBackButton();
}
}