diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c93c496..6a20dea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore run: dotnet restore - name: Build @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore run: dotnet restore - name: Build diff --git a/CS2-SimpleAdmin.cs b/CS2-SimpleAdmin.cs index 402517d..fa62329 100644 --- a/CS2-SimpleAdmin.cs +++ b/CS2-SimpleAdmin.cs @@ -38,7 +38,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig "CS2-SimpleAdmin"; public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)"; public override string ModuleAuthor => "daffyy & Dliix66"; - public override string ModuleVersion => "1.3.8a"; + public override string ModuleVersion => "1.3.8b"; public CS2_SimpleAdminConfig Config { get; set; } = new(); diff --git a/Commands/basebans.cs b/Commands/basebans.cs index c6dba6c..585e91b 100644 --- a/Commands/basebans.cs +++ b/Commands/basebans.cs @@ -49,7 +49,7 @@ namespace CS2_SimpleAdmin internal void Ban(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, BanManager? banManager = null, CommandInfo? command = null) { - if (_database == null) return; + if (_database == null || player is null || !player.IsValid) return; callerName ??= caller == null ? "Console" : caller.PlayerName; @@ -58,14 +58,14 @@ namespace CS2_SimpleAdmin player.Pawn.Value!.Freeze(); } - PlayerInfo playerInfo = new PlayerInfo + PlayerInfo playerInfo = new() { SteamId = player.SteamID.ToString(), Name = player.PlayerName, IpAddress = player.IpAddress?.Split(":")[0] }; - PlayerInfo adminInfo = new PlayerInfo + PlayerInfo adminInfo = new() { SteamId = caller?.SteamID.ToString(), Name = caller?.PlayerName, @@ -79,7 +79,8 @@ namespace CS2_SimpleAdmin }); if (player.UserId.HasValue) - AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value), + CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); if (playerInfo.IpAddress != null && !bannedPlayers.Contains(playerInfo.IpAddress)) bannedPlayers.Add(playerInfo.IpAddress); diff --git a/Commands/basecommands.cs b/Commands/basecommands.cs index 18a5c2c..8eb1c26 100644 --- a/Commands/basecommands.cs +++ b/Commands/basecommands.cs @@ -409,7 +409,7 @@ namespace CS2_SimpleAdmin player.Pawn.Value!.Freeze(); } - reason = reason ?? _localizer?["sa_unknown"] ?? "Unknown"; + reason ??= _localizer?["sa_unknown"] ?? "Unknown"; if (command != null) Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); @@ -423,12 +423,14 @@ namespace CS2_SimpleAdmin player.PrintToCenter(_localizer!["sa_player_kick_message", reason, caller == null ? "Console" : caller.PlayerName]); } if (player.UserId.HasValue) - AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value, reason), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value, reason), + CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } else { if (player.UserId.HasValue) - AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value), + CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } if (caller == null || caller != null && caller.UserId != null && !silentPlayers.Contains(caller.Slot)) diff --git a/Events.cs b/Events.cs index 7c5ea63..27850e0 100644 --- a/Events.cs +++ b/Events.cs @@ -306,22 +306,34 @@ public partial class CS2_SimpleAdmin Logger.LogCritical("[OnMapStart] Expired check"); #endif + List players = Helper.GetValidPlayers(); + List<(string? IpAddress, ulong SteamID, int? UserId)> onlinePlayers = players + .Where(player => player.IpAddress != null && player.SteamID.ToString().Length == 17) + .Select(player => (player.IpAddress, player.SteamID, player.UserId)) + .ToList(); + Task.Run(async () => { - AdminSQLManager _adminManager = new AdminSQLManager(_database); - BanManager _banManager = new BanManager(_database, Config); - MuteManager _muteManager = new MuteManager(_database); + AdminSQLManager _adminManager = new(_database); + BanManager _banManager = new(_database, Config); + MuteManager _muteManager = new(_database); await _banManager.ExpireOldBans(); await _muteManager.ExpireOldMutes(); await _adminManager.DeleteOldAdmins(); + try + { + await _banManager.CheckOnlinePlayers(onlinePlayers); + } + catch { } + bannedPlayers.Clear(); Server.NextFrame(() => { try { - foreach (CCSPlayerController player in Helper.GetValidPlayers()) + foreach (CCSPlayerController player in players) { if (playerPenaltyManager.IsSlotInPenalties(player.Slot)) { @@ -412,16 +424,6 @@ public partial class CS2_SimpleAdmin await _adminManager.GiveAllFlags(); }); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - - AddTimer(3.0f, () => - { - ConVar? botQuota = ConVar.Find("bot_quota"); - - if (botQuota != null && botQuota.GetPrimitiveValue() > 0) - { - Logger.LogWarning("Due to bugs with bots (game bug), consider disabling bots by setting `bot_quota 0` in the gamemode config if your server crashes after a map change."); - } - }); } [GameEventHandler] diff --git a/Helper.cs b/Helper.cs index b6200b3..51e9e56 100644 --- a/Helper.cs +++ b/Helper.cs @@ -307,12 +307,12 @@ namespace CS2_SimpleAdmin var updatedJsonContent = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); File.WriteAllText(CfgPath, updatedJsonContent); } - + public static void TryLogCommandOnDiscord(CCSPlayerController? caller, string commandString) { if (CS2_SimpleAdmin._discordWebhookClientLog == null || CS2_SimpleAdmin._localizer == null) return; - + if (caller != null && caller.IsValid == false) caller = null; diff --git a/Managers/AdminSQLManager.cs b/Managers/AdminSQLManager.cs index 65e873a..99b3b36 100644 --- a/Managers/AdminSQLManager.cs +++ b/Managers/AdminSQLManager.cs @@ -12,7 +12,7 @@ public class AdminSQLManager // Unused for now //public static readonly ConcurrentDictionary> _adminCache = new ConcurrentDictionary>(); - public static readonly ConcurrentDictionary _adminCache = new ConcurrentDictionary(); + public static readonly ConcurrentDictionary _adminCache = new(); //public static readonly ConcurrentDictionary _adminCacheTimestamps = new ConcurrentDictionary(); diff --git a/Managers/BanManager.cs b/Managers/BanManager.cs index bd8fbe8..ee26efb 100644 --- a/Managers/BanManager.cs +++ b/Managers/BanManager.cs @@ -1,43 +1,42 @@ -using Dapper; +using CounterStrikeSharp.API; +using Dapper; using Microsoft.Extensions.Logging; using MySqlConnector; namespace CS2_SimpleAdmin; -internal class BanManager +internal class BanManager(Database database, CS2_SimpleAdminConfig config) { - private readonly Database _database; - private readonly CS2_SimpleAdminConfig _config; - - public BanManager(Database database, CS2_SimpleAdminConfig config) - { - _database = database; - _config = config; - } + private readonly Database _database = database; + private readonly CS2_SimpleAdminConfig _config = config; public async Task BanPlayer(PlayerInfo player, PlayerInfo issuer, string reason, int time = 0) { DateTime now = DateTime.UtcNow.ToLocalTime(); DateTime futureTime = now.AddMinutes(time).ToLocalTime(); - await using MySqlConnection connection = await _database.GetConnectionAsync(); - - var sql = "INSERT INTO `sa_bans` (`player_steamid`, `player_name`, `player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + - "VALUES (@playerSteamid, @playerName, @playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; - - await connection.ExecuteAsync(sql, new + try { - playerSteamid = player.SteamId, - playerName = player.Name, - playerIp = _config.BanType == 1 ? player.IpAddress : null, - adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, - adminName = issuer.Name == null ? "Console" : issuer.Name, - banReason = reason, - duration = time, - ends = futureTime, - created = now, - serverid = CS2_SimpleAdmin.ServerId - }); + await using MySqlConnection connection = await _database.GetConnectionAsync(); + + var sql = "INSERT INTO `sa_bans` (`player_steamid`, `player_name`, `player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + + "VALUES (@playerSteamid, @playerName, @playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; + + await connection.ExecuteAsync(sql, new + { + playerSteamid = player.SteamId, + playerName = player.Name, + playerIp = _config.BanType == 1 ? player.IpAddress : null, + adminSteamid = issuer.SteamId ?? "Console", + adminName = issuer.Name ?? "Console", + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + catch { } } public async Task AddBanBySteamid(string playerSteamId, PlayerInfo issuer, string reason, int time = 0) @@ -47,22 +46,26 @@ internal class BanManager DateTime now = DateTime.UtcNow.ToLocalTime(); DateTime futureTime = now.AddMinutes(time).ToLocalTime(); - await using MySqlConnection connection = await _database.GetConnectionAsync(); - - var sql = "INSERT INTO `sa_bans` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + - "VALUES (@playerSteamid, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; - - await connection.ExecuteAsync(sql, new + try { - playerSteamid = playerSteamId, - adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, - adminName = issuer.Name == null ? "Console" : issuer.Name, - banReason = reason, - duration = time, - ends = futureTime, - created = now, - serverid = CS2_SimpleAdmin.ServerId - }); + await using MySqlConnection connection = await _database.GetConnectionAsync(); + + var sql = "INSERT INTO `sa_bans` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + + "VALUES (@playerSteamid, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; + + await connection.ExecuteAsync(sql, new + { + playerSteamid = playerSteamId, + adminSteamid = issuer.SteamId ?? "Console", + adminName = issuer.Name ?? "Console", + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + catch { } } public async Task AddBanByIp(string playerIp, PlayerInfo issuer, string reason, int time = 0) @@ -72,22 +75,26 @@ internal class BanManager DateTime now = DateTime.UtcNow.ToLocalTime(); DateTime futureTime = now.AddMinutes(time).ToLocalTime(); - await using MySqlConnection connection = await _database.GetConnectionAsync(); - - var sql = "INSERT INTO `sa_bans` (`player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + - "VALUES (@playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; - - await connection.ExecuteAsync(sql, new + try { - playerIp, - adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, - adminName = issuer.Name == null ? "Console" : issuer.Name, - banReason = reason, - duration = time, - ends = futureTime, - created = now, - serverid = CS2_SimpleAdmin.ServerId - }); + await using MySqlConnection connection = await _database.GetConnectionAsync(); + + var sql = "INSERT INTO `sa_bans` (`player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + + "VALUES (@playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; + + await connection.ExecuteAsync(sql, new + { + playerIp, + adminSteamid = issuer.SteamId ?? "Console", + adminName = issuer.Name ?? "Console", + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + catch { } } public async Task IsPlayerBanned(PlayerInfo player) @@ -143,21 +150,27 @@ internal class BanManager public async Task GetPlayerBans(PlayerInfo player) { - string sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP)"; - int banCount; - - await using MySqlConnection connection = await _database.GetConnectionAsync(); - - if (!string.IsNullOrEmpty(player.IpAddress)) + try { - banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = player.IpAddress }); - } - else - { - banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = DBNull.Value }); - } + string sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP)"; + int banCount; - return banCount; + await using MySqlConnection connection = await _database.GetConnectionAsync(); + + if (!string.IsNullOrEmpty(player.IpAddress)) + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = player.IpAddress }); + } + else + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = DBNull.Value }); + } + + return banCount; + } + catch { } + + return 0; } public async Task UnbanPlayer(string playerPattern) @@ -166,11 +179,48 @@ internal class BanManager { return; } + try + { + await using MySqlConnection connection = await _database.GetConnectionAsync(); - await using MySqlConnection connection = await _database.GetConnectionAsync(); + string sqlUnban = "UPDATE sa_bans SET status = 'UNBANNED' WHERE player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern AND status = 'ACTIVE'"; + await connection.ExecuteAsync(sqlUnban, new { pattern = playerPattern }); - string sqlUnban = "UPDATE sa_bans SET status = 'UNBANNED' WHERE player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern AND status = 'ACTIVE'"; - await connection.ExecuteAsync(sqlUnban, new { pattern = playerPattern }); + } + catch { } + } + + public async Task CheckOnlinePlayers(List<(string? IpAddress, ulong SteamID, int? UserId)> players) + { + try + { + await using MySqlConnection connection = await _database.GetConnectionAsync(); + string sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP) AND status = 'ACTIVE'"; + + foreach (var (IpAddress, SteamID, UserId) in players) + { + if (!UserId.HasValue) continue; + + int banCount = 0; + if (!string.IsNullOrEmpty(IpAddress)) + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = SteamID, PlayerIP = IpAddress }); + } + else + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = SteamID, PlayerIP = DBNull.Value }); + } + + if (banCount > 0) + { + Server.NextFrame(() => + { + Helper.KickPlayer(UserId.Value, "Banned"); + }); + } + } + } + catch { } } public async Task ExpireOldBans() diff --git a/Menus/ManagePlayersMenu.cs b/Menus/ManagePlayersMenu.cs index 399080f..7825838 100644 --- a/Menus/ManagePlayersMenu.cs +++ b/Menus/ManagePlayersMenu.cs @@ -20,7 +20,7 @@ namespace CS2_SimpleAdmin.Menus } BaseMenu menu = AdminMenu.CreateMenu("Manage Players"); - List options = new(); + List options = []; // permissions bool hasSlay = AdminManager.PlayerHasPermissions(admin, "@css/slay"); @@ -71,15 +71,16 @@ namespace CS2_SimpleAdmin.Menus private static void SlapMenu(CCSPlayerController admin, CCSPlayerController player) { BaseMenu menu = AdminMenu.CreateMenu($"Slap: {player.PlayerName}"); - List options = new(); - - // options added in order - options.Add(new ChatMenuOptionData("0 hp", () => ApplySlapAndKeepMenu(admin, player, 0))); - options.Add(new ChatMenuOptionData("1 hp", () => ApplySlapAndKeepMenu(admin, player, 1))); - options.Add(new ChatMenuOptionData("5 hp", () => ApplySlapAndKeepMenu(admin, player, 5))); - options.Add(new ChatMenuOptionData("10 hp", () => ApplySlapAndKeepMenu(admin, player, 10))); - options.Add(new ChatMenuOptionData("50 hp", () => ApplySlapAndKeepMenu(admin, player, 50))); - options.Add(new ChatMenuOptionData("100 hp", () => ApplySlapAndKeepMenu(admin, player, 100))); + List options = + [ + // options added in order + new ChatMenuOptionData("0 hp", () => ApplySlapAndKeepMenu(admin, player, 0)), + new ChatMenuOptionData("1 hp", () => ApplySlapAndKeepMenu(admin, player, 1)), + new ChatMenuOptionData("5 hp", () => ApplySlapAndKeepMenu(admin, player, 5)), + new ChatMenuOptionData("10 hp", () => ApplySlapAndKeepMenu(admin, player, 10)), + new ChatMenuOptionData("50 hp", () => ApplySlapAndKeepMenu(admin, player, 50)), + new ChatMenuOptionData("100 hp", () => ApplySlapAndKeepMenu(admin, player, 100)), + ]; foreach (ChatMenuOptionData menuOptionData in options) { @@ -92,29 +93,37 @@ namespace CS2_SimpleAdmin.Menus private static void ApplySlapAndKeepMenu(CCSPlayerController admin, CCSPlayerController player, int damage) { - CS2_SimpleAdmin.Instance.Slap(admin, player, damage); - SlapMenu(admin, player); + if (player is not null && player.IsValid) + { + CS2_SimpleAdmin.Instance.Slap(admin, player, damage); + SlapMenu(admin, player); + } } private static void Slay(CCSPlayerController admin, CCSPlayerController player) { - CS2_SimpleAdmin.Instance.Slay(admin, player); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Slay(admin, player); } private static void KickMenu(CCSPlayerController admin, CCSPlayerController player) { BaseMenu menu = AdminMenu.CreateMenu($"Kick: {player.PlayerName}"); - List options = new() - { + List options = + [ "Voice Abuse", "Chat Abuse", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Kick(admin, player, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Kick(admin, player, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -122,24 +131,29 @@ namespace CS2_SimpleAdmin.Menus private static void Kick(CCSPlayerController admin, CCSPlayerController player, string reason) { - CS2_SimpleAdmin.Instance.Kick(admin, player, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Kick(admin, player, reason); } private static void BanMenu(CCSPlayerController admin, CCSPlayerController player, int duration) { BaseMenu menu = AdminMenu.CreateMenu($"Ban: {player.PlayerName}"); - List options = new() - { + List options = + [ "Hacking", "Voice Abuse", "Chat Abuse", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Ban(admin, player, duration, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Ban(admin, player, duration, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -147,26 +161,31 @@ namespace CS2_SimpleAdmin.Menus private static void Ban(CCSPlayerController admin, CCSPlayerController player, int duration, string reason) { - CS2_SimpleAdmin.Instance.Ban(admin, player, duration, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Ban(admin, player, duration, reason); } private static void GagMenu(CCSPlayerController admin, CCSPlayerController player, int duration) { // TODO: Localize and make options in config? BaseMenu menu = AdminMenu.CreateMenu($"Gag: {player.PlayerName}"); - List options = new() - { + List options = + [ "Advertising", "Spamming", "Spectator camera abuse", "Hate", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Gag(admin, player, duration, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Gag(admin, player, duration, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -174,15 +193,16 @@ namespace CS2_SimpleAdmin.Menus private static void Gag(CCSPlayerController admin, CCSPlayerController player, int duration, string reason) { - CS2_SimpleAdmin.Instance.Gag(admin, player, duration, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Gag(admin, player, duration, reason); } private static void MuteMenu(CCSPlayerController admin, CCSPlayerController player, int duration) { // TODO: Localize and make options in config? BaseMenu menu = AdminMenu.CreateMenu($"Mute: {player.PlayerName}"); - List options = new() - { + List options = + [ "Shouting", "Playing music", "Advertising", @@ -191,11 +211,15 @@ namespace CS2_SimpleAdmin.Menus "Hate", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Mute(admin, player, duration, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Mute(admin, player, duration, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -203,15 +227,16 @@ namespace CS2_SimpleAdmin.Menus private static void Mute(CCSPlayerController admin, CCSPlayerController player, int duration, string reason) { - CS2_SimpleAdmin.Instance.Mute(admin, player, duration, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Mute(admin, player, duration, reason); } private static void SilenceMenu(CCSPlayerController admin, CCSPlayerController player, int duration) { // TODO: Localize and make options in config? BaseMenu menu = AdminMenu.CreateMenu($"Silence: {player.PlayerName}"); - List options = new() - { + List options = + [ "Shouting", "Playing music", "Advertising", @@ -220,11 +245,15 @@ namespace CS2_SimpleAdmin.Menus "Hate", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Silence(admin, player, duration, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Silence(admin, player, duration, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -232,18 +261,21 @@ namespace CS2_SimpleAdmin.Menus private static void Silence(CCSPlayerController admin, CCSPlayerController player, int duration, string reason) { - CS2_SimpleAdmin.Instance.Silence(admin, player, duration, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Silence(admin, player, duration, reason); } private static void ForceTeamMenu(CCSPlayerController admin, CCSPlayerController player) { // TODO: Localize BaseMenu menu = AdminMenu.CreateMenu($"Force {player.PlayerName}'s Team"); - List options = new(); - options.Add(new ChatMenuOptionData("CT", () => ForceTeam(admin, player, "ct", CsTeam.CounterTerrorist))); - options.Add(new ChatMenuOptionData("T", () => ForceTeam(admin, player, "t", CsTeam.Terrorist))); - options.Add(new ChatMenuOptionData("Swap", () => ForceTeam(admin, player, "swap", CsTeam.Spectator))); - options.Add(new ChatMenuOptionData("Spectator", () => ForceTeam(admin, player, "spec", CsTeam.Spectator))); + List options = + [ + new ChatMenuOptionData("CT", () => ForceTeam(admin, player, "ct", CsTeam.CounterTerrorist)), + new ChatMenuOptionData("T", () => ForceTeam(admin, player, "t", CsTeam.Terrorist)), + new ChatMenuOptionData("Swap", () => ForceTeam(admin, player, "swap", CsTeam.Spectator)), + new ChatMenuOptionData("Spectator", () => ForceTeam(admin, player, "spec", CsTeam.Spectator)), + ]; foreach (ChatMenuOptionData menuOptionData in options) { @@ -256,7 +288,8 @@ namespace CS2_SimpleAdmin.Menus private static void ForceTeam(CCSPlayerController admin, CCSPlayerController player, string teamName, CsTeam teamNum) { - CS2_SimpleAdmin.Instance.ChangeTeam(admin, player, teamName, teamNum, true); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.ChangeTeam(admin, player, teamName, teamNum, true); } } } \ No newline at end of file