From c2e8b4a8985ce377cd2119810d3eecae9eb1969e Mon Sep 17 00:00:00 2001 From: Dawid Bepierszcz <41084667+daffyyyy@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:37:14 +0100 Subject: [PATCH] Refactor player cache and ban checks, update version Improves player cache handling and ban status checks for race condition safety. Removes unused GodPlayers logic and related event handler. Refactors event handlers for disconnect and team changes, and fixes warn reason field naming. Updates version to 1.7.8-beta-7. --- CS2-SimpleAdmin/CS2-SimpleAdmin.cs | 5 ++- CS2-SimpleAdmin/Events.cs | 43 ++++++------------ CS2-SimpleAdmin/Helper.cs | 2 +- CS2-SimpleAdmin/Managers/CacheManager.cs | 55 ++++++++++++++++------- CS2-SimpleAdmin/Managers/PlayerManager.cs | 9 +--- CS2-SimpleAdmin/Managers/WarnManager.cs | 6 +-- CS2-SimpleAdmin/VERSION | 2 +- CS2-SimpleAdmin/Variables.cs | 1 - 8 files changed, 62 insertions(+), 61 deletions(-) diff --git a/CS2-SimpleAdmin/CS2-SimpleAdmin.cs b/CS2-SimpleAdmin/CS2-SimpleAdmin.cs index 03483b6..24d4a8a 100644 --- a/CS2-SimpleAdmin/CS2-SimpleAdmin.cs +++ b/CS2-SimpleAdmin/CS2-SimpleAdmin.cs @@ -22,7 +22,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)"); public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)"; public override string ModuleAuthor => "daffyy"; - public override string ModuleVersion => "1.7.8-beta-6"; + public override string ModuleVersion => "1.7.8-beta-7"; public override void Load(bool hotReload) { @@ -46,7 +46,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig p.IsValid && !p.IsHLTV).ToArray()) + foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.Connected == PlayerConnectedState.PlayerConnected && !p.IsHLTV).ToArray()) { if (!player.IsBot) PlayerManager.LoadPlayerData(player, true); @@ -260,6 +260,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig= 1 }) - { - SilentPlayers.Remove(player.Slot); - SimpleAdminApi?.OnAdminToggleSilentEvent(player.Slot, false); - } + if (@event is not { Oldteam: <= 1, Team: >= 1 }) return HookResult.Continue; + + SilentPlayers.Remove(player.Slot); + SimpleAdminApi?.OnAdminToggleSilentEvent(player.Slot, false); return HookResult.Continue; } diff --git a/CS2-SimpleAdmin/Helper.cs b/CS2-SimpleAdmin/Helper.cs index b7573d4..a15660c 100644 --- a/CS2-SimpleAdmin/Helper.cs +++ b/CS2-SimpleAdmin/Helper.cs @@ -64,7 +64,7 @@ internal static class Helper public static List GetValidPlayers() { - return CS2_SimpleAdmin.CachedPlayers.AsValueEnumerable().Where(p => p.Connected == PlayerConnectedState.PlayerConnected).ToList(); + return CS2_SimpleAdmin.CachedPlayers.AsValueEnumerable().Where(p => p.IsValid && p.Connected == PlayerConnectedState.PlayerConnected).ToList(); } public static List GetValidPlayersWithBots() diff --git a/CS2-SimpleAdmin/Managers/CacheManager.cs b/CS2-SimpleAdmin/Managers/CacheManager.cs index fe2a3c8..8e8867f 100644 --- a/CS2-SimpleAdmin/Managers/CacheManager.cs +++ b/CS2-SimpleAdmin/Managers/CacheManager.cs @@ -323,13 +323,19 @@ internal class CacheManager: IDisposable } // Update cache with new/modified bans + var needsRebuild = false; foreach (var ban in updatedBans) { + if (_banCache.TryGetValue(ban.Id, out var oldBan) && oldBan.Status != ban.Status) + { + // Ban status changed (e.g., ACTIVE -> EXPIRED/UNBANNED), need to rebuild indexes + needsRebuild = true; + } _banCache.AddOrUpdate(ban.Id, ban, (_, _) => ban); } - // Rebuild indexes if there were updates - if (updatedBans.Any()) + // Rebuild indexes if there were updates or status changes + if (updatedBans.Any() || needsRebuild) { RebuildIndexes(); } @@ -480,13 +486,17 @@ internal class CacheManager: IDisposable record = steamRecords.FirstOrDefault(r => r.StatusEnum == BanStatus.ACTIVE); if (record != null) { - if ((string.IsNullOrEmpty(record.PlayerIp) && !string.IsNullOrEmpty(ipAddress)) || - (!record.PlayerSteamId.HasValue)) + // Double-check the ban is still active in cache (handle race conditions) + if (_banCache.TryGetValue(record.Id, out var cachedBan) && cachedBan.StatusEnum == BanStatus.ACTIVE) { - _ = Task.Run(() => UpdatePlayerData(playerName, steamId, ipAddress)); - } + if ((string.IsNullOrEmpty(record.PlayerIp) && !string.IsNullOrEmpty(ipAddress)) || + (!record.PlayerSteamId.HasValue)) + { + _ = Task.Run(() => UpdatePlayerData(playerName, steamId, ipAddress)); + } - return true; + return true; + } } } @@ -497,15 +507,20 @@ internal class CacheManager: IDisposable !IpHelper.TryConvertIpToUint(ipAddress, out var ipUInt) || _cachedIgnoredIps.Contains(ipUInt) || !_ipIndex.TryGetValue(ipUInt, out var ipRecords)) return false; - + record = ipRecords.FirstOrDefault(r => r.StatusEnum == BanStatus.ACTIVE); if (record == null) return false; + + // Double-check the ban is still active in cache (handle race conditions) + if (!_banCache.TryGetValue(record.Id, out var cachedBanIp) || cachedBanIp.StatusEnum != BanStatus.ACTIVE) + return false; + if ((string.IsNullOrEmpty(record.PlayerIp) && !string.IsNullOrEmpty(ipAddress)) || (!record.PlayerSteamId.HasValue && steamId.HasValue)) { _ = Task.Run(() => UpdatePlayerData(playerName, steamId, ipAddress)); } - + return true; } @@ -591,10 +606,14 @@ internal class CacheManager: IDisposable var activeBan = steamBans.FirstOrDefault(b => b.StatusEnum == BanStatus.ACTIVE); if (activeBan != null) { - if (string.IsNullOrEmpty(activeBan.PlayerName) || string.IsNullOrEmpty(activeBan.PlayerIp) && !string.IsNullOrEmpty(ipAddress)) - _ = Task.Run(() => UpdatePlayerData(playerName, steamId, ipAddress)); - - return true; + // Double-check the ban is still active in cache (handle race conditions) + if (_banCache.TryGetValue(activeBan.Id, out var cachedBan) && cachedBan.StatusEnum == BanStatus.ACTIVE) + { + if (string.IsNullOrEmpty(activeBan.PlayerName) || string.IsNullOrEmpty(activeBan.PlayerIp) && !string.IsNullOrEmpty(ipAddress)) + _ = Task.Run(() => UpdatePlayerData(playerName, steamId, ipAddress)); + + return true; + } } } @@ -620,16 +639,20 @@ internal class CacheManager: IDisposable if (ipRecord.UsedAt < cutoff || _cachedIgnoredIps.Contains(ipRecord.Ip)) continue; - if (!_ipIndex.TryGetValue(ipRecord.Ip, out var banRecords)) + if (!_ipIndex.TryGetValue(ipRecord.Ip, out var banRecords)) continue; var activeBan = banRecords.FirstOrDefault(r => r.StatusEnum == BanStatus.ACTIVE); - if (activeBan == null) + if (activeBan == null) + continue; + + // Double-check the ban is still active in cache (handle race conditions) + if (!_banCache.TryGetValue(activeBan.Id, out var cachedBan) || cachedBan.StatusEnum != BanStatus.ACTIVE) continue; if (string.IsNullOrEmpty(activeBan.PlayerName)) activeBan.PlayerName = unknownName; - + activeBan.PlayerSteamId ??= steamId; _ = Task.Run(() => UpdatePlayerData(playerName, steamId, ipAddress)); diff --git a/CS2-SimpleAdmin/Managers/PlayerManager.cs b/CS2-SimpleAdmin/Managers/PlayerManager.cs index c8e84b0..e8c5c6a 100644 --- a/CS2-SimpleAdmin/Managers/PlayerManager.cs +++ b/CS2-SimpleAdmin/Managers/PlayerManager.cs @@ -80,13 +80,7 @@ internal class PlayerManager { var playerInfo = new PlayerInfo(userId, slot, new SteamID(steamId), playerName, ipAddress); CS2_SimpleAdmin.PlayersInfo[steamId] = playerInfo; - - await Server.NextWorldUpdateAsync(() => - { - if (!CS2_SimpleAdmin.CachedPlayers.Contains(player)) - CS2_SimpleAdmin.CachedPlayers.Add(player); - }); - + if (_config.OtherSettings.CheckMultiAccountsByIp && ipAddress != null && CS2_SimpleAdmin.PlayersInfo[steamId] != null) { @@ -253,6 +247,7 @@ internal class PlayerManager _loadPlayerSemaphore.Release(); } }); + if (CS2_SimpleAdmin.RenamedPlayers.TryGetValue(player.SteamID, out var name)) { player.Rename(name); diff --git a/CS2-SimpleAdmin/Managers/WarnManager.cs b/CS2-SimpleAdmin/Managers/WarnManager.cs index 0f58b84..5b87831 100644 --- a/CS2-SimpleAdmin/Managers/WarnManager.cs +++ b/CS2-SimpleAdmin/Managers/WarnManager.cs @@ -33,7 +33,7 @@ internal class WarnManager(IDatabaseProvider? databaseProvider) playerName = player.Name, adminSteamid = issuer?.SteamId.SteamId64 ?? 0, adminName = issuer?.Name ?? CS2_SimpleAdmin._localizer?["sa_console"] ?? "Console", - muteReason = reason, + warnReason = reason, duration = time, ends = futureTime, created = now, @@ -42,7 +42,7 @@ internal class WarnManager(IDatabaseProvider? databaseProvider) return warnId; } - catch + catch(Exception e) { return null; } @@ -73,7 +73,7 @@ internal class WarnManager(IDatabaseProvider? databaseProvider) playerSteamid = playerSteamId, adminSteamid = issuer?.SteamId.SteamId64 ?? 0, adminName = issuer?.Name ?? CS2_SimpleAdmin._localizer?["sa_console"] ?? "Console", - muteReason = reason, + warnReason = reason, duration = time, ends = futureTime, created = now, diff --git a/CS2-SimpleAdmin/VERSION b/CS2-SimpleAdmin/VERSION index 7361075..49c5f9b 100644 --- a/CS2-SimpleAdmin/VERSION +++ b/CS2-SimpleAdmin/VERSION @@ -1 +1 @@ -1.7.8-beta-6 \ No newline at end of file +1.7.8-beta-7 \ No newline at end of file diff --git a/CS2-SimpleAdmin/Variables.cs b/CS2-SimpleAdmin/Variables.cs index a35cc75..35424a9 100644 --- a/CS2-SimpleAdmin/Variables.cs +++ b/CS2-SimpleAdmin/Variables.cs @@ -40,7 +40,6 @@ public partial class CS2_SimpleAdmin internal static readonly HashSet AdminDisabledJoinComms = []; // Player Management - private static readonly HashSet GodPlayers = []; internal static readonly HashSet SilentPlayers = []; internal static readonly Dictionary RenamedPlayers = []; internal static readonly ConcurrentDictionary PlayersInfo = [];