Migrate menus and votes to Panorama UI Kit

Replace MenuManagerCS2 with Panorama UI Kit for the admin menus and
css_vote. Layout names (menu, vote, banner, toast) are configurable
under MenuConfig and preloaded on startup; MenuType is removed and
ConfigVersion bumped to 26.

- Drop MenuManagerApi.dll and the old chat menu classes
- Reference PanoramaUiKit.Shared.dll, bump CounterStrikeSharp to 1.0.376
- Add .editorconfig and CODING_CONVENTIONS.md, apply them codebase-wide
- Remove the CS2-SimpleAdmin-docs site
- Rewrite README for the fork
This commit is contained in:
Salvatore 2026-10-21 18:51:18 +02:00
parent 03a454b1b5
commit 460d8b2b85
112 changed files with 5559 additions and 36371 deletions

View file

@ -2,6 +2,7 @@ using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Admin;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Commands.Targeting;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.ValveConstants.Protobuf;
using CS2_SimpleAdmin.Managers;
@ -21,34 +22,38 @@ public partial class CS2_SimpleAdmin
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnBanCommand(CCSPlayerController? caller, CommandInfo command)
{
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
string callerName = Helper.GetCallerName(caller);
if (command.ArgCount < 2)
{
return;
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, Connected: PlayerConnectedState.Connected, IsHLTV: false }).ToList();
}
TargetResult? targets = GetTarget(command);
if (targets == null)
{
return;
}
List<CCSPlayerController> playersToTarget = targets.Players.Where(player => player is { IsValid: true, Connected: PlayerConnectedState.Connected, IsHLTV: false }).ToList();
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
{
return;
}
var reason = command.ArgCount >= 3
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
: _localizer?["sa_unknown"] ?? "Unknown";
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
var time = Helper.ParsePenaltyTime(command.GetArg(2));
string reason = Helper.GetArgsReason(command, 3);
int time = Helper.ParsePenaltyTime(command.GetArg(2));
playersToTarget.ForEach(player =>
{
if (!caller.CanTarget(player)) return;
if (!caller.CanTarget(player))
{
return;
}
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
{
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_ban"] ?? "Ban"}: {player.PlayerName}", player,
ManagePlayersMenu.BanMenu);
BasicMenu.CreatePenaltyMenu(caller, player, PenaltyType.Ban).OpenMenu(caller);
return;
}
@ -69,18 +74,27 @@ public partial class CS2_SimpleAdmin
/// <param name="silent">If true, suppresses command logging.</param>
internal void Ban(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, BanManager? banManager = null, CommandInfo? command = null, bool silent = false)
{
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue) return;
if (!caller.CanTarget(player)) return;
if (!CheckValidBan(caller, time)) return;
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue)
{
return;
}
if (!caller.CanTarget(player))
{
return;
}
if (!CheckValidBan(caller, time))
{
return;
}
// Set default caller name if not provided
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
? caller.PlayerName
: (_localizer?["sa_console"] ?? "Console");
callerName = Helper.GetCallerName(caller);
// Get player and admin information
var playerInfo = PlayersInfo[player.SteamID];
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
PlayerInfo playerInfo = PlayersInfo[player.SteamID];
PlayerInfo? adminInfo = Helper.GetAdminInfo(caller);
// Asynchronously handle banning logic
Task.Run(async () =>
@ -93,13 +107,25 @@ public partial class CS2_SimpleAdmin
});
// Determine message keys and arguments based on ban time
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) = time == 0
? ("sa_player_ban_message_perm", "sa_admin_ban_message_perm",
[reason, "CALLER"],
["CALLER", player.PlayerName, reason])
: ("sa_player_ban_message_time", "sa_admin_ban_message_time",
new object[] { reason, time, "CALLER" },
new object[] { "CALLER", player.PlayerName, reason, time });
string? messageKey;
string? activityMessageKey;
object[]? centerArgs;
object[]? adminActivityArgs;
if (time == 0)
{
messageKey = "sa_player_ban_message_perm";
activityMessageKey = "sa_admin_ban_message_perm";
centerArgs = [reason, "CALLER"];
adminActivityArgs = ["CALLER", player.PlayerName, reason];
}
else
{
messageKey = "sa_player_ban_message_time";
activityMessageKey = "sa_admin_ban_message_time";
centerArgs = new object[] { reason, time, "CALLER" };
adminActivityArgs = new object[] { "CALLER", player.PlayerName, reason, time };
}
// Display center message to the player
Helper.DisplayCenterMessage(player, messageKey, callerName, centerArgs);
@ -125,11 +151,15 @@ public partial class CS2_SimpleAdmin
if (!silent)
{
if (command == null)
Helper.LogCommand(caller, $"css_ban {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
{
Helper.LogCommand(caller, $"css_ban {Helper.GetLogName(player)} {time} {reason}");
}
else
{
Helper.LogCommand(caller, command);
}
}
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Ban, _localizer);
}
@ -144,23 +174,26 @@ public partial class CS2_SimpleAdmin
internal void AddBan(CCSPlayerController? caller, SteamID steamid, int time, string reason, BanManager? banManager = null)
{
// Set default caller name if not provided
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
? caller.PlayerName
: (_localizer?["sa_console"] ?? "Console");
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
string callerName = Helper.GetCallerName(caller);
PlayerInfo? adminInfo = Helper.GetAdminInfo(caller);
CCSPlayerController? player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
if (player != null && player.IsValid)
{
if (!caller.CanTarget(player))
{
return;
}
Ban(caller, player, time, reason, callerName, silent: true);
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
}
else
{
if (!caller.CanTarget(steamid))
{
return;
}
// Asynchronous ban operation if player is not online or not found
Task.Run(async () =>
{
@ -171,7 +204,7 @@ public partial class CS2_SimpleAdmin
penaltyId);
});
});
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Ban, _localizer);
}
}
@ -185,34 +218,41 @@ public partial class CS2_SimpleAdmin
[CommandHelper(minArgs: 1, usage: "<steamid> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnAddBanCommand(CCSPlayerController? caller, CommandInfo command)
{
if (DatabaseProvider == null) return;
var callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
if (DatabaseProvider == null)
{
return;
}
string callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1)))
{
return;
}
if (!Helper.ValidateSteamId(command.GetArg(1), out SteamID? steamId) || steamId == null)
{
command.ReplyToCommand("Invalid SteamID64.");
return;
}
var steamid = steamId.SteamId64;
var reason = command.ArgCount >= 3
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
: _localizer?["sa_unknown"] ?? "Unknown";
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
ulong steamid = steamId.SteamId64;
string reason = Helper.GetArgsReason(command, 3);
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
if (!CheckValidBan(caller, time)) return;
int time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
if (!CheckValidBan(caller, time))
{
return;
}
var adminInfo = caller != null && caller.UserId.HasValue
? PlayersInfo[caller.SteamID]
: null;
PlayerInfo? adminInfo = Helper.GetAdminInfo(caller);
var player = Helper.GetPlayerFromSteamid64(steamid);
CCSPlayerController? player = Helper.GetPlayerFromSteamid64(steamid);
if (player != null && player.IsValid)
{
if (!caller.CanTarget(player))
{
return;
}
Ban(caller, player, time, reason, callerName, silent: true);
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
@ -220,8 +260,10 @@ public partial class CS2_SimpleAdmin
else
{
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
{
return;
}
// Asynchronous ban operation if player is not online or not found
Task.Run(async () =>
{
@ -232,7 +274,7 @@ public partial class CS2_SimpleAdmin
penaltyId);
});
});
Helper.SendDiscordPenaltyMessage(caller, steamid.ToString(), reason, time, PenaltyType.Ban, _localizer);
command.ReplyToCommand($"Player with steamid {steamid} is not online. Ban has been added offline.");
@ -241,7 +283,9 @@ public partial class CS2_SimpleAdmin
Helper.LogCommand(caller, command);
if (UnlockedCommands)
{
Server.ExecuteCommand($"banid 1 {steamId.SteamId3}");
}
}
/// <summary>
@ -253,10 +297,18 @@ public partial class CS2_SimpleAdmin
[CommandHelper(minArgs: 1, usage: "<ip> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnBanIpCommand(CCSPlayerController? caller, CommandInfo command)
{
if (DatabaseProvider == null) return;
var callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
var ipAddress = command.GetArg(1);
if (DatabaseProvider == null)
{
return;
}
string callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1)))
{
return;
}
string ipAddress = command.GetArg(1);
if (!Helper.IsValidIp(ipAddress))
{
@ -264,28 +316,31 @@ public partial class CS2_SimpleAdmin
return;
}
var reason = command.ArgCount >= 3
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
: _localizer?["sa_unknown"] ?? "Unknown";
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
string reason = Helper.GetArgsReason(command, 3);
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
int time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
if (!CheckValidBan(caller, time)) return;
if (!CheckValidBan(caller, time))
{
return;
}
var adminInfo = caller != null && caller.UserId.HasValue
? PlayersInfo[caller.SteamID]
: null;
PlayerInfo? adminInfo = Helper.GetAdminInfo(caller);
var players = Helper.GetPlayerFromIp(ipAddress);
List<CCSPlayerController> players = Helper.GetPlayerFromIp(ipAddress);
if (players.Count >= 1)
{
foreach (var player in players)
foreach (CCSPlayerController player in players)
{
if (player == null || !player.IsValid) continue;
if (player == null || !player.IsValid)
{
continue;
}
if (!caller.CanTarget(player))
{
return;
}
Ban(caller, player, time, reason, callerName, silent: true);
}
@ -312,9 +367,12 @@ public partial class CS2_SimpleAdmin
/// <returns>True if ban duration is valid; otherwise, false.</returns>
private bool CheckValidBan(CCSPlayerController? caller, int duration)
{
if (caller == null) return true;
if (caller == null)
{
return true;
}
var canPermBan = AdminManager.PlayerHasPermissions(new SteamID(caller.SteamID), "@css/permban");
bool canPermBan = AdminManager.PlayerHasPermissions(new SteamID(caller.SteamID), "@css/permban");
if (duration <= 0 && !canPermBan)
{
@ -322,7 +380,10 @@ public partial class CS2_SimpleAdmin
return false;
}
if (duration <= Config.OtherSettings.MaxBanDuration || canPermBan) return true;
if (duration <= Config.OtherSettings.MaxBanDuration || canPermBan)
{
return true;
}
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_max_duration_exceeded", Config.OtherSettings.MaxBanDuration]}");
return false;
@ -337,20 +398,20 @@ public partial class CS2_SimpleAdmin
[CommandHelper(minArgs: 1, usage: "<steamid or name or ip> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnUnbanCommand(CCSPlayerController? caller, CommandInfo command)
{
if (DatabaseProvider == null) return;
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
if (DatabaseProvider == null)
{
return;
}
string callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
if (command.GetArg(1).Length <= 1)
{
command.ReplyToCommand($"Too short pattern to search.");
return;
}
var pattern = command.GetArg(1);
var reason = command.ArgCount >= 2
? string.Join(" ", Enumerable.Range(2, command.ArgCount - 2).Select(command.GetArg)).Trim()
: _localizer?["sa_unknown"] ?? "Unknown";
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
string pattern = command.GetArg(1);
string reason = Helper.GetArgsReason(command, 2);
Task.Run(async () => await BanManager.UnbanPlayer(pattern, callerSteamId, reason));
Helper.LogCommand(caller, command);
command.ReplyToCommand($"Unbanned player with pattern {pattern}.");
@ -366,26 +427,31 @@ public partial class CS2_SimpleAdmin
public void OnWarnCommand(CCSPlayerController? caller, CommandInfo command)
{
if (DatabaseProvider == null)
{
return;
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
}
string callerName = Helper.GetCallerName(caller);
if (command.ArgCount < 2)
{
return;
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player.Connected == PlayerConnectedState.Connected && !player.IsHLTV).ToList();
}
TargetResult? targets = GetTarget(command);
if (targets == null)
{
return;
}
List<CCSPlayerController> playersToTarget = targets.Players.Where(player => player.IsValid && player.Connected == PlayerConnectedState.Connected && !player.IsHLTV).ToList();
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
{
return;
}
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
var reason = command.ArgCount >= 3
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
: _localizer?["sa_unknown"] ?? "Unknown";
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
int time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
string reason = Helper.GetArgsReason(command, 3);
playersToTarget.ForEach(player =>
{
@ -407,14 +473,23 @@ public partial class CS2_SimpleAdmin
/// <param name="command">Optional command info for logging.</param>
internal void Warn(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, CommandInfo? command = null)
{
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue) return;
if (!caller.CanTarget(player)) return;
if (!CheckValidBan(caller, time)) return;
if (DatabaseProvider == null || !player.IsValid || !player.UserId.HasValue)
{
return;
}
if (!caller.CanTarget(player))
{
return;
}
if (!CheckValidBan(caller, time))
{
return;
}
// Set default caller name if not provided
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
? caller.PlayerName
: (_localizer?["sa_console"] ?? "Console");
callerName = Helper.GetCallerName(caller);
// Freeze player pawn if alive
if (player.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE)
@ -424,8 +499,8 @@ public partial class CS2_SimpleAdmin
}
// Get player and admin information
var playerInfo = PlayersInfo[player.SteamID];
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
PlayerInfo playerInfo = PlayersInfo[player.SteamID];
PlayerInfo? adminInfo = Helper.GetAdminInfo(caller);
// Asynchronously handle warning logic
Task.Run(async () =>
@ -438,16 +513,20 @@ public partial class CS2_SimpleAdmin
});
// Check for warn thresholds and execute punish command if applicable
var totalWarns = await WarnManager.GetPlayerWarnsCount(player.SteamID);
int totalWarns = await WarnManager.GetPlayerWarnsCount(player.SteamID);
if (Config.WarnThreshold.Count > 0)
{
string? punishCommand = null;
var lastKey = Config.WarnThreshold.Keys.Max();
int lastKey = Config.WarnThreshold.Keys.Max();
if (totalWarns >= lastKey)
{
punishCommand = Config.WarnThreshold[lastKey];
else if (Config.WarnThreshold.TryGetValue(totalWarns, out var value))
}
else if (Config.WarnThreshold.TryGetValue(totalWarns, out string? value))
{
punishCommand = value;
}
if (!string.IsNullOrEmpty(punishCommand))
{
@ -460,13 +539,25 @@ public partial class CS2_SimpleAdmin
});
// Determine message keys and arguments based on warning time
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) = time == 0
? ("sa_player_warn_message_perm", "sa_admin_warn_message_perm",
new object[] { reason, "CALLER" },
new object[] { "CALLER", player.PlayerName, reason })
: ("sa_player_warn_message_time", "sa_admin_warn_message_time",
[reason, time, "CALLER"],
["CALLER", player.PlayerName, reason, time]);
string? messageKey;
string? activityMessageKey;
object[]? centerArgs;
object[]? adminActivityArgs;
if (time == 0)
{
messageKey = "sa_player_warn_message_perm";
activityMessageKey = "sa_admin_warn_message_perm";
centerArgs = new object[] { reason, "CALLER" };
adminActivityArgs = new object[] { "CALLER", player.PlayerName, reason };
}
else
{
messageKey = "sa_player_warn_message_time";
activityMessageKey = "sa_admin_warn_message_time";
centerArgs = [reason, time, "CALLER"];
adminActivityArgs = ["CALLER", player.PlayerName, reason, time];
}
// Display center message to the playser
Helper.DisplayCenterMessage(player, messageKey, callerName, centerArgs);
@ -479,14 +570,18 @@ public partial class CS2_SimpleAdmin
// Log the warning command
if (command == null)
Helper.LogCommand(caller, $"css_warn {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
{
Helper.LogCommand(caller, $"css_warn {Helper.GetLogName(player)} {time} {reason}");
}
else
{
Helper.LogCommand(caller, command);
}
// Send Discord notification for the warning
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Warn, _localizer);
}
/// <summary>
/// Adds a warning to a player by their SteamID, including support for offline players.
/// </summary>
@ -498,18 +593,18 @@ public partial class CS2_SimpleAdmin
internal void AddWarn(CCSPlayerController? caller, SteamID steamid, int time, string reason, WarnManager? warnManager = null)
{
// Set default caller name if not provided
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
? caller.PlayerName
: (_localizer?["sa_console"] ?? "Console");
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.SteamID] : null;
string callerName = Helper.GetCallerName(caller);
var player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
PlayerInfo? adminInfo = Helper.GetAdminInfo(caller);
CCSPlayerController? player = Helper.GetPlayerFromSteamid64(steamid.SteamId64);
if (player != null && player.IsValid)
{
if (!caller.CanTarget(player))
{
return;
}
Warn(caller, player, time, reason, callerName);
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
@ -517,8 +612,10 @@ public partial class CS2_SimpleAdmin
else
{
if (!caller.CanTarget(steamid))
{
return;
}
// Asynchronous ban operation if player is not online or not found
Task.Run(async () =>
{
@ -530,16 +627,20 @@ public partial class CS2_SimpleAdmin
});
// Check for warn thresholds and execute punish command if applicable
var totalWarns = await WarnManager.GetPlayerWarnsCount(steamid.SteamId64);
int totalWarns = await WarnManager.GetPlayerWarnsCount(steamid.SteamId64);
if (Config.WarnThreshold.Count > 0)
{
string? punishCommand = null;
var lastKey = Config.WarnThreshold.Keys.Max();
int lastKey = Config.WarnThreshold.Keys.Max();
if (totalWarns >= lastKey)
{
punishCommand = Config.WarnThreshold[lastKey];
else if (Config.WarnThreshold.TryGetValue(totalWarns, out var value))
}
else if (Config.WarnThreshold.TryGetValue(totalWarns, out string? value))
{
punishCommand = value;
}
if (!string.IsNullOrEmpty(punishCommand))
{
@ -550,11 +651,11 @@ public partial class CS2_SimpleAdmin
}
}
});
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Warn, _localizer);
}
}
/// <summary>
/// Handles removing a warning (unwarn) by a pattern string.
/// </summary>
@ -564,7 +665,10 @@ public partial class CS2_SimpleAdmin
[CommandHelper(minArgs: 1, usage: "<steamid or name or ip>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnUnwarnCommand(CCSPlayerController? caller, CommandInfo command)
{
if (DatabaseProvider == null) return;
if (DatabaseProvider == null)
{
return;
}
if (command.GetArg(1).Length <= 1)
{
@ -572,9 +676,9 @@ public partial class CS2_SimpleAdmin
return;
}
var pattern = command.GetArg(1);
string pattern = command.GetArg(1);
Task.Run(async () => await WarnManager.UnwarnPlayer(pattern));
Helper.LogCommand(caller, command);
command.ReplyToCommand($"Unwarned player with pattern {pattern}.");
}
}
}