mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-09-27 20:17:04 +02:00
Refactor fun commands to external module
Commented out fun command implementations (noclip, godmode, freeze, unfreeze, resize) in funcommands.cs and removed their registration from RegisterCommands.cs. These commands are now intended to be provided by the new CS2-SimpleAdmin_FunCommands external module, improving modularity and maintainability.
This commit is contained in:
parent
2edacc2b3f
commit
78318102fe
69 changed files with 5943 additions and 1493 deletions
|
|
@ -1,47 +1,57 @@
|
|||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Commands.Targeting;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CS2_SimpleAdmin.Managers;
|
||||
using CS2_SimpleAdmin.Menus;
|
||||
using CS2_SimpleAdminApi;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace CS2_SimpleAdmin.Api;
|
||||
|
||||
public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
|
||||
{
|
||||
public event Action? OnSimpleAdminReady;
|
||||
public void OnSimpleAdminReadyEvent() => OnSimpleAdminReady?.Invoke();
|
||||
|
||||
public PlayerInfo GetPlayerInfo(CCSPlayerController player)
|
||||
{
|
||||
if (!player.UserId.HasValue)
|
||||
throw new KeyNotFoundException("Player with specific UserId not found");
|
||||
|
||||
return CS2_SimpleAdmin.PlayersInfo[player.SteamID];
|
||||
return !player.UserId.HasValue
|
||||
? throw new KeyNotFoundException("Player with specific UserId not found")
|
||||
: CS2_SimpleAdmin.PlayersInfo[player.SteamID];
|
||||
}
|
||||
|
||||
public string GetConnectionString() => CS2_SimpleAdmin.Instance.DbConnectionString;
|
||||
public string GetServerAddress() => CS2_SimpleAdmin.IpAddress;
|
||||
public int? GetServerId() => CS2_SimpleAdmin.ServerId;
|
||||
|
||||
public Dictionary<PenaltyType, List<(DateTime EndDateTime, int Duration, bool Passed)>> GetPlayerMuteStatus(CCSPlayerController player)
|
||||
public string GetConnectionString() => CS2_SimpleAdmin.Instance.DbConnectionString;
|
||||
public string GetServerAddress() => CS2_SimpleAdmin.IpAddress;
|
||||
public int? GetServerId() => CS2_SimpleAdmin.ServerId;
|
||||
|
||||
public Dictionary<PenaltyType, List<(DateTime EndDateTime, int Duration, bool Passed)>> GetPlayerMuteStatus(
|
||||
CCSPlayerController player)
|
||||
{
|
||||
return PlayerPenaltyManager.GetAllPlayerPenalties(player.Slot);
|
||||
}
|
||||
|
||||
|
||||
public event Action<PlayerInfo, PlayerInfo?, PenaltyType, string, int, int?, int?>? OnPlayerPenaltied;
|
||||
public event Action<SteamID, PlayerInfo?, PenaltyType, string, int, int?, int?>? OnPlayerPenaltiedAdded;
|
||||
public event Action<string, string?, bool, object>? OnAdminShowActivity;
|
||||
public event Action<int, bool>? OnAdminToggleSilent;
|
||||
|
||||
public void OnPlayerPenaltiedEvent(PlayerInfo player, PlayerInfo? admin, PenaltyType penaltyType, string reason,
|
||||
int duration, int? penaltyId) => OnPlayerPenaltied?.Invoke(player, admin, penaltyType, reason, duration, penaltyId, CS2_SimpleAdmin.ServerId);
|
||||
|
||||
int duration, int? penaltyId) => OnPlayerPenaltied?.Invoke(player, admin, penaltyType, reason, duration,
|
||||
penaltyId, CS2_SimpleAdmin.ServerId);
|
||||
|
||||
public void OnPlayerPenaltiedAddedEvent(SteamID player, PlayerInfo? admin, PenaltyType penaltyType, string reason,
|
||||
int duration, int? penaltyId) => OnPlayerPenaltiedAdded?.Invoke(player, admin, penaltyType, reason, duration, penaltyId, CS2_SimpleAdmin.ServerId);
|
||||
|
||||
public void OnAdminShowActivityEvent(string messageKey, string? callerName = null, bool dontPublish = false, params object[] messageArgs) => OnAdminShowActivity?.Invoke(messageKey, callerName, dontPublish, messageArgs);
|
||||
int duration, int? penaltyId) => OnPlayerPenaltiedAdded?.Invoke(player, admin, penaltyType, reason, duration,
|
||||
penaltyId, CS2_SimpleAdmin.ServerId);
|
||||
|
||||
public void OnAdminToggleSilentEvent(int slot, bool status) => OnAdminToggleSilent?.Invoke(slot, status);
|
||||
public void OnAdminShowActivityEvent(string messageKey, string? callerName = null, bool dontPublish = false,
|
||||
params object[] messageArgs) => OnAdminShowActivity?.Invoke(messageKey, callerName, dontPublish, messageArgs);
|
||||
|
||||
public void IssuePenalty(CCSPlayerController player, CCSPlayerController? admin, PenaltyType penaltyType, string reason, int duration = -1)
|
||||
public void OnAdminToggleSilentEvent(int slot, bool status) => OnAdminToggleSilent?.Invoke(slot, status);
|
||||
|
||||
public void IssuePenalty(CCSPlayerController player, CCSPlayerController? admin, PenaltyType penaltyType,
|
||||
string reason, int duration = -1)
|
||||
{
|
||||
switch (penaltyType)
|
||||
{
|
||||
|
|
@ -79,8 +89,9 @@ public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
|
|||
throw new ArgumentOutOfRangeException(nameof(penaltyType), penaltyType, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void IssuePenalty(SteamID steamid, CCSPlayerController? admin, PenaltyType penaltyType, string reason, int duration = -1)
|
||||
|
||||
public void IssuePenalty(SteamID steamid, CCSPlayerController? admin, PenaltyType penaltyType, string reason,
|
||||
int duration = -1)
|
||||
{
|
||||
switch (penaltyType)
|
||||
{
|
||||
|
|
@ -123,12 +134,12 @@ public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
|
|||
{
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
|
||||
public bool IsAdminSilent(CCSPlayerController player)
|
||||
{
|
||||
return CS2_SimpleAdmin.SilentPlayers.Contains(player.Slot);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public HashSet<int> ListSilentAdminsSlots()
|
||||
{
|
||||
return CS2_SimpleAdmin.SilentPlayers;
|
||||
|
|
@ -147,7 +158,7 @@ public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
|
|||
list = new List<CommandDefinition>();
|
||||
RegisterCommands._commandDefinitions[name] = list;
|
||||
}
|
||||
|
||||
|
||||
list.Add(definition);
|
||||
}
|
||||
|
||||
|
|
@ -162,9 +173,145 @@ public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
|
|||
CS2_SimpleAdmin.Instance.RemoveCommand(commandName, definition.Callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowAdminActivity(string messageKey, string? callerName = null, bool dontPublish = false, params object[] messageArgs)
|
||||
|
||||
public TargetResult? GetTarget(CommandInfo command)
|
||||
{
|
||||
return CS2_SimpleAdmin.GetTarget(command);
|
||||
}
|
||||
|
||||
public void ShowAdminActivity(string messageKey, string? callerName = null, bool dontPublish = false,
|
||||
params object[] messageArgs)
|
||||
{
|
||||
Helper.ShowAdminActivity(messageKey, callerName, dontPublish, messageArgs);
|
||||
}
|
||||
|
||||
public void ShowAdminActivityTranslated(string translatedMessage, string? callerName = null,
|
||||
bool dontPublish = false)
|
||||
{
|
||||
Helper.ShowAdminActivityTranslated(translatedMessage, callerName, dontPublish);
|
||||
}
|
||||
|
||||
public void ShowAdminActivityLocalized(object moduleLocalizer, string messageKey, string? callerName = null,
|
||||
bool dontPublish = false, params object[] messageArgs)
|
||||
{
|
||||
if (moduleLocalizer is not IStringLocalizer localizer)
|
||||
throw new InvalidOperationException("moduleLocalizer must be an IStringLocalizer instance");
|
||||
|
||||
Helper.ShowAdminActivityLocalized(localizer, messageKey, callerName, dontPublish, messageArgs);
|
||||
}
|
||||
|
||||
public void RegisterMenuCategory(string categoryId, string categoryName, string permission = "@css/generic")
|
||||
{
|
||||
Menus.MenuManager.Instance.RegisterCategory(categoryId, categoryName, permission);
|
||||
}
|
||||
|
||||
public void RegisterMenu(string categoryId, string menuId, string menuName,
|
||||
Func<CCSPlayerController, object> menuFactory, string? permission = null)
|
||||
{
|
||||
Menus.MenuManager.Instance.RegisterMenu(categoryId, menuId, menuName, BuilderFactory, permission);
|
||||
return;
|
||||
|
||||
MenuBuilder BuilderFactory(CCSPlayerController player)
|
||||
{
|
||||
if (menuFactory(player) is not MenuBuilder menuBuilder)
|
||||
throw new InvalidOperationException("Menu factory must return MenuBuilder");
|
||||
|
||||
// Dodaj automatyczną obsługę przycisku 'Wróć'
|
||||
menuBuilder.WithBackAction(p =>
|
||||
{
|
||||
if (Menus.MenuManager.Instance.GetMenuCategories().TryGetValue(categoryId, out var category))
|
||||
{
|
||||
Menus.MenuManager.Instance.CreateCategoryMenuPublic(category, p).OpenMenu(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
Menus.MenuManager.Instance.OpenMainMenu(p);
|
||||
}
|
||||
});
|
||||
|
||||
return menuBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void UnregisterMenu(string categoryId, string menuId)
|
||||
{
|
||||
Menus.MenuManager.Instance.UnregisterMenu(categoryId, menuId);
|
||||
}
|
||||
|
||||
public object CreateMenuWithBack(string title, string categoryId, CCSPlayerController player)
|
||||
{
|
||||
var builder = new MenuBuilder(title);
|
||||
builder.WithBackAction(p =>
|
||||
{
|
||||
if (Menus.MenuManager.Instance.GetMenuCategories().TryGetValue(categoryId, out var category))
|
||||
{
|
||||
Menus.MenuManager.Instance.CreateCategoryMenuPublic(category, p).OpenMenu(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
Menus.MenuManager.Instance.OpenMainMenu(p);
|
||||
}
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public List<CCSPlayerController> GetValidPlayers()
|
||||
{
|
||||
return Helper.GetValidPlayers();
|
||||
}
|
||||
|
||||
public object CreateMenuWithPlayers(string title, string categoryId, CCSPlayerController admin,
|
||||
Func<CCSPlayerController, bool> filter, Action<CCSPlayerController, CCSPlayerController> onSelect)
|
||||
{
|
||||
var menu = (MenuBuilder)CreateMenuWithBack(title, categoryId, admin);
|
||||
var players = Helper.GetValidPlayers().Where(filter);
|
||||
|
||||
foreach (var player in players)
|
||||
{
|
||||
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
|
||||
menu.AddOption(playerName, _ =>
|
||||
{
|
||||
if (player.IsValid)
|
||||
{
|
||||
onSelect(admin, player);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public void AddMenuOption(object menu, string name, Action<CCSPlayerController> action, bool disabled = false,
|
||||
string? permission = null)
|
||||
{
|
||||
if (menu is not MenuBuilder menuBuilder)
|
||||
throw new InvalidOperationException("Menu must be a MenuBuilder instance");
|
||||
|
||||
menuBuilder.AddOption(name, action, disabled, permission);
|
||||
}
|
||||
|
||||
public void AddSubMenu(object menu, string name, Func<CCSPlayerController, object> subMenuFactory,
|
||||
bool disabled = false, string? permission = null)
|
||||
{
|
||||
if (menu is not MenuBuilder menuBuilder)
|
||||
throw new InvalidOperationException("Menu must be a MenuBuilder instance");
|
||||
|
||||
menuBuilder.AddSubMenu(name, player =>
|
||||
{
|
||||
var subMenu = subMenuFactory(player);
|
||||
if (subMenu is not MenuBuilder builder)
|
||||
throw new InvalidOperationException("SubMenu factory must return MenuBuilder");
|
||||
return builder;
|
||||
}, disabled, permission);
|
||||
}
|
||||
|
||||
public void OpenMenu(object menu, CCSPlayerController player)
|
||||
{
|
||||
if (menu is not MenuBuilder menuBuilder)
|
||||
throw new InvalidOperationException("Menu must be a MenuBuilder instance");
|
||||
|
||||
menuBuilder.OpenMenu(player);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Reflection;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Core.Capabilities;
|
||||
|
|
@ -8,6 +7,7 @@ using CounterStrikeSharp.API.Modules.Commands.Targeting;
|
|||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CS2_SimpleAdmin.Database;
|
||||
using CS2_SimpleAdmin.Managers;
|
||||
using CS2_SimpleAdmin.Menus;
|
||||
using CS2_SimpleAdminApi;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MySqlConnector;
|
||||
|
|
@ -22,7 +22,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
|
|||
public override string ModuleName => "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)");
|
||||
public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)";
|
||||
public override string ModuleAuthor => "daffyy & Dliix66";
|
||||
public override string ModuleVersion => "1.7.7-alpha-10";
|
||||
public override string ModuleVersion => "1.7.8-beta-1";
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
|
|
@ -67,6 +67,9 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
|
|||
PlayersTimer?.Kill();
|
||||
PlayersTimer = null;
|
||||
PlayerManager.CheckPlayersTimer();
|
||||
|
||||
Menus.MenuManager.Instance.InitializeDefaultCategories();
|
||||
BasicMenu.Initialize();
|
||||
}
|
||||
|
||||
public override void OnAllPluginsLoaded(bool hotReload)
|
||||
|
|
@ -83,7 +86,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
|
|||
|
||||
AddTimer(6.0f, () => ReloadAdmins(null));
|
||||
RegisterEvents();
|
||||
RegisterCommands.InitializeCommands();
|
||||
AddTimer(0.5f, RegisterCommands.InitializeCommands);
|
||||
|
||||
if (!CoreConfig.UnlockConCommands)
|
||||
{
|
||||
|
|
@ -232,7 +235,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
|
|||
WarnManager = new WarnManager(DatabaseProvider);
|
||||
}
|
||||
|
||||
private static TargetResult? GetTarget(CommandInfo command, int argument = 1)
|
||||
internal static TargetResult? GetTarget(CommandInfo command, int argument = 1)
|
||||
{
|
||||
var matches = command.GetArgTargetResult(argument);
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@
|
|||
<None Update="Database\Migrations\Mysql\015_steamidToBigInt.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Database\Migrations\Mysql\016_OptimizeTablesAndIndexes.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Database\Migrations\Sqlite\001_CreateTables.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -126,6 +129,9 @@
|
|||
<None Update="Database\Migrations\Sqlite\015_steamidToBigInt.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Database\Migrations\Sqlite\016_OptimizeTablesAndIndexes.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -65,24 +65,11 @@ public static class RegisterCommands
|
|||
|
||||
new("css_vote", CS2_SimpleAdmin.Instance.OnVoteCommand),
|
||||
|
||||
new("css_noclip", CS2_SimpleAdmin.Instance.OnNoclipCommand),
|
||||
new("css_freeze", CS2_SimpleAdmin.Instance.OnFreezeCommand),
|
||||
new("css_unfreeze", CS2_SimpleAdmin.Instance.OnUnfreezeCommand),
|
||||
new("css_godmode", CS2_SimpleAdmin.Instance.OnGodCommand),
|
||||
|
||||
new("css_slay", CS2_SimpleAdmin.Instance.OnSlayCommand),
|
||||
new("css_slap", CS2_SimpleAdmin.Instance.OnSlapCommand),
|
||||
new("css_give", CS2_SimpleAdmin.Instance.OnGiveCommand),
|
||||
new("css_strip", CS2_SimpleAdmin.Instance.OnStripCommand),
|
||||
new("css_hp", CS2_SimpleAdmin.Instance.OnHpCommand),
|
||||
new("css_speed", CS2_SimpleAdmin.Instance.OnSpeedCommand),
|
||||
new("css_gravity", CS2_SimpleAdmin.Instance.OnGravityCommand),
|
||||
new("css_resize", CS2_SimpleAdmin.Instance.OnResizeCommand),
|
||||
new("css_money", CS2_SimpleAdmin.Instance.OnMoneyCommand),
|
||||
new("css_team", CS2_SimpleAdmin.Instance.OnTeamCommand),
|
||||
new("css_rename", CS2_SimpleAdmin.Instance.OnRenameCommand),
|
||||
new("css_prename", CS2_SimpleAdmin.Instance.OnPrenameCommand),
|
||||
new("css_respawn", CS2_SimpleAdmin.Instance.OnRespawnCommand),
|
||||
new("css_tp", CS2_SimpleAdmin.Instance.OnGotoCommand),
|
||||
new("css_bring", CS2_SimpleAdmin.Instance.OnBringCommand),
|
||||
new("css_pluginsmanager", CS2_SimpleAdmin.Instance.OnPluginManagerCommand),
|
||||
|
|
@ -160,23 +147,12 @@ public static class RegisterCommands
|
|||
{ "css_addsilence", new Command { Aliases = ["css_addsilence"] } },
|
||||
{ "css_unsilence", new Command { Aliases = ["css_unsilence"] } },
|
||||
{ "css_vote", new Command { Aliases = ["css_vote"] } },
|
||||
{ "css_noclip", new Command { Aliases = ["css_noclip"] } },
|
||||
{ "css_freeze", new Command { Aliases = ["css_freeze"] } },
|
||||
{ "css_unfreeze", new Command { Aliases = ["css_unfreeze"] } },
|
||||
{ "css_godmode", new Command { Aliases = ["css_godmode"] } },
|
||||
{ "css_slay", new Command { Aliases = ["css_slay"] } },
|
||||
{ "css_slap", new Command { Aliases = ["css_slap"] } },
|
||||
{ "css_give", new Command { Aliases = ["css_give"] } },
|
||||
{ "css_strip", new Command { Aliases = ["css_strip"] } },
|
||||
{ "css_hp", new Command { Aliases = ["css_hp"] } },
|
||||
{ "css_speed", new Command { Aliases = ["css_speed"] } },
|
||||
{ "css_gravity", new Command { Aliases = ["css_gravity"] } },
|
||||
{ "css_resize", new Command { Aliases = ["css_resize", "css_size"] } },
|
||||
{ "css_money", new Command { Aliases = ["css_money"] } },
|
||||
{ "css_team", new Command { Aliases = ["css_team"] } },
|
||||
{ "css_rename", new Command { Aliases = ["css_rename"] } },
|
||||
{ "css_prename", new Command { Aliases = ["css_prename"] } },
|
||||
{ "css_respawn", new Command { Aliases = ["css_respawn"] } },
|
||||
{ "css_resize", new Command { Aliases = ["css_resize", "css_size"] } },
|
||||
{ "css_tp", new Command { Aliases = ["css_tp", "css_tpto", "css_goto"] } },
|
||||
{ "css_bring", new Command { Aliases = ["css_bring", "css_tphere"] } },
|
||||
{ "css_pluginsmanager", new Command { Aliases = ["css_pluginsmanager", "css_pluginmanager"] } },
|
||||
|
|
@ -205,25 +181,26 @@ public static class RegisterCommands
|
|||
var commandsConfig = JsonSerializer.Deserialize<CommandsConfig>(json,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
|
||||
if (commandsConfig?.Commands == null) return;
|
||||
|
||||
foreach (var command in commandsConfig.Commands)
|
||||
if (commandsConfig?.Commands != null)
|
||||
{
|
||||
if (command.Value.Aliases == null) continue;
|
||||
|
||||
CS2_SimpleAdmin._logger?.LogInformation(
|
||||
$"Registering command: `{command.Key}` with aliases: `{string.Join(", ", command.Value.Aliases)}`");
|
||||
|
||||
var mapping = CommandMappings.FirstOrDefault(m => m.CommandKey == command.Key);
|
||||
if (mapping == null || command.Value.Aliases.Length == 0) continue;
|
||||
|
||||
foreach (var alias in command.Value.Aliases)
|
||||
foreach (var command in commandsConfig.Commands)
|
||||
{
|
||||
CS2_SimpleAdmin.Instance.AddCommand(alias, "", mapping.Callback);
|
||||
if (command.Value.Aliases == null) continue;
|
||||
|
||||
CS2_SimpleAdmin._logger?.LogInformation(
|
||||
$"Registering command: `{command.Key}` with aliases: `{string.Join(", ", command.Value.Aliases)}`");
|
||||
|
||||
var mapping = CommandMappings.FirstOrDefault(m => m.CommandKey == command.Key);
|
||||
if (mapping == null || command.Value.Aliases.Length == 0) continue;
|
||||
|
||||
foreach (var alias in command.Value.Aliases)
|
||||
{
|
||||
CS2_SimpleAdmin.Instance.AddCommand(alias, "", mapping.Callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (name, definitions) in RegisterCommands._commandDefinitions)
|
||||
foreach (var (name, definitions) in _commandDefinitions)
|
||||
{
|
||||
foreach (var definition in definitions)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
var canPermBan = AdminManager.PlayerHasPermissions(new SteamID(caller.SteamID), "@css/permban");
|
||||
|
||||
if (duration <= 0 && canPermBan == false)
|
||||
if (duration <= 0 && !canPermBan)
|
||||
{
|
||||
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_perm_restricted"]}");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public partial class CS2_SimpleAdmin
|
|||
[CommandHelper(usage: "[#userid or name]", whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnPenaltiesCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (caller == null || caller.IsValid == false || !caller.UserId.HasValue || DatabaseProvider == null)
|
||||
if (caller == null || !caller.IsValid || !caller.UserId.HasValue || DatabaseProvider == null)
|
||||
return;
|
||||
|
||||
var userId = caller.UserId.Value;
|
||||
|
|
@ -160,7 +160,7 @@ public partial class CS2_SimpleAdmin
|
|||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnAdminVoiceCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (caller == null || caller.IsValid == false)
|
||||
if (caller == null || !caller.IsValid)
|
||||
return;
|
||||
|
||||
if (command.ArgCount > 1)
|
||||
|
|
@ -205,7 +205,7 @@ public partial class CS2_SimpleAdmin
|
|||
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)]
|
||||
public void OnAdminCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
if (caller == null || caller.IsValid == false)
|
||||
if (caller == null || !caller.IsValid)
|
||||
return;
|
||||
|
||||
AdminMenu.OpenMenu(caller);
|
||||
|
|
|
|||
|
|
@ -959,7 +959,7 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
var canPermMute = AdminManager.PlayerHasPermissions(new SteamID(caller.SteamID), "@css/permmute");
|
||||
|
||||
if (duration <= 0 && canPermMute == false)
|
||||
if (duration <= 0 && !canPermMute)
|
||||
{
|
||||
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_perm_restricted"]}");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,307 +1,307 @@
|
|||
using System.Globalization;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
|
||||
namespace CS2_SimpleAdmin;
|
||||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables or disables no-clip mode for specified player(s).
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command input containing targets.</param>
|
||||
[CommandHelper(1, "<#userid or name>")]
|
||||
[RequiresPermissions("@css/cheats")]
|
||||
public void OnNoclipCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
var playersToTarget = targets.Players.Where(player =>
|
||||
player.IsValid &&
|
||||
player is { IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
NoClip(caller, player, callerName);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles no-clip mode for a player and shows admin activity messages.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin toggling no-clip.</param>
|
||||
/// <param name="player">The target player whose no-clip state changes.</param>
|
||||
/// <param name="callerName">Optional caller name for messages.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void NoClip(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Toggle no-clip mode for the player
|
||||
player.Pawn.Value?.ToggleNoclip();
|
||||
|
||||
// Determine message keys and arguments for the no-clip notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_noclip_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_noclip {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables god mode for specified player(s).
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the command.</param>
|
||||
/// <param name="command">The command input containing targets.</param>
|
||||
|
||||
[RequiresPermissions("@css/cheats")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnGodCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is {IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return;
|
||||
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
God(caller, player, command);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles god mode for a player and notifies admins.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin toggling god mode.</param>
|
||||
/// <param name="player">The target player whose god mode changes.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void God(CCSPlayerController? caller, CCSPlayerController player, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Toggle god mode for the player
|
||||
if (!GodPlayers.Add(player.Slot))
|
||||
{
|
||||
GodPlayers.Remove(player.Slot);
|
||||
}
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_god {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
|
||||
// Determine message key and arguments for the god mode notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_god_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Freezes target player(s) for an optional specified duration.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the freeze command.</param>
|
||||
/// <param name="command">The command input containing targets and duration.</param>
|
||||
[CommandHelper(1, "<#userid or name> [duration]")]
|
||||
[RequiresPermissions("@css/slay")]
|
||||
public void OnFreezeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
int.TryParse(command.GetArg(2), out var time);
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
Freeze(caller, player, time, callerName, command);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resizes the target player(s) models to a specified scale.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the resize command.</param>
|
||||
/// <param name="command">The command input containing targets and scale factor.</param>
|
||||
[CommandHelper(1, "<#userid or name> [size]")]
|
||||
[RequiresPermissions("@css/slay")]
|
||||
public void OnResizeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var size);
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (!caller!.CanTarget(player)) return;
|
||||
|
||||
var sceneNode = player.PlayerPawn.Value!.CBodyComponent?.SceneNode;
|
||||
if (sceneNode == null) return;
|
||||
|
||||
sceneNode.GetSkeletonInstance().Scale = size;
|
||||
player.PlayerPawn.Value.AcceptInput("SetScale", null, null, size.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
Server.NextWorldUpdate(() =>
|
||||
{
|
||||
Utilities.SetStateChanged(player.PlayerPawn.Value, "CBaseEntity", "m_CBodyComponent");
|
||||
});
|
||||
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_resize_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Freezes a single player and optionally schedules automatic unfreeze after a duration.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin freezing the player.</param>
|
||||
/// <param name="player">The player to freeze.</param>
|
||||
/// <param name="time">Duration of freeze in seconds.</param>
|
||||
/// <param name="callerName">Optional name for notifications.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void Freeze(CCSPlayerController? caller, CCSPlayerController player, int time, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Freeze player pawn
|
||||
player.Pawn.Value?.Freeze();
|
||||
|
||||
// Determine message keys and arguments for the freeze notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_freeze_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
|
||||
// Schedule unfreeze for the player if time is specified
|
||||
if (time > 0)
|
||||
{
|
||||
Instance.AddTimer(time, () => player.Pawn.Value?.Unfreeze(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
}
|
||||
|
||||
// Log the command and send Discord notification
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_freeze {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unfreezes target player(s).
|
||||
/// </summary>
|
||||
/// <param name="caller">The player issuing the unfreeze command.</param>
|
||||
/// <param name="command">The command input with targets.</param>
|
||||
[CommandHelper(1, "<#userid or name>")]
|
||||
[RequiresPermissions("@css/slay")]
|
||||
public void OnUnfreezeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
Unfreeze(caller, player, callerName, command);
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unfreezes a single player and notifies admins.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin unfreezing the player.</param>
|
||||
/// <param name="player">The player to unfreeze.</param>
|
||||
/// <param name="callerName">Optional name for notifications.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void Unfreeze(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Unfreeze player pawn
|
||||
player.Pawn.Value?.Unfreeze();
|
||||
|
||||
// Determine message keys and arguments for the unfreeze notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_unfreeze_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
|
||||
// Log the command and send Discord notification
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_unfreeze {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
}
|
||||
}
|
||||
// using System.Globalization;
|
||||
// using CounterStrikeSharp.API;
|
||||
// using CounterStrikeSharp.API.Core;
|
||||
// using CounterStrikeSharp.API.Modules.Admin;
|
||||
// using CounterStrikeSharp.API.Modules.Commands;
|
||||
//
|
||||
// namespace CS2_SimpleAdmin;
|
||||
//
|
||||
// public partial class CS2_SimpleAdmin
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// Enables or disables no-clip mode for specified player(s).
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player issuing the command.</param>
|
||||
// /// <param name="command">The command input containing targets.</param>
|
||||
// [CommandHelper(1, "<#userid or name>")]
|
||||
// [RequiresPermissions("@css/cheats")]
|
||||
// public void OnNoclipCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
// {
|
||||
// var callerName = caller == null ? _localizer?["sa_console"] ?? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
//
|
||||
// var targets = GetTarget(command);
|
||||
// if (targets == null) return;
|
||||
// var playersToTarget = targets.Players.Where(player =>
|
||||
// player.IsValid &&
|
||||
// player is { IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
//
|
||||
// playersToTarget.ForEach(player =>
|
||||
// {
|
||||
// if (caller!.CanTarget(player))
|
||||
// {
|
||||
// NoClip(caller, player, callerName);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// Helper.LogCommand(caller, command);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Toggles no-clip mode for a player and shows admin activity messages.
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player/admin toggling no-clip.</param>
|
||||
// /// <param name="player">The target player whose no-clip state changes.</param>
|
||||
// /// <param name="callerName">Optional caller name for messages.</param>
|
||||
// /// <param name="command">Optional command info for logging.</param>
|
||||
// internal static void NoClip(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
// {
|
||||
// if (!player.IsValid) return;
|
||||
// if (!caller.CanTarget(player)) return;
|
||||
//
|
||||
// // Set default caller name if not provided
|
||||
// callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
//
|
||||
// // Toggle no-clip mode for the player
|
||||
// player.Pawn.Value?.ToggleNoclip();
|
||||
//
|
||||
// // Determine message keys and arguments for the no-clip notification
|
||||
// var (activityMessageKey, adminActivityArgs) =
|
||||
// ("sa_admin_noclip_message",
|
||||
// new object[] { "CALLER", player.PlayerName });
|
||||
//
|
||||
// // Display admin activity message to other players
|
||||
// if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
// {
|
||||
// Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
// }
|
||||
//
|
||||
// // Log the command
|
||||
// if (command == null)
|
||||
// Helper.LogCommand(caller, $"css_noclip {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Enables or disables god mode for specified player(s).
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player issuing the command.</param>
|
||||
// /// <param name="command">The command input containing targets.</param>
|
||||
//
|
||||
// [RequiresPermissions("@css/cheats")]
|
||||
// [CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
// public void OnGodCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
// {
|
||||
// var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
// var targets = GetTarget(command);
|
||||
// if (targets == null) return;
|
||||
//
|
||||
// var playersToTarget = targets.Players.Where(player => player.IsValid && player is {IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
//
|
||||
// playersToTarget.ForEach(player =>
|
||||
// {
|
||||
// if (player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
// return;
|
||||
//
|
||||
// if (caller!.CanTarget(player))
|
||||
// {
|
||||
// God(caller, player, command);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// Helper.LogCommand(caller, command);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Toggles god mode for a player and notifies admins.
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player/admin toggling god mode.</param>
|
||||
// /// <param name="player">The target player whose god mode changes.</param>
|
||||
// /// <param name="command">Optional command info for logging.</param>
|
||||
// internal static void God(CCSPlayerController? caller, CCSPlayerController player, CommandInfo? command = null)
|
||||
// {
|
||||
// if (!caller.CanTarget(player)) return;
|
||||
//
|
||||
// // Set default caller name if not provided
|
||||
// var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
//
|
||||
// // Toggle god mode for the player
|
||||
// if (!GodPlayers.Add(player.Slot))
|
||||
// {
|
||||
// GodPlayers.Remove(player.Slot);
|
||||
// }
|
||||
//
|
||||
// // Log the command
|
||||
// if (command == null)
|
||||
// Helper.LogCommand(caller, $"css_god {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
//
|
||||
// // Determine message key and arguments for the god mode notification
|
||||
// var (activityMessageKey, adminActivityArgs) =
|
||||
// ("sa_admin_god_message",
|
||||
// new object[] { "CALLER", player.PlayerName });
|
||||
//
|
||||
// // Display admin activity message to other players
|
||||
// if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
// {
|
||||
// Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Freezes target player(s) for an optional specified duration.
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player issuing the freeze command.</param>
|
||||
// /// <param name="command">The command input containing targets and duration.</param>
|
||||
// [CommandHelper(1, "<#userid or name> [duration]")]
|
||||
// [RequiresPermissions("@css/slay")]
|
||||
// public void OnFreezeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
// {
|
||||
// var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
// int.TryParse(command.GetArg(2), out var time);
|
||||
//
|
||||
// var targets = GetTarget(command);
|
||||
// if (targets == null) return;
|
||||
// var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
//
|
||||
// playersToTarget.ForEach(player =>
|
||||
// {
|
||||
// if (caller!.CanTarget(player))
|
||||
// {
|
||||
// Freeze(caller, player, time, callerName, command);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// Helper.LogCommand(caller, command);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Resizes the target player(s) models to a specified scale.
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player issuing the resize command.</param>
|
||||
// /// <param name="command">The command input containing targets and scale factor.</param>
|
||||
// [CommandHelper(1, "<#userid or name> [size]")]
|
||||
// [RequiresPermissions("@css/slay")]
|
||||
// public void OnResizeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
// {
|
||||
// var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
// float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var size);
|
||||
//
|
||||
// var targets = GetTarget(command);
|
||||
// if (targets == null) return;
|
||||
// var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
//
|
||||
// playersToTarget.ForEach(player =>
|
||||
// {
|
||||
// if (!caller!.CanTarget(player)) return;
|
||||
//
|
||||
// var sceneNode = player.PlayerPawn.Value!.CBodyComponent?.SceneNode;
|
||||
// if (sceneNode == null) return;
|
||||
//
|
||||
// sceneNode.GetSkeletonInstance().Scale = size;
|
||||
// player.PlayerPawn.Value.AcceptInput("SetScale", null, null, size.ToString(CultureInfo.InvariantCulture));
|
||||
//
|
||||
// Server.NextWorldUpdate(() =>
|
||||
// {
|
||||
// Utilities.SetStateChanged(player.PlayerPawn.Value, "CBaseEntity", "m_CBodyComponent");
|
||||
// });
|
||||
//
|
||||
// var (activityMessageKey, adminActivityArgs) =
|
||||
// ("sa_admin_resize_message",
|
||||
// new object[] { "CALLER", player.PlayerName });
|
||||
//
|
||||
// // Display admin activity message to other players
|
||||
// if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
// {
|
||||
// Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// Helper.LogCommand(caller, command);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Freezes a single player and optionally schedules automatic unfreeze after a duration.
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player/admin freezing the player.</param>
|
||||
// /// <param name="player">The player to freeze.</param>
|
||||
// /// <param name="time">Duration of freeze in seconds.</param>
|
||||
// /// <param name="callerName">Optional name for notifications.</param>
|
||||
// /// <param name="command">Optional command info for logging.</param>
|
||||
// internal static void Freeze(CCSPlayerController? caller, CCSPlayerController player, int time, string? callerName = null, CommandInfo? command = null)
|
||||
// {
|
||||
// if (!player.IsValid) return;
|
||||
// if (!caller.CanTarget(player)) return;
|
||||
//
|
||||
// // Set default caller name if not provided
|
||||
// callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
//
|
||||
// // Freeze player pawn
|
||||
// player.Pawn.Value?.Freeze();
|
||||
//
|
||||
// // Determine message keys and arguments for the freeze notification
|
||||
// var (activityMessageKey, adminActivityArgs) =
|
||||
// ("sa_admin_freeze_message",
|
||||
// new object[] { "CALLER", player.PlayerName });
|
||||
//
|
||||
// // Display admin activity message to other players
|
||||
// if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
// {
|
||||
// Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
// }
|
||||
//
|
||||
// // Schedule unfreeze for the player if time is specified
|
||||
// if (time > 0)
|
||||
// {
|
||||
// Instance.AddTimer(time, () => player.Pawn.Value?.Unfreeze(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||
// }
|
||||
//
|
||||
// // Log the command and send Discord notification
|
||||
// if (command == null)
|
||||
// Helper.LogCommand(caller, $"css_freeze {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time}");
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Unfreezes target player(s).
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player issuing the unfreeze command.</param>
|
||||
// /// <param name="command">The command input with targets.</param>
|
||||
// [CommandHelper(1, "<#userid or name>")]
|
||||
// [RequiresPermissions("@css/slay")]
|
||||
// public void OnUnfreezeCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
// {
|
||||
// var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
//
|
||||
// var targets = GetTarget(command);
|
||||
// if (targets == null) return;
|
||||
// var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
//
|
||||
// playersToTarget.ForEach(player =>
|
||||
// {
|
||||
// Unfreeze(caller, player, callerName, command);
|
||||
// });
|
||||
//
|
||||
// Helper.LogCommand(caller, command);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Unfreezes a single player and notifies admins.
|
||||
// /// </summary>
|
||||
// /// <param name="caller">The player/admin unfreezing the player.</param>
|
||||
// /// <param name="player">The player to unfreeze.</param>
|
||||
// /// <param name="callerName">Optional name for notifications.</param>
|
||||
// /// <param name="command">Optional command info for logging.</param>
|
||||
// internal static void Unfreeze(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
// {
|
||||
// if (!player.IsValid) return;
|
||||
// if (!caller.CanTarget(player)) return;
|
||||
//
|
||||
// // Set default caller name if not provided
|
||||
// callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
//
|
||||
// // Unfreeze player pawn
|
||||
// player.Pawn.Value?.Unfreeze();
|
||||
//
|
||||
// // Determine message keys and arguments for the unfreeze notification
|
||||
// var (activityMessageKey, adminActivityArgs) =
|
||||
// ("sa_admin_unfreeze_message",
|
||||
// new object[] { "CALLER", player.PlayerName });
|
||||
//
|
||||
// // Display admin activity message to other players
|
||||
// if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
// {
|
||||
// Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
// }
|
||||
//
|
||||
// // Log the command and send Discord notification
|
||||
// if (command == null)
|
||||
// Helper.LogCommand(caller, $"css_unfreeze {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
// }
|
||||
// }
|
||||
|
|
@ -11,9 +11,6 @@ namespace CS2_SimpleAdmin;
|
|||
|
||||
public partial class CS2_SimpleAdmin
|
||||
{
|
||||
internal static readonly Dictionary<CCSPlayerController, float> SpeedPlayers = [];
|
||||
internal static readonly Dictionary<CCSPlayerController, float> GravityPlayers = [];
|
||||
|
||||
/// <summary>
|
||||
/// Executes the 'slay' command, forcing the targeted players to commit suicide.
|
||||
/// Checks player validity and permissions.
|
||||
|
|
@ -72,451 +69,6 @@ public partial class CS2_SimpleAdmin
|
|||
Helper.LogCommand(caller, $"css_slay {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the 'give' command to provide a specified weapon to targeted players.
|
||||
/// Enforces server rules for prohibited weapons.
|
||||
/// </summary>
|
||||
/// <param name="caller">Player or console issuing the command.</param>
|
||||
/// <param name="command">Command details, including targets and weapon name.</param>
|
||||
[RequiresPermissions("@css/cheats")]
|
||||
[CommandHelper(minArgs: 2, usage: "<#userid or name> <weapon>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnGiveCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
var weaponName = command.GetArg(2);
|
||||
|
||||
// check if weapon is knife
|
||||
if (weaponName.Contains("_knife") || weaponName.Contains("bayonet"))
|
||||
{
|
||||
if (CoreConfig.FollowCS2ServerGuidelines)
|
||||
{
|
||||
command.ReplyToCommand($"Cannot Give {weaponName} because it's illegal to be given.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return;
|
||||
|
||||
GiveWeapon(caller, player, weaponName, callerName, command);
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gives a weapon identified by name to a player, handling ambiguous matches and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin issuing the command.</param>
|
||||
/// <param name="player">Target player to receive the weapon.</param>
|
||||
/// <param name="weaponName">Weapon name or partial name.</param>
|
||||
/// <param name="callerName">Optional name to display in notifications.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
private static void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, string weaponName, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
var weapons = WeaponHelper.GetWeaponsByPartialName(weaponName);
|
||||
|
||||
switch (weapons.Count)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case > 1:
|
||||
{
|
||||
var weaponList = string.Join(", ", weapons.Select(w => w.EnumMemberValue));
|
||||
command?.ReplyToCommand($"Found weapons with a similar name: {weaponList}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Give weapon to the player
|
||||
player.GiveNamedItem(weapons.First().EnumValue);
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_giveweapon {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {weaponName}");
|
||||
|
||||
// Determine message keys and arguments for the weapon give notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_give_message",
|
||||
new object[] { "CALLER", player.PlayerName, weaponName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gives a specific weapon to a player, with notifications and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin issuing the command.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="weapon">Weapon item object.</param>
|
||||
/// <param name="callerName">Optional caller name for notifications.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, CsItem weapon, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Give weapon to the player
|
||||
player.GiveNamedItem(weapon);
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_giveweapon {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {weapon.ToString()}");
|
||||
|
||||
// Determine message keys and arguments for the weapon give notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_give_message",
|
||||
new object[] { "CALLER", player.PlayerName, weapon.ToString() });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the 'strip' command, removing all weapons from targeted players.
|
||||
/// Checks player validity and permissions.
|
||||
/// </summary>
|
||||
/// <param name="caller">Player or console issuing the command.</param>
|
||||
/// <param name="command">Command details including targets.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnStripCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
StripWeapons(caller, player, callerName, command);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all weapons from a player, with notifications and logging.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the strip command.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="callerName">Optional caller name.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void StripWeapons(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Check if player is valid, alive, and connected
|
||||
if (!player.IsValid || player.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE || player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return;
|
||||
|
||||
// Strip weapons from the player
|
||||
player.RemoveWeapons();
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_strip {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
|
||||
// Determine message keys and arguments for the weapon strip notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_strip_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets health value on targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the command.</param>
|
||||
/// <param name="command">Command details including targets and health value.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <health>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnHpCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
int.TryParse(command.GetArg(2), out var health);
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
SetHp(caller, player, health, command);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes health of a player and logs the action.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console calling the method.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="health">Health value to set.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void SetHp(CCSPlayerController? caller, CCSPlayerController player, int health, CommandInfo? command = null)
|
||||
{
|
||||
if (!player.IsValid || player.IsHLTV) return;
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Set player's health
|
||||
player.SetHp(health);
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_hp {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {health}");
|
||||
|
||||
// Determine message keys and arguments for the HP set notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_hp_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets movement speed on targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the command.</param>
|
||||
/// <param name="command">Command details including targets and speed.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <speed>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnSpeedCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var speed);
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return;
|
||||
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
SetSpeed(caller, player, speed, command);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes speed of a player and logs the action.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console calling the method.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="speed">Speed value to set.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void SetSpeed(CCSPlayerController? caller, CCSPlayerController player, float speed, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Set player's speed
|
||||
player.SetSpeed(speed);
|
||||
|
||||
if (speed == 1f)
|
||||
SpeedPlayers.Remove(player);
|
||||
else
|
||||
SpeedPlayers[player] = speed;
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_speed {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {speed}");
|
||||
|
||||
// Determine message keys and arguments for the speed set notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_speed_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets gravity on targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console issuing the command.</param>
|
||||
/// <param name="command">Command details including targets and gravity value.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <gravity>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnGravityCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var gravity);
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return;
|
||||
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
SetGravity(caller, player, gravity, command);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes gravity of a player and logs the action.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or console calling the method.</param>
|
||||
/// <param name="player">Target player.</param>
|
||||
/// <param name="gravity">Gravity value to set.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void SetGravity(CCSPlayerController? caller, CCSPlayerController player, float gravity, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Set player's gravity
|
||||
player.SetGravity(gravity);
|
||||
|
||||
if (gravity == 1f)
|
||||
GravityPlayers.Remove(player);
|
||||
else
|
||||
GravityPlayers[player] = gravity;
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_gravity {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {gravity}");
|
||||
|
||||
// Determine message keys and arguments for the gravity set notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_gravity_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the money amount for the targeted players.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin executing the command.</param>
|
||||
/// <param name="command">The command containing target player and money value.</param>
|
||||
[RequiresPermissions("@css/slay")]
|
||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <money>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnMoneyCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
int.TryParse(command.GetArg(2), out var money);
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
|
||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return;
|
||||
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
SetMoney(caller, player, money, command);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies money value to a single targeted player and logs the operation.
|
||||
/// </summary>
|
||||
/// <param name="caller">The player/admin setting the money.</param>
|
||||
/// <param name="player">The player whose money will be set.</param>
|
||||
/// <param name="money">The value of money to set.</param>
|
||||
/// <param name="command">Optional command info for logging.</param>
|
||||
internal static void SetMoney(CCSPlayerController? caller, CCSPlayerController player, int money, CommandInfo? command = null)
|
||||
{
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
||||
|
||||
// Set player's money
|
||||
player.SetMoney(money);
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_money {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {money}");
|
||||
|
||||
// Determine message keys and arguments for the money set notification
|
||||
var (activityMessageKey, adminActivityArgs) =
|
||||
("sa_admin_money_message",
|
||||
new object[] { "CALLER", player.PlayerName });
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
||||
{
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies damage as a slap effect to the targeted players.
|
||||
/// </summary>
|
||||
|
|
@ -802,75 +354,6 @@ public partial class CS2_SimpleAdmin
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Respawns targeted players, restoring their state.
|
||||
/// </summary>
|
||||
/// <param name="caller">The admin or player issuing respawn.</param>
|
||||
/// <param name="command">The command including target players.</param>
|
||||
[CommandHelper(1, "<#userid or name>")]
|
||||
[RequiresPermissions("@css/cheats")]
|
||||
public void OnRespawnCommand(CCSPlayerController? caller, CommandInfo command)
|
||||
{
|
||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
var targets = GetTarget(command);
|
||||
if (targets == null) return;
|
||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
||||
|
||||
playersToTarget.ForEach(player =>
|
||||
{
|
||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return;
|
||||
|
||||
if (caller!.CanTarget(player))
|
||||
{
|
||||
Respawn(caller, player, callerName, command);
|
||||
}
|
||||
});
|
||||
|
||||
Helper.LogCommand(caller, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Respawns a specified player and updates admin notifications.
|
||||
/// </summary>
|
||||
/// <param name="caller">Admin or player executing respawn.</param>
|
||||
/// <param name="player">Player to respawn.</param>
|
||||
/// <param name="callerName">Optional admin name.</param>
|
||||
/// <param name="command">Optional command info.</param>
|
||||
internal static void Respawn(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
||||
{
|
||||
// Check if the caller can target the player
|
||||
if (!caller.CanTarget(player)) return;
|
||||
|
||||
// Set default caller name if not provided
|
||||
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
||||
|
||||
// Ensure the player's pawn is valid before attempting to respawn
|
||||
if (_cBasePlayerControllerSetPawnFunc == null || player.PlayerPawn.Value == null || !player.PlayerPawn.IsValid) return;
|
||||
|
||||
// Perform the respawn operation
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
_cBasePlayerControllerSetPawnFunc.Invoke(player, playerPawn, true, false);
|
||||
VirtualFunction.CreateVoid<CCSPlayerController>(player.Handle, GameData.GetOffset("CCSPlayerController_Respawn"))(player);
|
||||
|
||||
if (player.UserId.HasValue && PlayersInfo.TryGetValue(player.SteamID, out var value) && value.DiePosition != null)
|
||||
playerPawn.Teleport(value.DiePosition?.Position, value.DiePosition?.Angle);
|
||||
|
||||
// Log the command
|
||||
if (command == null)
|
||||
Helper.LogCommand(caller, $"css_respawn {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
||||
|
||||
// Determine message key and arguments for the respawn notification
|
||||
var activityMessageKey = "sa_admin_respawn_message";
|
||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
|
||||
|
||||
// Display admin activity message to other players
|
||||
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
|
||||
|
||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Teleports targeted player(s) to another player's location.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -17,16 +17,27 @@ public class Migration(string migrationsPath)
|
|||
if (files.Count == 0) return;
|
||||
|
||||
await using var connection = await CS2_SimpleAdmin.DatabaseProvider.CreateConnectionAsync();
|
||||
|
||||
await using (var cmd = connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = """
|
||||
CREATE TABLE IF NOT EXISTS sa_migrations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
version TEXT NOT NULL
|
||||
);
|
||||
|
||||
""";
|
||||
if (migrationsPath.Contains("sqlite", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
cmd.CommandText = """
|
||||
CREATE TABLE IF NOT EXISTS sa_migrations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
version TEXT NOT NULL
|
||||
);
|
||||
|
||||
""";
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.CommandText = """
|
||||
CREATE TABLE IF NOT EXISTS sa_migrations (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
version VARCHAR(128) NOT NULL
|
||||
);
|
||||
""";
|
||||
}
|
||||
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ CREATE TABLE IF NOT EXISTS `sa_groups_servers` (
|
|||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
ALTER TABLE `sa_admins` ADD `group_id` INT NULL AFTER `created`;
|
||||
|
||||
ALTER TABLE `sa_groups_flags` ADD FOREIGN KEY (`group_id`) REFERENCES `sa_groups`(`id`) ON DELETE CASCADE;
|
||||
ALTER TABLE `sa_groups_servers` ADD FOREIGN KEY (`group_id`) REFERENCES `sa_groups`(`id`) ON DELETE CASCADE;
|
||||
ALTER TABLE `sa_admins` ADD FOREIGN KEY (`group_id`) REFERENCES `sa_groups`(`id`) ON DELETE SET NULL;
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
CREATE TABLE IF NOT EXISTS `sa_players_ips` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`steamid` bigint(20) NOT NULL,
|
||||
`address` varchar(64) NOT NULL,
|
||||
`used_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `steamid` (`steamid`,`address`)
|
||||
PRIMARY KEY (`steamid`, `address`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
DELETE FROM `sa_players_ips`
|
||||
WHERE `id` NOT IN (
|
||||
SELECT * FROM (
|
||||
SELECT MIN(`id`)
|
||||
FROM `sa_players_ips`
|
||||
GROUP BY `steamid`
|
||||
) AS `keep_ids`
|
||||
);
|
||||
DELETE FROM sa_players_ips WHERE INET_ATON(address) IS NULL AND address IS NOT NULL;
|
||||
UPDATE `sa_players_ips` SET `address` = INET_ATON(address);
|
||||
ALTER TABLE `sa_players_ips` CHANGE `address` `address` INT UNSIGNED NOT NULL;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
-- Migration 016: Optimize tables and indexes
|
||||
-- Add proper indexes for all tables to improve query performance
|
||||
|
||||
-- Optimize sa_players_ips table indexes
|
||||
-- Add index on used_at for efficient date-based queries
|
||||
ALTER TABLE `sa_players_ips` ADD INDEX IF NOT EXISTS `idx_used_at` (`used_at` DESC);
|
||||
|
||||
-- Optimize sa_bans table indexes
|
||||
-- Add composite indexes for common query patterns
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_steamid_status` ON `sa_bans` (`player_steamid`, `status`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_ip_status` ON `sa_bans` (`player_ip`, `status`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_status_ends` ON `sa_bans` (`status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_server_status` ON `sa_bans` (`server_id`, `status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_created` ON `sa_bans` (`created` DESC);
|
||||
|
||||
-- Optimize sa_admins table indexes
|
||||
CREATE INDEX IF NOT EXISTS `idx_admins_steamid` ON `sa_admins` (`player_steamid`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_admins_server_ends` ON `sa_admins` (`server_id`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_admins_ends` ON `sa_admins` (`ends`);
|
||||
|
||||
-- Optimize sa_mutes table indexes (in addition to migration 014)
|
||||
-- Add index for expire queries
|
||||
CREATE INDEX IF NOT EXISTS `idx_mutes_status_ends` ON `sa_mutes` (`status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_mutes_server_status` ON `sa_mutes` (`server_id`, `status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_mutes_created` ON `sa_mutes` (`created` DESC);
|
||||
|
||||
-- Optimize sa_warns table indexes (if exists)
|
||||
CREATE INDEX IF NOT EXISTS `idx_warns_steamid_status` ON `sa_warns` (`player_steamid`, `status`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_warns_status_ends` ON `sa_warns` (`status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_warns_server_status` ON `sa_warns` (`server_id`, `status`, `ends`);
|
||||
|
||||
-- Add index on sa_servers for faster lookups
|
||||
CREATE INDEX IF NOT EXISTS `idx_servers_hostname` ON `sa_servers` (`hostname`);
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
CREATE TABLE IF NOT EXISTS `sa_players_ips` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
`steamid` INTEGER NOT NULL,
|
||||
`address` VARCHAR(64) NOT NULL,
|
||||
`used_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE (`steamid`, `address`)
|
||||
);
|
||||
`used_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`steamid`, `address`)
|
||||
);
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
-- Migration 016: Optimize tables and indexes
|
||||
-- Add proper indexes for all tables to improve query performance
|
||||
|
||||
-- Optimize sa_players_ips table indexes
|
||||
-- Add index on used_at for efficient date-based queries
|
||||
CREATE INDEX IF NOT EXISTS `idx_used_at` ON `sa_players_ips` (`used_at` DESC);
|
||||
|
||||
-- Optimize sa_bans table indexes
|
||||
-- Add composite indexes for common query patterns
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_steamid_status` ON `sa_bans` (`player_steamid`, `status`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_ip_status` ON `sa_bans` (`player_ip`, `status`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_status_ends` ON `sa_bans` (`status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_server_status` ON `sa_bans` (`server_id`, `status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_bans_created` ON `sa_bans` (`created` DESC);
|
||||
|
||||
-- Optimize sa_admins table indexes
|
||||
CREATE INDEX IF NOT EXISTS `idx_admins_steamid` ON `sa_admins` (`player_steamid`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_admins_server_ends` ON `sa_admins` (`server_id`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_admins_ends` ON `sa_admins` (`ends`);
|
||||
|
||||
-- Optimize sa_mutes table indexes (in addition to migration 014)
|
||||
-- Add index for expire queries
|
||||
CREATE INDEX IF NOT EXISTS `idx_mutes_status_ends` ON `sa_mutes` (`status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_mutes_server_status` ON `sa_mutes` (`server_id`, `status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_mutes_created` ON `sa_mutes` (`created` DESC);
|
||||
|
||||
-- Optimize sa_warns table indexes (if exists)
|
||||
CREATE INDEX IF NOT EXISTS `idx_warns_steamid_status` ON `sa_warns` (`player_steamid`, `status`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_warns_status_ends` ON `sa_warns` (`status`, `ends`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_warns_server_status` ON `sa_warns` (`server_id`, `status`, `ends`);
|
||||
|
||||
-- Add index on sa_servers for faster lookups
|
||||
CREATE INDEX IF NOT EXISTS `idx_servers_hostname` ON `sa_servers` (`hostname`);
|
||||
|
|
@ -9,6 +9,15 @@ public class MySqlDatabaseProvider(string connectionString) : IDatabaseProvider
|
|||
{
|
||||
var connection = new MySqlConnection(connectionString);
|
||||
await connection.OpenAsync();
|
||||
|
||||
await using var cmd = connection.CreateCommand();
|
||||
|
||||
cmd.CommandText = "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_general_ci';";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
|
||||
cmd.CommandText = "SET time_zone = '+00:00';";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,9 +96,6 @@ public partial class CS2_SimpleAdmin
|
|||
CachedPlayers.Remove(player);
|
||||
|
||||
SilentPlayers.Remove(player.Slot);
|
||||
GodPlayers.Remove(player.Slot);
|
||||
SpeedPlayers.Remove(player);
|
||||
GravityPlayers.Remove(player);
|
||||
|
||||
if (player.IsBot)
|
||||
return HookResult.Continue;
|
||||
|
|
@ -247,10 +244,6 @@ public partial class CS2_SimpleAdmin
|
|||
Logger.LogCritical("[OnRoundStart]");
|
||||
#endif
|
||||
|
||||
GodPlayers.Clear();
|
||||
SpeedPlayers.Clear();
|
||||
GravityPlayers.Clear();
|
||||
|
||||
foreach (var player in PlayersInfo.Values)
|
||||
{
|
||||
player.DiePosition = null;
|
||||
|
|
@ -467,8 +460,6 @@ public partial class CS2_SimpleAdmin
|
|||
|
||||
GodPlayers.Clear();
|
||||
SilentPlayers.Clear();
|
||||
SpeedPlayers.Clear();
|
||||
GravityPlayers.Clear();
|
||||
|
||||
PlayerPenaltyManager.RemoveAllPenalties();
|
||||
}
|
||||
|
|
@ -494,13 +485,9 @@ public partial class CS2_SimpleAdmin
|
|||
{
|
||||
var player = @event.Userid;
|
||||
|
||||
if (player?.UserId == null || !player.IsValid || player.IsHLTV || player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return HookResult.Continue;
|
||||
|
||||
SpeedPlayers.Remove(player);
|
||||
GravityPlayers.Remove(player);
|
||||
|
||||
if (!PlayersInfo.ContainsKey(player.SteamID) || @event.Attacker == null)
|
||||
if (player?.UserId == null || !player.IsValid || player.IsHLTV ||
|
||||
player.Connected != PlayerConnectedState.PlayerConnected || !PlayersInfo.ContainsKey(player.SteamID) ||
|
||||
@event.Attacker == null)
|
||||
return HookResult.Continue;
|
||||
|
||||
var playerPosition = player.PlayerPawn.Value?.AbsOrigin;
|
||||
|
|
|
|||
|
|
@ -335,10 +335,10 @@ public static class PlayerExtensions
|
|||
{
|
||||
StringBuilder sb = new();
|
||||
sb.Append(localizer[messageKey, messageArgs]);
|
||||
|
||||
|
||||
foreach (var part in Helper.SeparateLines(sb.ToString()))
|
||||
{
|
||||
var lineWithPrefix = localizer["sa_prefix"] + part.Trim();
|
||||
var lineWithPrefix = (CS2_SimpleAdmin._localizer?["sa_prefix"] ?? "") + part.Trim();
|
||||
controller.PrintToChat(lineWithPrefix);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -441,20 +441,20 @@ internal static class Helper
|
|||
public static void ShowAdminActivity(string messageKey, string? callerName = null, bool dontPublish = false, params object[] messageArgs)
|
||||
{
|
||||
string[] publishActions = ["ban", "gag", "silence", "mute"];
|
||||
|
||||
|
||||
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.ShowActivityType == 0) return;
|
||||
if (CS2_SimpleAdmin._localizer == null) return;
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(callerName))
|
||||
callerName = CS2_SimpleAdmin._localizer["sa_console"];
|
||||
|
||||
var formattedMessageArgs = messageArgs.Select(arg => arg.ToString() ?? string.Empty).ToArray();
|
||||
|
||||
if (dontPublish == false && publishActions.Any(messageKey.Contains))
|
||||
|
||||
if (!dontPublish && publishActions.Any(messageKey.Contains))
|
||||
{
|
||||
CS2_SimpleAdmin.SimpleAdminApi?.OnAdminShowActivityEvent(messageKey, callerName, dontPublish, messageArgs);
|
||||
}
|
||||
|
||||
|
||||
// // Replace placeholder based on showActivityType
|
||||
// for (var i = 0; i < formattedMessageArgs.Length; i++)
|
||||
// {
|
||||
|
|
@ -478,7 +478,7 @@ internal static class Helper
|
|||
AdminManager.PlayerHasPermissions(new SteamID(c.SteamID), "@css/kick") ||
|
||||
AdminManager.PlayerHasPermissions(new SteamID(c.SteamID), "@css/ban"));
|
||||
}
|
||||
|
||||
|
||||
foreach (var controller in validPlayers.ToList())
|
||||
{
|
||||
var currentMessageArgs = (string[])formattedMessageArgs.Clone();
|
||||
|
|
@ -499,6 +499,89 @@ internal static class Helper
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows admin activity with a custom translated message (for modules with their own localizer).
|
||||
/// </summary>
|
||||
public static void ShowAdminActivityTranslated(string translatedMessage, string? callerName = null, bool dontPublish = false)
|
||||
{
|
||||
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.ShowActivityType == 0) return;
|
||||
if (CS2_SimpleAdmin._localizer == null) return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(callerName))
|
||||
callerName = CS2_SimpleAdmin._localizer["sa_console"];
|
||||
|
||||
var validPlayers = GetValidPlayers().Where(c => c is { IsValid: true, IsBot: false });
|
||||
|
||||
if (!validPlayers.Any())
|
||||
return;
|
||||
|
||||
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.ShowActivityType == 3)
|
||||
{
|
||||
validPlayers = validPlayers.Where(c =>
|
||||
AdminManager.PlayerHasPermissions(new SteamID(c.SteamID), "@css/kick") ||
|
||||
AdminManager.PlayerHasPermissions(new SteamID(c.SteamID), "@css/ban"));
|
||||
}
|
||||
|
||||
foreach (var controller in validPlayers.ToList())
|
||||
{
|
||||
// Replace "CALLER" placeholder based on showActivityType
|
||||
var message = CS2_SimpleAdmin.Instance.Config.OtherSettings.ShowActivityType switch
|
||||
{
|
||||
1 => translatedMessage.Replace("CALLER", AdminManager.PlayerHasPermissions(new SteamID(controller.SteamID), "@css/kick") || AdminManager.PlayerHasPermissions(new SteamID(controller.SteamID), "@css/ban") ? callerName : CS2_SimpleAdmin._localizer["sa_admin"]),
|
||||
_ => translatedMessage.Replace("CALLER", callerName ?? CS2_SimpleAdmin._localizer["sa_console"]),
|
||||
};
|
||||
|
||||
// Send the pre-translated message to the player
|
||||
controller.PrintToChat(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows admin activity using module's localizer for per-player language support.
|
||||
/// Each player receives the message in their configured language using SendLocalizedMessage.
|
||||
/// </summary>
|
||||
public static void ShowAdminActivityLocalized(IStringLocalizer moduleLocalizer, string messageKey, string? callerName = null, bool dontPublish = false, params object[] messageArgs)
|
||||
{
|
||||
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.ShowActivityType == 0) return;
|
||||
if (CS2_SimpleAdmin._localizer == null) return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(callerName))
|
||||
callerName = CS2_SimpleAdmin._localizer["sa_console"];
|
||||
|
||||
var formattedMessageArgs = messageArgs.Select(arg => arg.ToString() ?? string.Empty).ToArray();
|
||||
|
||||
var validPlayers = GetValidPlayers().Where(c => c is { IsValid: true, IsBot: false });
|
||||
|
||||
if (!validPlayers.Any())
|
||||
return;
|
||||
|
||||
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.ShowActivityType == 3)
|
||||
{
|
||||
validPlayers = validPlayers.Where(c =>
|
||||
AdminManager.PlayerHasPermissions(new SteamID(c.SteamID), "@css/kick") ||
|
||||
AdminManager.PlayerHasPermissions(new SteamID(c.SteamID), "@css/ban"));
|
||||
}
|
||||
|
||||
foreach (var controller in validPlayers.ToList())
|
||||
{
|
||||
var currentMessageArgs = (string[])formattedMessageArgs.Clone();
|
||||
|
||||
// Replace "CALLER" placeholder based on showActivityType
|
||||
for (var i = 0; i < currentMessageArgs.Length; i++)
|
||||
{
|
||||
var arg = currentMessageArgs[i];
|
||||
currentMessageArgs[i] = CS2_SimpleAdmin.Instance.Config.OtherSettings.ShowActivityType switch
|
||||
{
|
||||
1 => arg.Replace("CALLER", AdminManager.PlayerHasPermissions(new SteamID(controller.SteamID), "@css/kick") || AdminManager.PlayerHasPermissions(new SteamID(controller.SteamID), "@css/ban") ? callerName : CS2_SimpleAdmin._localizer["sa_admin"]),
|
||||
_ => arg.Replace("CALLER", callerName ?? CS2_SimpleAdmin._localizer["sa_console"]),
|
||||
};
|
||||
}
|
||||
|
||||
// Send the localized message to each player using their language
|
||||
controller.SendLocalizedMessage(moduleLocalizer, messageKey, currentMessageArgs.Cast<object>().ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisplayCenterMessage(
|
||||
CCSPlayerController player,
|
||||
string messageKey,
|
||||
|
|
@ -794,7 +877,7 @@ internal static class Helper
|
|||
if (CS2_SimpleAdmin.DiscordWebhookClientLog == null || CS2_SimpleAdmin._localizer == null)
|
||||
return;
|
||||
|
||||
if (caller != null && caller.IsValid == false)
|
||||
if (caller != null && !caller.IsValid)
|
||||
caller = null;
|
||||
|
||||
var callerName = caller == null ? CS2_SimpleAdmin._localizer["sa_console"] : caller.PlayerName;
|
||||
|
|
@ -806,32 +889,38 @@ internal static class Helper
|
|||
commandString]));
|
||||
}
|
||||
|
||||
public static IMenu? CreateMenu(string title, Action<CCSPlayerController>? backAction = null)
|
||||
#pragma warning disable CS8604
|
||||
public static IMenu? CreateMenu(string title, Action<CCSPlayerController>? backAction = null, Action<CCSPlayerController>? resetAction = null)
|
||||
{
|
||||
if (CS2_SimpleAdmin.MenuApi == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var menuType = CS2_SimpleAdmin.Instance.Config.MenuConfigs.MenuType.ToLower();
|
||||
|
||||
var menu = menuType switch
|
||||
{
|
||||
_ when menuType.Equals("selectable", StringComparison.CurrentCultureIgnoreCase) =>
|
||||
CS2_SimpleAdmin.MenuApi?.GetMenu(title),
|
||||
CS2_SimpleAdmin.MenuApi.GetMenu(title, backAction, resetAction),
|
||||
|
||||
_ when menuType.Equals("dynamic", StringComparison.CurrentCultureIgnoreCase) =>
|
||||
CS2_SimpleAdmin.MenuApi?.GetMenuForcetype(title, MenuType.ButtonMenu),
|
||||
CS2_SimpleAdmin.MenuApi.GetMenuForcetype(title, MenuType.ButtonMenu, backAction, resetAction),
|
||||
|
||||
_ when menuType.Equals("center", StringComparison.CurrentCultureIgnoreCase) =>
|
||||
CS2_SimpleAdmin.MenuApi?.GetMenuForcetype(title, MenuType.CenterMenu),
|
||||
CS2_SimpleAdmin.MenuApi.GetMenuForcetype(title, MenuType.CenterMenu, backAction, resetAction),
|
||||
|
||||
_ when menuType.Equals("chat", StringComparison.CurrentCultureIgnoreCase) =>
|
||||
CS2_SimpleAdmin.MenuApi?.GetMenuForcetype(title, MenuType.ChatMenu),
|
||||
CS2_SimpleAdmin.MenuApi.GetMenuForcetype(title, MenuType.ChatMenu, backAction, resetAction),
|
||||
|
||||
_ when menuType.Equals("console", StringComparison.CurrentCultureIgnoreCase) =>
|
||||
CS2_SimpleAdmin.MenuApi?.GetMenuForcetype(title, MenuType.ConsoleMenu),
|
||||
CS2_SimpleAdmin.MenuApi.GetMenuForcetype(title, MenuType.ConsoleMenu, backAction, resetAction),
|
||||
|
||||
_ => CS2_SimpleAdmin.MenuApi?.GetMenu(title)
|
||||
_ => CS2_SimpleAdmin.MenuApi.GetMenu(title, backAction, resetAction)
|
||||
};
|
||||
|
||||
return menu;
|
||||
}
|
||||
#pragma warning restore CS8604
|
||||
|
||||
internal static IPluginManager? GetPluginManager()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ internal class BanManager(IDatabaseProvider? databaseProvider)
|
|||
try
|
||||
{
|
||||
var sql = databaseProvider.GetAddBanQuery();
|
||||
|
||||
var banId = await connection.ExecuteScalarAsync<int?>(sql, new
|
||||
{
|
||||
playerSteamid = player.SteamId.SteamId64,
|
||||
|
|
|
|||
|
|
@ -70,39 +70,44 @@ internal class CacheManager: IDisposable
|
|||
|
||||
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.CheckMultiAccountsByIp)
|
||||
{
|
||||
var ipHistory =
|
||||
(await connection.QueryAsync<(ulong steamid, string? name, uint address, DateTime used_at)>(
|
||||
"SELECT steamid, name, address, used_at FROM sa_players_ips ORDER BY used_at DESC")).ToList();
|
||||
|
||||
foreach (var group in ipHistory.AsValueEnumerable().GroupBy(x => x.steamid))
|
||||
{
|
||||
var ipSet = group
|
||||
.GroupBy(x => x.address)
|
||||
.Select(g =>
|
||||
{
|
||||
var latest = g.MaxBy(x => x.used_at);
|
||||
return new IpRecord(
|
||||
g.Key,
|
||||
latest.used_at,
|
||||
string.IsNullOrEmpty(latest.name)
|
||||
? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"
|
||||
: latest.name
|
||||
);
|
||||
})
|
||||
.ToHashSet(new IpRecordComparer());
|
||||
// Optimization: Load IP history and build cache in single pass
|
||||
var ipHistory = await connection.QueryAsync<(ulong steamid, string? name, uint address, DateTime used_at)>(
|
||||
"SELECT steamid, name, address, used_at FROM sa_players_ips ORDER BY steamid, address, used_at DESC");
|
||||
|
||||
_playerIpsCache.AddOrUpdate(
|
||||
group.Key,
|
||||
_ => ipSet,
|
||||
(_, existingSet) =>
|
||||
{
|
||||
foreach (var ip in ipSet)
|
||||
{
|
||||
existingSet.Remove(ip);
|
||||
existingSet.Add(ip);
|
||||
}
|
||||
return existingSet;
|
||||
});
|
||||
var unknownName = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown";
|
||||
var currentSteamId = 0UL;
|
||||
var currentIpSet = new HashSet<IpRecord>(new IpRecordComparer());
|
||||
var latestIpTimestamps = new Dictionary<uint, DateTime>();
|
||||
|
||||
foreach (var record in ipHistory)
|
||||
{
|
||||
// When we encounter a new steamid, save the previous one
|
||||
if (record.steamid != currentSteamId && currentSteamId != 0)
|
||||
{
|
||||
_playerIpsCache[currentSteamId] = currentIpSet;
|
||||
currentIpSet = new HashSet<IpRecord>(new IpRecordComparer());
|
||||
latestIpTimestamps.Clear();
|
||||
}
|
||||
|
||||
currentSteamId = record.steamid;
|
||||
|
||||
// Only keep the latest timestamp for each IP
|
||||
if (!latestIpTimestamps.TryGetValue(record.address, out var existingTimestamp) ||
|
||||
record.used_at > existingTimestamp)
|
||||
{
|
||||
latestIpTimestamps[record.address] = record.used_at;
|
||||
currentIpSet.Add(new IpRecord(
|
||||
record.address,
|
||||
record.used_at,
|
||||
string.IsNullOrEmpty(record.name) ? unknownName : record.name
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Don't forget the last steamid
|
||||
if (currentSteamId != 0)
|
||||
{
|
||||
_playerIpsCache[currentSteamId] = currentIpSet;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -150,8 +155,10 @@ internal class CacheManager: IDisposable
|
|||
{
|
||||
await using var connection = await CS2_SimpleAdmin.DatabaseProvider.CreateConnectionAsync();
|
||||
IEnumerable<BanRecord> updatedBans;
|
||||
|
||||
var allIds = (await connection.QueryAsync<int>("SELECT id FROM sa_bans")).ToHashSet();
|
||||
|
||||
// Optimization: Only get IDs for comparison if we need to check for deletions
|
||||
// Most of the time bans are just added/updated, not deleted
|
||||
HashSet<int>? allIds = null;
|
||||
|
||||
if (CS2_SimpleAdmin.Instance.Config.MultiServerMode)
|
||||
{
|
||||
|
|
@ -161,11 +168,19 @@ internal class CacheManager: IDisposable
|
|||
player_name AS PlayerName,
|
||||
player_steamid AS PlayerSteamId,
|
||||
player_ip AS PlayerIp,
|
||||
status AS Status
|
||||
status AS Status
|
||||
FROM `sa_bans` WHERE updated_at > @lastUpdate OR created > @lastUpdate ORDER BY updated_at DESC
|
||||
""",
|
||||
new { lastUpdate = _lastUpdateTime }
|
||||
));
|
||||
|
||||
// Optimization: Only fetch all IDs if there were updates
|
||||
var updatedList = updatedBans.ToList();
|
||||
if (updatedList.Count > 0)
|
||||
{
|
||||
allIds = (await connection.QueryAsync<int>("SELECT id FROM sa_bans")).ToHashSet();
|
||||
}
|
||||
updatedBans = updatedList;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -175,32 +190,47 @@ internal class CacheManager: IDisposable
|
|||
player_name AS PlayerName,
|
||||
player_steamid AS PlayerSteamId,
|
||||
player_ip AS PlayerIp,
|
||||
status AS Status
|
||||
status AS Status
|
||||
FROM `sa_bans` WHERE (updated_at > @lastUpdate OR created > @lastUpdate) AND server_id = @serverId ORDER BY updated_at DESC
|
||||
""",
|
||||
new { lastUpdate = _lastUpdateTime, serverId = CS2_SimpleAdmin.ServerId }
|
||||
));
|
||||
}
|
||||
|
||||
foreach (var id in _banCache.Keys)
|
||||
{
|
||||
if (allIds.Contains(id) || !_banCache.TryRemove(id, out var ban)) continue;
|
||||
|
||||
if (ban.PlayerSteamId != null &&
|
||||
_steamIdIndex.TryGetValue(ban.PlayerSteamId.Value, out var steamBans))
|
||||
{
|
||||
steamBans.RemoveAll(b => b.Id == id);
|
||||
if (steamBans.Count == 0)
|
||||
_steamIdIndex.TryRemove(ban.PlayerSteamId.Value, out _);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ban.PlayerIp) ||
|
||||
!IpHelper.TryConvertIpToUint(ban.PlayerIp, out var ipUInt) ||
|
||||
!_ipIndex.TryGetValue(ipUInt, out var ipBans)) continue;
|
||||
// Optimization: Only fetch all IDs if there were updates
|
||||
var updatedList = updatedBans.ToList();
|
||||
if (updatedList.Count > 0)
|
||||
{
|
||||
ipBans.RemoveAll(b => b.Id == id);
|
||||
if (ipBans.Count == 0)
|
||||
_ipIndex.TryRemove(ipUInt, out _);
|
||||
allIds = (await connection.QueryAsync<int>(
|
||||
"SELECT id FROM sa_bans WHERE server_id = @serverId",
|
||||
new { serverId = CS2_SimpleAdmin.ServerId }
|
||||
)).ToHashSet();
|
||||
}
|
||||
updatedBans = updatedList;
|
||||
}
|
||||
|
||||
// Optimization: Only process deletions if we have the full ID list
|
||||
if (allIds != null)
|
||||
{
|
||||
foreach (var id in _banCache.Keys)
|
||||
{
|
||||
if (allIds.Contains(id) || !_banCache.TryRemove(id, out var ban)) continue;
|
||||
|
||||
if (ban.PlayerSteamId != null &&
|
||||
_steamIdIndex.TryGetValue(ban.PlayerSteamId.Value, out var steamBans))
|
||||
{
|
||||
steamBans.RemoveAll(b => b.Id == id);
|
||||
if (steamBans.Count == 0)
|
||||
_steamIdIndex.TryRemove(ban.PlayerSteamId.Value, out _);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ban.PlayerIp) ||
|
||||
!IpHelper.TryConvertIpToUint(ban.PlayerIp, out var ipUInt) ||
|
||||
!_ipIndex.TryGetValue(ipUInt, out var ipBans)) continue;
|
||||
{
|
||||
ipBans.RemoveAll(b => b.Id == id);
|
||||
if (ipBans.Count == 0)
|
||||
_ipIndex.TryRemove(ipUInt, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -245,12 +275,21 @@ internal class CacheManager: IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
// Update cache with new/modified bans
|
||||
var hasUpdates = false;
|
||||
foreach (var ban in updatedBans)
|
||||
{
|
||||
_banCache.AddOrUpdate(ban.Id, ban, (_, _) => ban);
|
||||
hasUpdates = true;
|
||||
}
|
||||
|
||||
RebuildIndexes();
|
||||
|
||||
// Always rebuild indexes if there were any updates
|
||||
// This ensures status changes (ACTIVE -> UNBANNED) are reflected
|
||||
if (hasUpdates)
|
||||
{
|
||||
RebuildIndexes();
|
||||
}
|
||||
|
||||
_lastUpdateTime = Time.ActualDateTime().AddSeconds(-1);
|
||||
}
|
||||
catch (Exception)
|
||||
|
|
@ -266,38 +305,38 @@ internal class CacheManager: IDisposable
|
|||
{
|
||||
_steamIdIndex.Clear();
|
||||
_ipIndex.Clear();
|
||||
|
||||
foreach (var ban in _banCache.Values)
|
||||
{
|
||||
if (ban.StatusEnum != BanStatus.ACTIVE)
|
||||
continue;
|
||||
|
||||
if (ban.PlayerSteamId != null)
|
||||
// Optimization: Cache config value to avoid repeated property access
|
||||
var banType = CS2_SimpleAdmin.Instance.Config.OtherSettings.BanType;
|
||||
var checkIpBans = banType != 0;
|
||||
|
||||
// Optimization: Pre-filter only ACTIVE bans to avoid checking status in loop
|
||||
var activeBans = _banCache.Values.Where(b => b.StatusEnum == BanStatus.ACTIVE);
|
||||
|
||||
foreach (var ban in activeBans)
|
||||
{
|
||||
// Index by Steam ID
|
||||
if (ban.PlayerSteamId.HasValue)
|
||||
{
|
||||
var steamId = ban.PlayerSteamId;
|
||||
_steamIdIndex.AddOrUpdate(
|
||||
steamId.Value,
|
||||
key => [ban],
|
||||
(key, list) =>
|
||||
{
|
||||
list.Add(ban);
|
||||
return list;
|
||||
});
|
||||
var steamId = ban.PlayerSteamId.Value;
|
||||
if (!_steamIdIndex.TryGetValue(steamId, out var steamList))
|
||||
{
|
||||
steamList = new List<BanRecord>();
|
||||
_steamIdIndex[steamId] = steamList;
|
||||
}
|
||||
steamList.Add(ban);
|
||||
}
|
||||
|
||||
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.BanType == 0) continue;
|
||||
|
||||
if (ban.PlayerIp != null &&
|
||||
|
||||
// Index by IP (only if IP bans are enabled)
|
||||
if (checkIpBans && !string.IsNullOrEmpty(ban.PlayerIp) &&
|
||||
IpHelper.TryConvertIpToUint(ban.PlayerIp, out var ipUInt))
|
||||
{
|
||||
_ipIndex.AddOrUpdate(
|
||||
ipUInt,
|
||||
key => [ban],
|
||||
(key, list) =>
|
||||
{
|
||||
list.Add(ban);
|
||||
return list;
|
||||
});
|
||||
if (!_ipIndex.TryGetValue(ipUInt, out var ipList))
|
||||
{
|
||||
ipList = new List<BanRecord>();
|
||||
_ipIndex[ipUInt] = ipList;
|
||||
}
|
||||
ipList.Add(ban);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -332,16 +371,16 @@ internal class CacheManager: IDisposable
|
|||
{
|
||||
var ipAsUint = IpHelper.IpToUint(ipAddress);
|
||||
var results = new List<(ulong, DateTime, string)>();
|
||||
var comparer = _playerIpsCache.Comparer;
|
||||
|
||||
// Optimization: Direct lookup using HashSet.Contains instead of TryGetValue
|
||||
var searchRecord = new IpRecord(ipAsUint, default, null!);
|
||||
|
||||
foreach (var (steamId, ipSet) in _playerIpsCache)
|
||||
{
|
||||
if (!ipSet.TryGetValue(new IpRecord(ipAsUint, Time.ActualDateTime(), "Unknown"), out var actualEntry)) continue;
|
||||
results.Add((steamId, actualEntry.UsedAt, actualEntry.PlayerName));
|
||||
|
||||
// Optimization: Single pass through the set
|
||||
foreach (var entry in ipSet)
|
||||
{
|
||||
if (entry.Ip == ipAsUint && !Equals(entry, actualEntry))
|
||||
if (entry.Ip == ipAsUint)
|
||||
{
|
||||
results.Add((steamId, entry.UsedAt, entry.PlayerName));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,66 +95,36 @@ internal class PlayerManager
|
|||
{
|
||||
await using var connection = await CS2_SimpleAdmin.DatabaseProvider.CreateConnectionAsync();
|
||||
|
||||
if (CS2_SimpleAdmin.Instance.CacheManager.HasIpForPlayer(
|
||||
steamId, ipAddress))
|
||||
{
|
||||
const string updateQuery = """
|
||||
UPDATE `sa_players_ips`
|
||||
SET used_at = CURRENT_TIMESTAMP,
|
||||
name = @playerName
|
||||
WHERE steamid = @SteamID AND address = @IPAddress;
|
||||
""";
|
||||
await connection.ExecuteAsync(updateQuery, new
|
||||
{
|
||||
playerName,
|
||||
SteamID = CS2_SimpleAdmin.PlayersInfo[steamId].SteamId.SteamId64,
|
||||
IPAddress = IpHelper.IpToUint(ipAddress)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
const string selectQuery =
|
||||
"SELECT COUNT(*) FROM `sa_players_ips` WHERE steamid = @SteamID AND address = @IPAddress;";
|
||||
var recordExists = await connection.ExecuteScalarAsync<int>(selectQuery, new
|
||||
{
|
||||
SteamID = CS2_SimpleAdmin.PlayersInfo[steamId].SteamId.SteamId64,
|
||||
IPAddress = IpHelper.IpToUint(ipAddress)
|
||||
});
|
||||
// Eliminates the need for SELECT COUNT and duplicate UPDATE queries
|
||||
var steamId64 = CS2_SimpleAdmin.PlayersInfo[steamId].SteamId.SteamId64;
|
||||
var ipUint = IpHelper.IpToUint(ipAddress);
|
||||
|
||||
if (recordExists > 0)
|
||||
{
|
||||
const string updateQuery = """
|
||||
UPDATE `sa_players_ips`
|
||||
SET used_at = CURRENT_TIMESTAMP,
|
||||
name = @playerName
|
||||
WHERE steamid = @SteamID AND address = @IPAddress;
|
||||
""";
|
||||
await connection.ExecuteAsync(updateQuery, new
|
||||
{
|
||||
playerName,
|
||||
SteamID = CS2_SimpleAdmin.PlayersInfo[steamId].SteamId.SteamId64,
|
||||
IPAddress = IpHelper.IpToUint(ipAddress)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
const string insertQuery = """
|
||||
INSERT INTO `sa_players_ips` (steamid, name, address, used_at)
|
||||
VALUES (@SteamID, @playerName, @IPAddress, CURRENT_TIMESTAMP);
|
||||
""";
|
||||
await connection.ExecuteAsync(insertQuery, new
|
||||
{
|
||||
SteamID = CS2_SimpleAdmin.PlayersInfo[steamId].SteamId.SteamId64,
|
||||
playerName,
|
||||
IPAddress = IpHelper.IpToUint(ipAddress)
|
||||
});
|
||||
}
|
||||
}
|
||||
// MySQL: INSERT ... ON DUPLICATE KEY UPDATE pattern
|
||||
const string upsertQuery = """
|
||||
INSERT INTO `sa_players_ips` (steamid, name, address, used_at)
|
||||
VALUES (@SteamID, @playerName, @IPAddress, CURRENT_TIMESTAMP)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
used_at = CURRENT_TIMESTAMP,
|
||||
name = @playerName;
|
||||
""";
|
||||
|
||||
await connection.ExecuteAsync(upsertQuery, new
|
||||
{
|
||||
SteamID = steamId64,
|
||||
playerName,
|
||||
IPAddress = ipUint
|
||||
});
|
||||
|
||||
// // Cache will be updated on next refresh cycle
|
||||
// if (!CS2_SimpleAdmin.Instance.CacheManager.HasIpForPlayer(steamId, ipAddress))
|
||||
// {
|
||||
// // IP association will be reflected after cache refresh
|
||||
// }
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CS2_SimpleAdmin._logger?.LogError(
|
||||
$"Unable to save ip address for {playerInfo.Name} ({ipAddress}) {ex.Message}");
|
||||
$"Unable to save ip address for {playerInfo.Name} ({ipAddress}): {ex.Message}");
|
||||
}
|
||||
|
||||
playerInfo.AccountsAssociated =
|
||||
|
|
@ -313,31 +283,6 @@ internal class PlayerManager
|
|||
/// </remarks>
|
||||
public void CheckPlayersTimer()
|
||||
{
|
||||
CS2_SimpleAdmin.Instance.AddTimer(0.12f, () =>
|
||||
{
|
||||
if (CS2_SimpleAdmin.SpeedPlayers.Count > 0)
|
||||
{
|
||||
foreach (var (player, speed) in CS2_SimpleAdmin.SpeedPlayers)
|
||||
{
|
||||
if (player is { IsValid: true, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE })
|
||||
{
|
||||
player.SetSpeed(speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CS2_SimpleAdmin.GravityPlayers.Count > 0)
|
||||
{
|
||||
foreach (var (player, gravity) in CS2_SimpleAdmin.GravityPlayers)
|
||||
{
|
||||
if (player is { IsValid: true, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE })
|
||||
{
|
||||
player.SetGravity(gravity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, TimerFlags.REPEAT);
|
||||
|
||||
CS2_SimpleAdmin.Instance.PlayersTimer = CS2_SimpleAdmin.Instance.AddTimer(61.0f, () =>
|
||||
{
|
||||
#if DEBUG
|
||||
|
|
@ -346,18 +291,26 @@ internal class PlayerManager
|
|||
if (CS2_SimpleAdmin.DatabaseProvider == null)
|
||||
return;
|
||||
|
||||
var tempPlayers = Helper.GetValidPlayers()
|
||||
.Select(p => new
|
||||
{
|
||||
p.PlayerName, p.SteamID, p.IpAddress, p.UserId, p.Slot,
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// Optimization: Get players once and avoid allocating anonymous types
|
||||
var validPlayers = Helper.GetValidPlayers();
|
||||
if (validPlayers.Count == 0)
|
||||
return;
|
||||
|
||||
// Use ValueTuple instead of anonymous type - better performance and less allocations
|
||||
var tempPlayers = new List<(string PlayerName, ulong SteamID, string? IpAddress, int? UserId, int Slot)>(validPlayers.Count);
|
||||
foreach (var p in validPlayers)
|
||||
{
|
||||
tempPlayers.Add((p.PlayerName, p.SteamID, p.IpAddress, p.UserId, p.Slot));
|
||||
}
|
||||
|
||||
var pluginInstance = CS2_SimpleAdmin.Instance;
|
||||
var config = _config.OtherSettings; // Cache config access
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Run all expire tasks in parallel
|
||||
var expireTasks = new[]
|
||||
{
|
||||
pluginInstance.BanManager.ExpireOldBans(),
|
||||
|
|
@ -384,22 +337,33 @@ internal class PlayerManager
|
|||
|
||||
if (pluginInstance.CacheManager == null)
|
||||
return;
|
||||
|
||||
var bannedPlayers = tempPlayers.AsValueEnumerable()
|
||||
.Where(player =>
|
||||
{
|
||||
var playerName = player.PlayerName;
|
||||
var steamId = player.SteamID;
|
||||
var ip = player.IpAddress?.Split(':')[0];
|
||||
|
||||
return CS2_SimpleAdmin.Instance.Config.OtherSettings.BanType switch
|
||||
{
|
||||
0 => pluginInstance.CacheManager.IsPlayerBanned(playerName, steamId, null),
|
||||
_ => CS2_SimpleAdmin.Instance.Config.OtherSettings.CheckMultiAccountsByIp
|
||||
? pluginInstance.CacheManager.IsPlayerOrAnyIpBanned(playerName, steamId, ip)
|
||||
: pluginInstance.CacheManager.IsPlayerBanned(playerName, steamId, ip)
|
||||
};
|
||||
}).ToList();
|
||||
// Optimization: Cache ban type and multi-account check to avoid repeated config access
|
||||
var banType = config.BanType;
|
||||
var checkMultiAccounts = config.CheckMultiAccountsByIp;
|
||||
|
||||
var bannedPlayers = new List<(string PlayerName, ulong SteamID, string? IpAddress, int? UserId, int Slot)>();
|
||||
|
||||
// Manual loop instead of LINQ - better performance
|
||||
foreach (var player in tempPlayers)
|
||||
{
|
||||
var playerName = player.PlayerName;
|
||||
var steamId = player.SteamID;
|
||||
var ip = player.IpAddress?.Split(':')[0];
|
||||
|
||||
bool isBanned = banType switch
|
||||
{
|
||||
0 => pluginInstance.CacheManager.IsPlayerBanned(playerName, steamId, null),
|
||||
_ => checkMultiAccounts
|
||||
? pluginInstance.CacheManager.IsPlayerOrAnyIpBanned(playerName, steamId, ip)
|
||||
: pluginInstance.CacheManager.IsPlayerBanned(playerName, steamId, ip)
|
||||
};
|
||||
|
||||
if (isBanned)
|
||||
{
|
||||
bannedPlayers.Add(player);
|
||||
}
|
||||
}
|
||||
|
||||
if (bannedPlayers.Count > 0)
|
||||
{
|
||||
|
|
@ -410,32 +374,38 @@ internal class PlayerManager
|
|||
}
|
||||
}
|
||||
|
||||
if (_config.OtherSettings.TimeMode == 0)
|
||||
if (config.TimeMode == 0)
|
||||
{
|
||||
var onlinePlayers = tempPlayers.AsValueEnumerable().Select(player => (player.SteamID, player.UserId, player.Slot)).ToList();
|
||||
if (tempPlayers.Count == 0 || onlinePlayers.Count == 0) return;
|
||||
// Optimization: Manual projection instead of LINQ
|
||||
var onlinePlayers = new List<(ulong, int?, int)>(tempPlayers.Count);
|
||||
foreach (var player in tempPlayers)
|
||||
{
|
||||
onlinePlayers.Add((player.SteamID, player.UserId, player.Slot));
|
||||
}
|
||||
|
||||
if (onlinePlayers.Count > 0)
|
||||
{
|
||||
await pluginInstance.MuteManager.CheckOnlineModeMutes(onlinePlayers);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// Optimization: Process penalties without LINQ allocations
|
||||
var players = Helper.GetValidPlayers();
|
||||
var penalizedSlots = players
|
||||
.Where(player => PlayerPenaltyManager.IsSlotInPenalties(player.Slot))
|
||||
.Select(player => new
|
||||
{
|
||||
Player = player,
|
||||
IsMuted = PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute, out _),
|
||||
IsSilenced = PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence, out _),
|
||||
IsGagged = PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag, out _)
|
||||
});
|
||||
|
||||
foreach (var entry in penalizedSlots)
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (!entry.IsMuted && !entry.IsSilenced)
|
||||
if (!PlayerPenaltyManager.IsSlotInPenalties(player.Slot))
|
||||
continue;
|
||||
|
||||
var isMuted = PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute, out _);
|
||||
var isSilenced = PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence, out _);
|
||||
|
||||
// Only reset voice flags if not muted or silenced
|
||||
if (!isMuted && !isSilenced)
|
||||
{
|
||||
entry.Player.VoiceFlags = VoiceFlags.Normal;
|
||||
player.VoiceFlags = VoiceFlags.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,29 +35,43 @@ public class ServerManager
|
|||
{
|
||||
if (CS2_SimpleAdmin.ServerLoaded || CS2_SimpleAdmin.DatabaseProvider == null) return;
|
||||
|
||||
if (_getIpTryCount > 32 && Helper.GetServerIp().StartsWith("0.0.0.0") || string.IsNullOrEmpty(Helper.GetServerIp()))
|
||||
// Optimization: Get server IP once and reuse
|
||||
var serverIp = Helper.GetServerIp();
|
||||
var isInvalidIp = string.IsNullOrEmpty(serverIp) || serverIp.StartsWith("0.0.0");
|
||||
|
||||
// Check if we've exceeded retry limit with invalid IP
|
||||
if (_getIpTryCount > 32 && isInvalidIp)
|
||||
{
|
||||
CS2_SimpleAdmin._logger?.LogError("Unable to load server data - can't fetch ip address!");
|
||||
return;
|
||||
}
|
||||
|
||||
var ipAddress = ConVar.Find("ip")?.StringValue;
|
||||
// Optimization: Cache ConVar lookups
|
||||
var ipConVar = ConVar.Find("ip");
|
||||
var ipAddress = ipConVar?.StringValue;
|
||||
|
||||
// Use Helper IP if ConVar IP is invalid
|
||||
if (string.IsNullOrEmpty(ipAddress) || ipAddress.StartsWith("0.0.0"))
|
||||
{
|
||||
ipAddress = Helper.GetServerIp();
|
||||
ipAddress = serverIp;
|
||||
|
||||
if (_getIpTryCount <= 32 && (string.IsNullOrEmpty(ipAddress) || ipAddress.StartsWith("0.0.0")))
|
||||
// Retry if still invalid and under retry limit
|
||||
if (_getIpTryCount <= 32 && isInvalidIp)
|
||||
{
|
||||
_getIpTryCount++;
|
||||
|
||||
LoadServerData();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var address = $"{ipAddress}:{ConVar.Find("hostport")?.GetPrimitiveValue<int>()}";
|
||||
var hostname = ConVar.Find("hostname")?.StringValue ?? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown";
|
||||
var rconPassword = ConVar.Find("rcon_password")?.StringValue ?? "";
|
||||
// Optimization: Cache remaining ConVar lookups
|
||||
var hostportConVar = ConVar.Find("hostport");
|
||||
var hostnameConVar = ConVar.Find("hostname");
|
||||
var rconPasswordConVar = ConVar.Find("rcon_password");
|
||||
|
||||
var address = $"{ipAddress}:{hostportConVar?.GetPrimitiveValue<int>()}";
|
||||
var hostname = hostnameConVar?.StringValue ?? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown";
|
||||
var rconPassword = rconPasswordConVar?.StringValue ?? "";
|
||||
CS2_SimpleAdmin.IpAddress = address;
|
||||
|
||||
Task.Run(async () =>
|
||||
|
|
@ -118,6 +132,8 @@ public class ServerManager
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
CS2_SimpleAdmin.SimpleAdminApi?.OnSimpleAdminReadyEvent();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,11 @@ namespace CS2_SimpleAdmin.Menus;
|
|||
|
||||
public static class AdminMenu
|
||||
{
|
||||
public static void OpenMenu(CCSPlayerController admin)
|
||||
{
|
||||
MenuManager.Instance.OpenMainMenu(admin);
|
||||
}
|
||||
|
||||
public static IMenu? CreateMenu(string title, Action<CCSPlayerController>? backAction = null)
|
||||
{
|
||||
return Helper.CreateMenu(title, backAction);
|
||||
|
|
@ -27,44 +32,44 @@ public static class AdminMenu
|
|||
// }
|
||||
}
|
||||
|
||||
public static void OpenMenu(CCSPlayerController admin)
|
||||
{
|
||||
if (admin.IsValid == false)
|
||||
return;
|
||||
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic") == false)
|
||||
{
|
||||
admin.PrintToChat(localizer?["sa_prefix"] ??
|
||||
"[SimpleAdmin] " +
|
||||
(localizer?["sa_no_permission"] ?? "You do not have permissions to use this command")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var menu = CreateMenu(localizer?["sa_title"] ?? "SimpleAdmin");
|
||||
List<ChatMenuOptionData> options =
|
||||
[
|
||||
new(localizer?["sa_menu_players_manage"] ?? "Players Manage", () => ManagePlayersMenu.OpenMenu(admin)),
|
||||
new(localizer?["sa_menu_server_manage"] ?? "Server Manage", () => ManageServerMenu.OpenMenu(admin)),
|
||||
new(localizer?["sa_menu_fun_commands"] ?? "Fun Commands", () => FunActionsMenu.OpenMenu(admin)),
|
||||
];
|
||||
|
||||
var customCommands = CS2_SimpleAdmin.Instance.Config.CustomServerCommands;
|
||||
if (customCommands.Count > 0)
|
||||
{
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_menu_custom_commands"] ?? "Custom Commands", () => CustomCommandsMenu.OpenMenu(admin)));
|
||||
}
|
||||
|
||||
if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/root"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_menu_admins_manage"] ?? "Admins Manage", () => ManageAdminsMenu.OpenMenu(admin)));
|
||||
|
||||
foreach (var menuOptionData in options)
|
||||
{
|
||||
var menuName = menuOptionData.Name;
|
||||
menu?.AddMenuOption(menuName, (_, _) => { menuOptionData.Action.Invoke(); }, menuOptionData.Disabled);
|
||||
}
|
||||
|
||||
if (menu != null) OpenMenu(admin, menu);
|
||||
}
|
||||
// public static void OpenMenu(CCSPlayerController admin)
|
||||
// {
|
||||
// if (admin.IsValid == false)
|
||||
// return;
|
||||
//
|
||||
// var localizer = CS2_SimpleAdmin._localizer;
|
||||
// if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic") == false)
|
||||
// {
|
||||
// admin.PrintToChat(localizer?["sa_prefix"] ??
|
||||
// "[SimpleAdmin] " +
|
||||
// (localizer?["sa_no_permission"] ?? "You do not have permissions to use this command")
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var menu = CreateMenu(localizer?["sa_title"] ?? "SimpleAdmin");
|
||||
// List<ChatMenuOptionData> options =
|
||||
// [
|
||||
// new(localizer?["sa_menu_players_manage"] ?? "Players Manage", () => ManagePlayersMenu.OpenMenu(admin)),
|
||||
// new(localizer?["sa_menu_server_manage"] ?? "Server Manage", () => ManageServerMenu.OpenMenu(admin)),
|
||||
// new(localizer?["sa_menu_fun_commands"] ?? "Fun Commands", () => FunActionsMenu.OpenMenu(admin)),
|
||||
// ];
|
||||
//
|
||||
// var customCommands = CS2_SimpleAdmin.Instance.Config.CustomServerCommands;
|
||||
// if (customCommands.Count > 0)
|
||||
// {
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_menu_custom_commands"] ?? "Custom Commands", () => CustomCommandsMenu.OpenMenu(admin)));
|
||||
// }
|
||||
//
|
||||
// if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/root"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_menu_admins_manage"] ?? "Admins Manage", () => ManageAdminsMenu.OpenMenu(admin)));
|
||||
//
|
||||
// foreach (var menuOptionData in options)
|
||||
// {
|
||||
// var menuName = menuOptionData.Name;
|
||||
// menu?.AddMenuOption(menuName, (_, _) => { menuOptionData.Action.Invoke(); }, menuOptionData.Disabled);
|
||||
// }
|
||||
//
|
||||
// if (menu != null) OpenMenu(admin, menu);
|
||||
// }
|
||||
}
|
||||
602
CS2-SimpleAdmin/Menus/BasicMenu.cs
Normal file
602
CS2-SimpleAdmin/Menus/BasicMenu.cs
Normal file
|
|
@ -0,0 +1,602 @@
|
|||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes all menus in the system by registering them with the MenuManager.
|
||||
/// </summary>
|
||||
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");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for slapping players with selectable damage amounts.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the slap menu.</returns>
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates damage selection submenu for slapping a specific player.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player executing the slap.</param>
|
||||
/// <param name="target">The target player to be slapped.</param>
|
||||
/// <returns>A MenuBuilder instance for the slap damage menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for slaying (killing) players.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the slay menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for kicking players with reason selection.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the kick menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for warning players with duration and reason selection.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the warn menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for banning players with duration and reason selection.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the ban menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for gagging (text chat muting) players with duration and reason selection.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the gag menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for muting (voice chat muting) players with duration and reason selection.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the mute menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for silencing (both text and voice chat muting) players with duration and reason selection.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the silence menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for forcing players to switch teams.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the force team menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates team selection submenu for forcing a specific player to a team.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player executing the team change.</param>
|
||||
/// <param name="target">The target player to be moved.</param>
|
||||
/// <returns>A MenuBuilder instance for the team selection menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for managing server plugins.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the plugins menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for changing the current map (includes default and workshop maps).
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the change map menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for restarting the current game/round.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the restart game menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for executing custom server commands defined in configuration.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the custom commands menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for adding admin privileges to players.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the add admin menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates admin flags selection submenu for granting specific permissions to a player.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player granting permissions.</param>
|
||||
/// <param name="target">The target player to receive admin privileges.</param>
|
||||
/// <returns>A MenuBuilder instance for the admin flags menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for removing admin privileges from players.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the remove admin menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates menu for reloading admin list from database.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player opening the menu.</param>
|
||||
/// <returns>A MenuBuilder instance for the reload admins menu.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates duration selection submenu for time-based penalties (ban, mute, gag, etc.).
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player selecting duration.</param>
|
||||
/// <param name="player">The target player for the penalty.</param>
|
||||
/// <param name="actionName">The name of the penalty action.</param>
|
||||
/// <param name="onSelectAction">Callback action executed when duration is selected.</param>
|
||||
/// <returns>A MenuBuilder instance for the duration menu.</returns>
|
||||
private static MenuBuilder CreateDurationMenu(CCSPlayerController admin, CCSPlayerController player, string actionName,
|
||||
Action<CCSPlayerController, CCSPlayerController, int> 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates reason selection submenu for penalties with predefined reasons from configuration.
|
||||
/// </summary>
|
||||
/// <param name="admin">The admin player selecting reason.</param>
|
||||
/// <param name="player">The target player for the penalty.</param>
|
||||
/// <param name="actionName">The name of the penalty action.</param>
|
||||
/// <param name="penaltyType">The type of penalty to determine which reason list to use.</param>
|
||||
/// <param name="onSelectAction">Callback action executed when reason is selected.</param>
|
||||
/// <returns>A MenuBuilder instance for the reason menu.</returns>
|
||||
private static MenuBuilder CreateReasonMenu(CCSPlayerController admin, CCSPlayerController player, string actionName,
|
||||
PenaltyType penaltyType, Action<CCSPlayerController, CCSPlayerController, string> 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -9,11 +9,11 @@ public static class CustomCommandsMenu
|
|||
{
|
||||
public static void OpenMenu(CCSPlayerController admin)
|
||||
{
|
||||
if (admin.IsValid == false)
|
||||
if (!admin.IsValid)
|
||||
return;
|
||||
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic") == false)
|
||||
if (!AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic"))
|
||||
{
|
||||
admin.PrintToChat(localizer?["sa_prefix"] ??
|
||||
"[SimpleAdmin] " +
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ public static class DurationMenu
|
|||
public static void OpenMenu(CCSPlayerController admin, string menuName, CCSPlayerController player, Action<CCSPlayerController, CCSPlayerController, int> onSelectAction)
|
||||
{
|
||||
var menu = AdminMenu.CreateMenu(menuName);
|
||||
|
||||
foreach (var durationItem in CS2_SimpleAdmin.Instance.Config.MenuConfigs.Durations)
|
||||
{
|
||||
menu?.AddMenuOption(durationItem.Name, (_, _) => { onSelectAction(admin, player, durationItem.Duration); });
|
||||
|
|
@ -20,7 +19,6 @@ public static class DurationMenu
|
|||
public static void OpenMenu(CCSPlayerController admin, string menuName, DisconnectedPlayer player, Action<CCSPlayerController, DisconnectedPlayer, int> onSelectAction)
|
||||
{
|
||||
var menu = AdminMenu.CreateMenu(menuName);
|
||||
|
||||
foreach (var durationItem in CS2_SimpleAdmin.Instance.Config.MenuConfigs.Durations)
|
||||
{
|
||||
menu?.AddMenuOption(durationItem.Name, (_, _) => { onSelectAction(admin, player, durationItem.Duration); });
|
||||
|
|
|
|||
|
|
@ -1,267 +1,267 @@
|
|||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
|
||||
namespace CS2_SimpleAdmin.Menus;
|
||||
|
||||
public static class FunActionsMenu
|
||||
{
|
||||
private static Dictionary<int, CsItem>? _weaponsCache;
|
||||
|
||||
private static Dictionary<int, CsItem> GetWeaponsCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_weaponsCache != null) return _weaponsCache;
|
||||
|
||||
var weaponsArray = Enum.GetValues(typeof(CsItem));
|
||||
|
||||
// avoid duplicates in the menu
|
||||
_weaponsCache = new Dictionary<int, CsItem>();
|
||||
foreach (CsItem item in weaponsArray)
|
||||
{
|
||||
if (item == CsItem.Tablet)
|
||||
continue;
|
||||
|
||||
_weaponsCache[(int)item] = item;
|
||||
}
|
||||
|
||||
return _weaponsCache;
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenMenu(CCSPlayerController admin)
|
||||
{
|
||||
if (admin.IsValid == false)
|
||||
return;
|
||||
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic") == false)
|
||||
{
|
||||
admin.PrintToChat(localizer?["sa_prefix"] ??
|
||||
"[SimpleAdmin] " +
|
||||
(localizer?["sa_no_permission"] ?? "You do not have permissions to use this command")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var menu = AdminMenu.CreateMenu(localizer?["sa_menu_fun_commands"] ?? "Fun Commands");
|
||||
List<ChatMenuOptionData> options = [];
|
||||
|
||||
//var hasCheats = AdminManager.PlayerHasPermissions(admin, "@css/cheats");
|
||||
//var hasSlay = AdminManager.PlayerHasPermissions(admin, "@css/slay");
|
||||
|
||||
// options added in order
|
||||
|
||||
if (AdminManager.CommandIsOverriden("css_god")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_god"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/cheats"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_godmode"] ?? "God Mode", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_godmode"] ?? "God Mode", GodMode)));
|
||||
if (AdminManager.CommandIsOverriden("css_noclip")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_noclip"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/cheats"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_noclip"] ?? "No Clip", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_noclip"] ?? "No Clip", NoClip)));
|
||||
if (AdminManager.CommandIsOverriden("css_respawn")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_respawn"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/cheats"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_respawn"] ?? "Respawn", () => PlayersMenu.OpenDeadMenu(admin, localizer?["sa_respawn"] ?? "Respawn", Respawn)));
|
||||
if (AdminManager.CommandIsOverriden("css_give")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_give"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/cheats"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_give_weapon"] ?? "Give Weapon", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_give_weapon"] ?? "Give Weapon", GiveWeaponMenu)));
|
||||
|
||||
if (AdminManager.CommandIsOverriden("css_strip")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_strip"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_strip_weapons"] ?? "Strip Weapons", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_strip_weapons"] ?? "Strip Weapons", StripWeapons)));
|
||||
if (AdminManager.CommandIsOverriden("css_freeze")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_freeze"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_freeze"] ?? "Freeze", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_freeze"] ?? "Freeze", Freeze)));
|
||||
if (AdminManager.CommandIsOverriden("css_hp")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_hp"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_set_hp"] ?? "Set Hp", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_set_hp"] ?? "Set Hp", SetHpMenu)));
|
||||
if (AdminManager.CommandIsOverriden("css_speed")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_speed"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_set_speed"] ?? "Set Speed", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_set_speed"] ?? "Set Speed", SetSpeedMenu)));
|
||||
if (AdminManager.CommandIsOverriden("css_gravity")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_gravity"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_set_gravity"] ?? "Set Gravity", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_set_gravity"] ?? "Set Gravity", SetGravityMenu)));
|
||||
if (AdminManager.CommandIsOverriden("css_money")
|
||||
? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_money"))
|
||||
: AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
options.Add(new ChatMenuOptionData(localizer?["sa_set_money"] ?? "Set Money", () => PlayersMenu.OpenMenu(admin, localizer?["sa_set_money"] ?? "Set Money", SetMoneyMenu)));
|
||||
|
||||
foreach (var menuOptionData in options)
|
||||
{
|
||||
var menuName = menuOptionData.Name;
|
||||
menu?.AddMenuOption(menuName, (_, _) => { menuOptionData.Action(); }, menuOptionData.Disabled);
|
||||
}
|
||||
|
||||
if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
}
|
||||
|
||||
private static void GodMode(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
CS2_SimpleAdmin.God(admin, player);
|
||||
}
|
||||
|
||||
private static void NoClip(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
CS2_SimpleAdmin.NoClip(admin, player);
|
||||
}
|
||||
|
||||
private static void Respawn(CCSPlayerController? admin, CCSPlayerController player)
|
||||
{
|
||||
CS2_SimpleAdmin.Respawn(admin, player);
|
||||
}
|
||||
|
||||
private static void GiveWeaponMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_give_weapon"] ?? "Give Weapon"}: {player.PlayerName}");
|
||||
|
||||
foreach (var weapon in GetWeaponsCache)
|
||||
{
|
||||
menu?.AddMenuOption(weapon.Value.ToString(), (_, _) => { GiveWeapon(admin, player, weapon.Value); });
|
||||
}
|
||||
|
||||
if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
}
|
||||
|
||||
private static void GiveWeapon(CCSPlayerController admin, CCSPlayerController player, CsItem weaponValue)
|
||||
{
|
||||
CS2_SimpleAdmin.GiveWeapon(admin, player, weaponValue);
|
||||
}
|
||||
|
||||
private static void StripWeapons(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
CS2_SimpleAdmin.StripWeapons(admin, player);
|
||||
}
|
||||
|
||||
private static void Freeze(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
if (!(player.PlayerPawn.Value?.IsValid ?? false))
|
||||
return;
|
||||
|
||||
if (player.PlayerPawn.Value.MoveType != MoveType_t.MOVETYPE_INVALID)
|
||||
CS2_SimpleAdmin.Freeze(admin, player, -1);
|
||||
else
|
||||
CS2_SimpleAdmin.Unfreeze(admin, player);
|
||||
}
|
||||
|
||||
private static void SetHpMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
var hpArray = new[]
|
||||
{
|
||||
new Tuple<string, int>("1", 1),
|
||||
new Tuple<string, int>("10", 10),
|
||||
new Tuple<string, int>("25", 25),
|
||||
new Tuple<string, int>("50", 50),
|
||||
new Tuple<string, int>("100", 100),
|
||||
new Tuple<string, int>("200", 200),
|
||||
new Tuple<string, int>("500", 500),
|
||||
new Tuple<string, int>("999", 999)
|
||||
};
|
||||
|
||||
var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_set_hp"] ?? "Set Hp"}: {player.PlayerName}");
|
||||
|
||||
foreach (var (optionName, value) in hpArray)
|
||||
{
|
||||
menu?.AddMenuOption(optionName, (_, _) => { SetHp(admin, player, value); });
|
||||
}
|
||||
|
||||
if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
}
|
||||
|
||||
private static void SetHp(CCSPlayerController admin, CCSPlayerController player, int hp)
|
||||
{
|
||||
CS2_SimpleAdmin.SetHp(admin, player, hp);
|
||||
}
|
||||
|
||||
private static void SetSpeedMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
var speedArray = new[]
|
||||
{
|
||||
new Tuple<string, float>("0.1", .1f),
|
||||
new Tuple<string, float>("0.25", .25f),
|
||||
new Tuple<string, float>("0.5", .5f),
|
||||
new Tuple<string, float>("0.75", .75f),
|
||||
new Tuple<string, float>("1", 1),
|
||||
new Tuple<string, float>("2", 2),
|
||||
new Tuple<string, float>("3", 3),
|
||||
new Tuple<string, float>("4", 4)
|
||||
};
|
||||
|
||||
var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_set_speed"] ?? "Set Speed"}: {player.PlayerName}");
|
||||
|
||||
foreach (var (optionName, value) in speedArray)
|
||||
{
|
||||
menu?.AddMenuOption(optionName, (_, _) => { SetSpeed(admin, player, value); });
|
||||
}
|
||||
|
||||
if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
}
|
||||
|
||||
private static void SetSpeed(CCSPlayerController admin, CCSPlayerController player, float speed)
|
||||
{
|
||||
CS2_SimpleAdmin.SetSpeed(admin, player, speed);
|
||||
}
|
||||
|
||||
private static void SetGravityMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
var gravityArray = new[]
|
||||
{
|
||||
new Tuple<string, float>("0.1", .1f),
|
||||
new Tuple<string, float>("0.25", .25f),
|
||||
new Tuple<string, float>("0.5", .5f),
|
||||
new Tuple<string, float>("0.75", .75f),
|
||||
new Tuple<string, float>("1", 1),
|
||||
new Tuple<string, float>("2", 2)
|
||||
};
|
||||
|
||||
var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_set_gravity"] ?? "Set Gravity"}: {player.PlayerName}");
|
||||
|
||||
foreach (var (optionName, value) in gravityArray)
|
||||
{
|
||||
menu?.AddMenuOption(optionName, (_, _) => { SetGravity(admin, player, value); });
|
||||
}
|
||||
|
||||
if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
}
|
||||
|
||||
private static void SetGravity(CCSPlayerController admin, CCSPlayerController player, float gravity)
|
||||
{
|
||||
CS2_SimpleAdmin.SetGravity(admin, player, gravity);
|
||||
}
|
||||
|
||||
private static void SetMoneyMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
{
|
||||
var moneyArray = new[]
|
||||
{
|
||||
new Tuple<string, int>("$0", 0),
|
||||
new Tuple<string, int>("$1000", 1000),
|
||||
new Tuple<string, int>("$2500", 2500),
|
||||
new Tuple<string, int>("$5000", 5000),
|
||||
new Tuple<string, int>("$10000", 10000),
|
||||
new Tuple<string, int>("$16000", 16000)
|
||||
};
|
||||
|
||||
var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_set_money"] ?? "Set Money"}: {player.PlayerName}");
|
||||
|
||||
foreach (var (optionName, value) in moneyArray)
|
||||
{
|
||||
menu?.AddMenuOption(optionName, (_, _) => { SetMoney(admin, player, value); });
|
||||
}
|
||||
|
||||
if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
}
|
||||
|
||||
private static void SetMoney(CCSPlayerController admin, CCSPlayerController player, int money)
|
||||
{
|
||||
CS2_SimpleAdmin.SetMoney(admin, player, money);
|
||||
}
|
||||
}
|
||||
// using CounterStrikeSharp.API.Core;
|
||||
// using CounterStrikeSharp.API.Modules.Admin;
|
||||
// using CounterStrikeSharp.API.Modules.Entities;
|
||||
// using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
//
|
||||
// namespace CS2_SimpleAdmin.Menus;
|
||||
//
|
||||
// public static class FunActionsMenu
|
||||
// {
|
||||
// private static Dictionary<int, CsItem>? _weaponsCache;
|
||||
//
|
||||
// private static Dictionary<int, CsItem> GetWeaponsCache
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// if (_weaponsCache != null) return _weaponsCache;
|
||||
//
|
||||
// var weaponsArray = Enum.GetValues(typeof(CsItem));
|
||||
//
|
||||
// // avoid duplicates in the menu
|
||||
// _weaponsCache = new Dictionary<int, CsItem>();
|
||||
// foreach (CsItem item in weaponsArray)
|
||||
// {
|
||||
// if (item == CsItem.Tablet)
|
||||
// continue;
|
||||
//
|
||||
// _weaponsCache[(int)item] = item;
|
||||
// }
|
||||
//
|
||||
// return _weaponsCache;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static void OpenMenu(CCSPlayerController admin)
|
||||
// {
|
||||
// if (!admin.IsValid)
|
||||
// return;
|
||||
//
|
||||
// var localizer = CS2_SimpleAdmin._localizer;
|
||||
// if (!AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic"))
|
||||
// {
|
||||
// admin.PrintToChat(localizer?["sa_prefix"] ??
|
||||
// "[SimpleAdmin] " +
|
||||
// (localizer?["sa_no_permission"] ?? "You do not have permissions to use this command")
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var menu = AdminMenu.CreateMenu(localizer?["sa_menu_fun_commands"] ?? "Fun Commands");
|
||||
// List<ChatMenuOptionData> options = [];
|
||||
//
|
||||
// //var hasCheats = AdminManager.PlayerHasPermissions(admin, "@css/cheats");
|
||||
// //var hasSlay = AdminManager.PlayerHasPermissions(admin, "@css/slay");
|
||||
//
|
||||
// // options added in order
|
||||
//
|
||||
// if (AdminManager.CommandIsOverriden("css_god")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_god"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/cheats"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_godmode"] ?? "God Mode", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_godmode"] ?? "God Mode", GodMode)));
|
||||
// if (AdminManager.CommandIsOverriden("css_noclip")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_noclip"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/cheats"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_noclip"] ?? "No Clip", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_noclip"] ?? "No Clip", NoClip)));
|
||||
// if (AdminManager.CommandIsOverriden("css_respawn")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_respawn"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/cheats"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_respawn"] ?? "Respawn", () => PlayersMenu.OpenDeadMenu(admin, localizer?["sa_respawn"] ?? "Respawn", Respawn)));
|
||||
// if (AdminManager.CommandIsOverriden("css_give")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_give"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/cheats"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_give_weapon"] ?? "Give Weapon", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_give_weapon"] ?? "Give Weapon", GiveWeaponMenu)));
|
||||
//
|
||||
// if (AdminManager.CommandIsOverriden("css_strip")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_strip"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_strip_weapons"] ?? "Strip Weapons", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_strip_weapons"] ?? "Strip Weapons", StripWeapons)));
|
||||
// if (AdminManager.CommandIsOverriden("css_freeze")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_freeze"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_freeze"] ?? "Freeze", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_freeze"] ?? "Freeze", Freeze)));
|
||||
// if (AdminManager.CommandIsOverriden("css_hp")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_hp"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_set_hp"] ?? "Set Hp", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_set_hp"] ?? "Set Hp", SetHpMenu)));
|
||||
// if (AdminManager.CommandIsOverriden("css_speed")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_speed"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_set_speed"] ?? "Set Speed", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_set_speed"] ?? "Set Speed", SetSpeedMenu)));
|
||||
// if (AdminManager.CommandIsOverriden("css_gravity")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_gravity"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_set_gravity"] ?? "Set Gravity", () => PlayersMenu.OpenAliveMenu(admin, localizer?["sa_set_gravity"] ?? "Set Gravity", SetGravityMenu)));
|
||||
// if (AdminManager.CommandIsOverriden("css_money")
|
||||
// ? AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), AdminManager.GetPermissionOverrides("css_money"))
|
||||
// : AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/slay"))
|
||||
// options.Add(new ChatMenuOptionData(localizer?["sa_set_money"] ?? "Set Money", () => PlayersMenu.OpenMenu(admin, localizer?["sa_set_money"] ?? "Set Money", SetMoneyMenu)));
|
||||
//
|
||||
// foreach (var menuOptionData in options)
|
||||
// {
|
||||
// var menuName = menuOptionData.Name;
|
||||
// menu?.AddMenuOption(menuName, (_, _) => { menuOptionData.Action(); }, menuOptionData.Disabled);
|
||||
// }
|
||||
//
|
||||
// if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
// }
|
||||
//
|
||||
// private static void GodMode(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// CS2_SimpleAdmin.God(admin, player);
|
||||
// }
|
||||
//
|
||||
// private static void NoClip(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// CS2_SimpleAdmin.NoClip(admin, player);
|
||||
// }
|
||||
//
|
||||
// private static void Respawn(CCSPlayerController? admin, CCSPlayerController player)
|
||||
// {
|
||||
// CS2_SimpleAdmin.Respawn(admin, player);
|
||||
// }
|
||||
//
|
||||
// private static void GiveWeaponMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_give_weapon"] ?? "Give Weapon"}: {player.PlayerName}");
|
||||
//
|
||||
// foreach (var weapon in GetWeaponsCache)
|
||||
// {
|
||||
// menu?.AddMenuOption(weapon.Value.ToString(), (_, _) => { GiveWeapon(admin, player, weapon.Value); });
|
||||
// }
|
||||
//
|
||||
// if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
// }
|
||||
//
|
||||
// private static void GiveWeapon(CCSPlayerController admin, CCSPlayerController player, CsItem weaponValue)
|
||||
// {
|
||||
// CS2_SimpleAdmin.GiveWeapon(admin, player, weaponValue);
|
||||
// }
|
||||
//
|
||||
// private static void StripWeapons(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// CS2_SimpleAdmin.StripWeapons(admin, player);
|
||||
// }
|
||||
//
|
||||
// private static void Freeze(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// if (!(player.PlayerPawn.Value?.IsValid ?? false))
|
||||
// return;
|
||||
//
|
||||
// if (player.PlayerPawn.Value.MoveType != MoveType_t.MOVETYPE_INVALID)
|
||||
// CS2_SimpleAdmin.Freeze(admin, player, -1);
|
||||
// else
|
||||
// CS2_SimpleAdmin.Unfreeze(admin, player);
|
||||
// }
|
||||
//
|
||||
// private static void SetHpMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// var hpArray = new[]
|
||||
// {
|
||||
// new Tuple<string, int>("1", 1),
|
||||
// new Tuple<string, int>("10", 10),
|
||||
// new Tuple<string, int>("25", 25),
|
||||
// new Tuple<string, int>("50", 50),
|
||||
// new Tuple<string, int>("100", 100),
|
||||
// new Tuple<string, int>("200", 200),
|
||||
// new Tuple<string, int>("500", 500),
|
||||
// new Tuple<string, int>("999", 999)
|
||||
// };
|
||||
//
|
||||
// var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_set_hp"] ?? "Set Hp"}: {player.PlayerName}");
|
||||
//
|
||||
// foreach (var (optionName, value) in hpArray)
|
||||
// {
|
||||
// menu?.AddMenuOption(optionName, (_, _) => { SetHp(admin, player, value); });
|
||||
// }
|
||||
//
|
||||
// if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
// }
|
||||
//
|
||||
// private static void SetHp(CCSPlayerController admin, CCSPlayerController player, int hp)
|
||||
// {
|
||||
// CS2_SimpleAdmin.SetHp(admin, player, hp);
|
||||
// }
|
||||
//
|
||||
// private static void SetSpeedMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// var speedArray = new[]
|
||||
// {
|
||||
// new Tuple<string, float>("0.1", .1f),
|
||||
// new Tuple<string, float>("0.25", .25f),
|
||||
// new Tuple<string, float>("0.5", .5f),
|
||||
// new Tuple<string, float>("0.75", .75f),
|
||||
// new Tuple<string, float>("1", 1),
|
||||
// new Tuple<string, float>("2", 2),
|
||||
// new Tuple<string, float>("3", 3),
|
||||
// new Tuple<string, float>("4", 4)
|
||||
// };
|
||||
//
|
||||
// var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_set_speed"] ?? "Set Speed"}: {player.PlayerName}");
|
||||
//
|
||||
// foreach (var (optionName, value) in speedArray)
|
||||
// {
|
||||
// menu?.AddMenuOption(optionName, (_, _) => { SetSpeed(admin, player, value); });
|
||||
// }
|
||||
//
|
||||
// if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
// }
|
||||
//
|
||||
// private static void SetSpeed(CCSPlayerController admin, CCSPlayerController player, float speed)
|
||||
// {
|
||||
// CS2_SimpleAdmin.SetSpeed(admin, player, speed);
|
||||
// }
|
||||
//
|
||||
// private static void SetGravityMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// var gravityArray = new[]
|
||||
// {
|
||||
// new Tuple<string, float>("0.1", .1f),
|
||||
// new Tuple<string, float>("0.25", .25f),
|
||||
// new Tuple<string, float>("0.5", .5f),
|
||||
// new Tuple<string, float>("0.75", .75f),
|
||||
// new Tuple<string, float>("1", 1),
|
||||
// new Tuple<string, float>("2", 2)
|
||||
// };
|
||||
//
|
||||
// var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_set_gravity"] ?? "Set Gravity"}: {player.PlayerName}");
|
||||
//
|
||||
// foreach (var (optionName, value) in gravityArray)
|
||||
// {
|
||||
// menu?.AddMenuOption(optionName, (_, _) => { SetGravity(admin, player, value); });
|
||||
// }
|
||||
//
|
||||
// if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
// }
|
||||
//
|
||||
// private static void SetGravity(CCSPlayerController admin, CCSPlayerController player, float gravity)
|
||||
// {
|
||||
// CS2_SimpleAdmin.SetGravity(admin, player, gravity);
|
||||
// }
|
||||
//
|
||||
// private static void SetMoneyMenu(CCSPlayerController admin, CCSPlayerController player)
|
||||
// {
|
||||
// var moneyArray = new[]
|
||||
// {
|
||||
// new Tuple<string, int>("$0", 0),
|
||||
// new Tuple<string, int>("$1000", 1000),
|
||||
// new Tuple<string, int>("$2500", 2500),
|
||||
// new Tuple<string, int>("$5000", 5000),
|
||||
// new Tuple<string, int>("$10000", 10000),
|
||||
// new Tuple<string, int>("$16000", 16000)
|
||||
// };
|
||||
//
|
||||
// var menu = AdminMenu.CreateMenu($"{CS2_SimpleAdmin._localizer?["sa_set_money"] ?? "Set Money"}: {player.PlayerName}");
|
||||
//
|
||||
// foreach (var (optionName, value) in moneyArray)
|
||||
// {
|
||||
// menu?.AddMenuOption(optionName, (_, _) => { SetMoney(admin, player, value); });
|
||||
// }
|
||||
//
|
||||
// if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
// }
|
||||
//
|
||||
// private static void SetMoney(CCSPlayerController admin, CCSPlayerController player, int money)
|
||||
// {
|
||||
// CS2_SimpleAdmin.SetMoney(admin, player, money);
|
||||
// }
|
||||
// }
|
||||
|
|
@ -8,11 +8,11 @@ public static class ManageAdminsMenu
|
|||
{
|
||||
public static void OpenMenu(CCSPlayerController admin)
|
||||
{
|
||||
if (admin.IsValid == false)
|
||||
if (!admin.IsValid)
|
||||
return;
|
||||
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/root") == false)
|
||||
if (!AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/root"))
|
||||
{
|
||||
admin.PrintToChat(localizer?["sa_prefix"] ??
|
||||
"[SimpleAdmin] " +
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ public static class ManagePlayersMenu
|
|||
{
|
||||
public static void OpenMenu(CCSPlayerController admin)
|
||||
{
|
||||
if (admin.IsValid == false)
|
||||
if (!admin.IsValid)
|
||||
return;
|
||||
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic") == false)
|
||||
if (!AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic"))
|
||||
{
|
||||
admin.PrintToChat(localizer?["sa_prefix"] ??
|
||||
"[SimpleAdmin] " +
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ public static class ManageServerMenu
|
|||
{
|
||||
public static void OpenMenu(CCSPlayerController admin)
|
||||
{
|
||||
if (admin.IsValid == false)
|
||||
if (!admin.IsValid)
|
||||
return;
|
||||
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
if (AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic") == false)
|
||||
if (!AdminManager.PlayerHasPermissions(new SteamID(admin.SteamID), "@css/generic"))
|
||||
{
|
||||
admin.PrintToChat(localizer?["sa_prefix"] ??
|
||||
"[SimpleAdmin] " +
|
||||
|
|
|
|||
170
CS2-SimpleAdmin/Menus/MenuBuilder.cs
Normal file
170
CS2-SimpleAdmin/Menus/MenuBuilder.cs
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
using CounterStrikeSharp.API.Core;
|
||||
|
||||
namespace CS2_SimpleAdmin.Menus;
|
||||
public class MenuBuilder(string title)
|
||||
{
|
||||
private readonly List<MenuOption> _options = [];
|
||||
private MenuBuilder? _parentMenu;
|
||||
private Action<CCSPlayerController>? _backAction;
|
||||
private Action<CCSPlayerController>? _resetAction;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a menu option with an action.
|
||||
/// </summary>
|
||||
public MenuBuilder AddOption(string name, Action<CCSPlayerController> action, bool disabled = false, string? permission = null)
|
||||
{
|
||||
_options.Add(new MenuOption
|
||||
{
|
||||
Name = name,
|
||||
Action = action,
|
||||
Disabled = disabled,
|
||||
Permission = permission
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a menu option that opens a submenu.
|
||||
/// </summary>
|
||||
public MenuBuilder AddSubMenu(string name, Func<MenuBuilder> subMenuFactory, bool disabled = false, string? permission = null)
|
||||
{
|
||||
_options.Add(new MenuOption
|
||||
{
|
||||
Name = name,
|
||||
Action = player =>
|
||||
{
|
||||
var subMenu = subMenuFactory();
|
||||
subMenu.SetParent(this);
|
||||
// Automatically add back button to submenu
|
||||
subMenu.WithBackButton();
|
||||
subMenu.OpenMenu(player);
|
||||
},
|
||||
Disabled = disabled,
|
||||
Permission = permission
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a menu option that opens a submenu (with player parameter in factory).
|
||||
/// </summary>
|
||||
public MenuBuilder AddSubMenu(string name, Func<CCSPlayerController, MenuBuilder> subMenuFactory, bool disabled = false, string? permission = null)
|
||||
{
|
||||
_options.Add(new MenuOption
|
||||
{
|
||||
Name = name,
|
||||
Action = player =>
|
||||
{
|
||||
var subMenu = subMenuFactory(player);
|
||||
subMenu.SetParent(this);
|
||||
// Automatically add back button to submenu
|
||||
subMenu.WithBackButton();
|
||||
subMenu.OpenMenu(player);
|
||||
},
|
||||
Disabled = disabled,
|
||||
Permission = permission
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a back button to return to the previous menu.
|
||||
/// </summary>
|
||||
public MenuBuilder WithBackButton()
|
||||
{
|
||||
if (_parentMenu != null)
|
||||
{
|
||||
_backAction = player => _parentMenu.OpenMenu(player);
|
||||
|
||||
// Add back option at the end of menu
|
||||
// AddOption(backButtonText, _backAction);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the parent menu (for navigation).
|
||||
/// </summary>
|
||||
private void SetParent(MenuBuilder parent)
|
||||
{
|
||||
_parentMenu = parent;
|
||||
_backAction = player => _parentMenu.OpenMenu(player);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the menu for a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to open the menu for.</param>
|
||||
public void OpenMenu(CCSPlayerController player)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
|
||||
// Use MenuManager dependency
|
||||
var menu = Helper.CreateMenu(title, _backAction);
|
||||
if (menu == null) return;
|
||||
|
||||
foreach (var option in _options)
|
||||
{
|
||||
// Check permissions if required
|
||||
if (!string.IsNullOrEmpty(option.Permission))
|
||||
{
|
||||
var steamId = new CounterStrikeSharp.API.Modules.Entities.SteamID(player.SteamID);
|
||||
if (!CounterStrikeSharp.API.Modules.Admin.AdminManager.PlayerHasPermissions(steamId, option.Permission))
|
||||
{
|
||||
continue; // Skip option if player doesn't have permission
|
||||
}
|
||||
}
|
||||
|
||||
menu.AddMenuOption(option.Name, (menuPlayer, menuOption) =>
|
||||
{
|
||||
option.Action?.Invoke(menuPlayer);
|
||||
}, option.Disabled);
|
||||
}
|
||||
|
||||
menu.Open(player);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all menu options.
|
||||
/// </summary>
|
||||
/// <returns>This MenuBuilder instance for chaining.</returns>
|
||||
public MenuBuilder Clear()
|
||||
{
|
||||
_options.Clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a reset action for the menu.
|
||||
/// </summary>
|
||||
/// <param name="resetAction">The action to execute on reset.</param>
|
||||
/// <returns>This MenuBuilder instance for chaining.</returns>
|
||||
public MenuBuilder WithResetAction(Action<CCSPlayerController> resetAction)
|
||||
{
|
||||
_resetAction = resetAction;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a custom back action for the menu.
|
||||
/// </summary>
|
||||
/// <param name="backAction">The action to execute when going back (nullable).</param>
|
||||
/// <returns>This MenuBuilder instance for chaining.</returns>
|
||||
public MenuBuilder WithBackAction(Action<CCSPlayerController>? backAction)
|
||||
{
|
||||
_backAction = backAction;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an option within a menu.
|
||||
/// </summary>
|
||||
public class MenuOption
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public Action<CCSPlayerController>? Action { get; set; }
|
||||
public bool Disabled { get; set; }
|
||||
public string? Permission { get; set; }
|
||||
}
|
||||
|
||||
190
CS2-SimpleAdmin/Menus/MenuManager.cs
Normal file
190
CS2-SimpleAdmin/Menus/MenuManager.cs
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
|
||||
namespace CS2_SimpleAdmin.Menus;
|
||||
|
||||
public class MenuManager
|
||||
{
|
||||
private static MenuManager? _instance;
|
||||
public static MenuManager Instance => _instance ??= new MenuManager();
|
||||
|
||||
private readonly Dictionary<string, Func<CCSPlayerController, MenuBuilder>> _menuFactories = [];
|
||||
private readonly Dictionary<string, MenuCategory> _menuCategories = [];
|
||||
|
||||
/// <summary>
|
||||
/// Provides public access to menu categories (for API usage).
|
||||
/// </summary>
|
||||
/// <returns>Dictionary of menu categories keyed by category ID.</returns>
|
||||
public Dictionary<string, MenuCategory> GetMenuCategories()
|
||||
{
|
||||
return _menuCategories;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new menu category with specified permissions.
|
||||
/// </summary>
|
||||
/// <param name="categoryId">Unique identifier for the category.</param>
|
||||
/// <param name="categoryName">Display name of the category.</param>
|
||||
/// <param name="permission">Required permission to access this category (default: @css/generic).</param>
|
||||
public void RegisterCategory(string categoryId, string categoryName, string permission = "@css/generic")
|
||||
{
|
||||
_menuCategories[categoryId] = new MenuCategory
|
||||
{
|
||||
Id = categoryId,
|
||||
Name = categoryName,
|
||||
Permission = permission,
|
||||
MenuFactories = new Dictionary<string, Func<CCSPlayerController, MenuBuilder>>()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a menu within a category (API for other plugins).
|
||||
/// </summary>
|
||||
/// <param name="categoryId">The category to add this menu to.</param>
|
||||
/// <param name="menuId">Unique identifier for the menu.</param>
|
||||
/// <param name="menuName">Display name of the menu.</param>
|
||||
/// <param name="menuFactory">Factory function that creates the menu for a player.</param>
|
||||
/// <param name="permission">Required permission to access this menu (optional).</param>
|
||||
public void RegisterMenu(string categoryId, string menuId, string menuName, Func<CCSPlayerController, MenuBuilder> menuFactory, string? permission = null)
|
||||
{
|
||||
if (!_menuCategories.ContainsKey(categoryId))
|
||||
{
|
||||
RegisterCategory(categoryId, categoryId); // Auto-create category if it doesn't exist
|
||||
}
|
||||
|
||||
_menuCategories[categoryId].MenuFactories[menuId] = menuFactory;
|
||||
_menuCategories[categoryId].MenuNames[menuId] = menuName;
|
||||
if (permission != null)
|
||||
{
|
||||
_menuCategories[categoryId].MenuPermissions[menuId] = permission;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a menu from a category.
|
||||
/// </summary>
|
||||
/// <param name="categoryId">The category containing the menu.</param>
|
||||
/// <param name="menuId">The menu to unregister.</param>
|
||||
public void UnregisterMenu(string categoryId, string menuId)
|
||||
{
|
||||
if (!_menuCategories.TryGetValue(categoryId, out var category)) return;
|
||||
category.MenuFactories.Remove(menuId);
|
||||
_menuCategories[categoryId].MenuNames.Remove(menuId);
|
||||
_menuCategories[categoryId].MenuPermissions.Remove(menuId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the main admin menu for a player with accessible categories.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to create the menu for.</param>
|
||||
/// <returns>A MenuBuilder instance for the main menu.</returns>
|
||||
public MenuBuilder CreateMainMenu(CCSPlayerController player)
|
||||
{
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
var mainMenu = new MenuBuilder(localizer?["sa_title"] ?? "SimpleAdmin");
|
||||
|
||||
foreach (var category in _menuCategories.Values)
|
||||
{
|
||||
if (category.MenuFactories.Count <= 0) continue;
|
||||
// Check category permissions
|
||||
var steamId = new SteamID(player.SteamID);
|
||||
if (!AdminManager.PlayerHasPermissions(steamId, category.Permission))
|
||||
continue;
|
||||
|
||||
// Pass player to CreateCategoryMenu
|
||||
mainMenu.AddSubMenu(category.Name, () => CreateCategoryMenu(category, player),
|
||||
permission: category.Permission);
|
||||
}
|
||||
|
||||
return mainMenu;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a category submenu containing all registered menus in that category.
|
||||
/// </summary>
|
||||
/// <param name="category">The menu category to create.</param>
|
||||
/// <param name="player">The player to create the menu for.</param>
|
||||
/// <returns>A MenuBuilder instance for the category menu.</returns>
|
||||
private MenuBuilder CreateCategoryMenu(MenuCategory category, CCSPlayerController player)
|
||||
{
|
||||
var categoryMenu = new MenuBuilder(category.Name);
|
||||
|
||||
foreach (var kvp in category.MenuFactories)
|
||||
{
|
||||
var menuId = kvp.Key;
|
||||
var menuFactory = kvp.Value;
|
||||
var menuName = category.MenuNames.TryGetValue(menuId, out var name) ? name : menuId;
|
||||
var permission = category.MenuPermissions.TryGetValue(menuId, out var perm) ? perm : null;
|
||||
|
||||
// Check permissions
|
||||
if (!string.IsNullOrEmpty(permission))
|
||||
{
|
||||
var steamId = new SteamID(player.SteamID);
|
||||
if (!AdminManager.PlayerHasPermissions(steamId, permission))
|
||||
continue;
|
||||
}
|
||||
|
||||
// Call the actual factory with player parameter
|
||||
categoryMenu.AddSubMenu(menuName, () => menuFactory(player), permission: permission);
|
||||
}
|
||||
|
||||
return categoryMenu.WithBackButton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the main admin menu for a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to open the menu for.</param>
|
||||
public void OpenMainMenu(CCSPlayerController player)
|
||||
{
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
|
||||
var steamId = new SteamID(player.SteamID);
|
||||
if (!AdminManager.PlayerHasPermissions(steamId, "@css/generic"))
|
||||
{
|
||||
player.PrintToChat(localizer?["sa_prefix"] ?? "[SimpleAdmin] " +
|
||||
(localizer?["sa_no_permission"] ?? "You do not have permissions to use this command"));
|
||||
return;
|
||||
}
|
||||
|
||||
CreateMainMenu(player).OpenMenu(player);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes default menu categories (Players, Server, Admin).
|
||||
/// </summary>
|
||||
public void InitializeDefaultCategories()
|
||||
{
|
||||
var localizer = CS2_SimpleAdmin._localizer;
|
||||
|
||||
RegisterCategory("players", localizer?["sa_menu_players_manage"] ?? "Manage Players", "@css/generic");
|
||||
RegisterCategory("server", localizer?["sa_menu_server_manage"] ?? "Server Management", "@css/generic");
|
||||
// RegisterCategory("fun", localizer?["sa_menu_fun_commands"] ?? "Fun Commands", "@css/generic");
|
||||
RegisterCategory("admin", localizer?["sa_menu_admins_manage"] ?? "Admin Management", "@css/root");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method for creating category menus (for API usage).
|
||||
/// </summary>
|
||||
/// <param name="category">The menu category to create.</param>
|
||||
/// <param name="player">The player to create the menu for.</param>
|
||||
/// <returns>A MenuBuilder instance for the category menu.</returns>
|
||||
public MenuBuilder CreateCategoryMenuPublic(MenuCategory category, CCSPlayerController player)
|
||||
{
|
||||
return CreateCategoryMenu(category, player);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a menu category containing multiple menus.
|
||||
/// </summary>
|
||||
public class MenuCategory
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Permission { get; set; } = "@css/generic";
|
||||
public Dictionary<string, Func<CCSPlayerController, MenuBuilder>> MenuFactories { get; set; } = [];
|
||||
public Dictionary<string, string> MenuNames { get; set; } = [];
|
||||
public Dictionary<string, string> MenuPermissions { get; set; } = [];
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ public static class PlayersMenu
|
|||
{
|
||||
public static void OpenRealPlayersMenu(CCSPlayerController admin, string menuName, Action<CCSPlayerController, CCSPlayerController> onSelectAction, Func<CCSPlayerController, bool>? enableFilter = null)
|
||||
{
|
||||
OpenMenu(admin, menuName, onSelectAction, p => p.IsBot == false);
|
||||
OpenMenu(admin, menuName, onSelectAction, p => !p.IsBot);
|
||||
}
|
||||
|
||||
public static void OpenAdminPlayersMenu(CCSPlayerController admin, string menuName, Action<CCSPlayerController, CCSPlayerController> onSelectAction, Func<CCSPlayerController?, bool>? enableFilter = null)
|
||||
|
|
@ -37,7 +37,7 @@ public static class PlayersMenu
|
|||
var playerName = player != null && player.PlayerName.Length > 26 ? player.PlayerName[..26] : player?.PlayerName;
|
||||
|
||||
var optionName = HttpUtility.HtmlEncode(playerName);
|
||||
if (player != null && enableFilter != null && enableFilter(player) == false)
|
||||
if (player != null && enableFilter != null && !enableFilter(player))
|
||||
continue;
|
||||
|
||||
var enabled = admin.CanTarget(player);
|
||||
|
|
@ -47,7 +47,7 @@ public static class PlayersMenu
|
|||
{
|
||||
if (player != null) onSelectAction.Invoke(admin, player);
|
||||
},
|
||||
enabled == false);
|
||||
!enabled);
|
||||
}
|
||||
|
||||
if (menu != null) AdminMenu.OpenMenu(admin, menu);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
1.7.7-alpha-10
|
||||
1.7.8-beta-1
|
||||
Loading…
Add table
Add a link
Reference in a new issue