mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-03-10 08:31:44 +00:00
1.7.7-alpha-small-optimizations
- Clear bans cache on plugin reload - Changed ip history to int
This commit is contained in:
@@ -31,6 +31,8 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
|
|||||||
{
|
{
|
||||||
ServerLoaded = false;
|
ServerLoaded = false;
|
||||||
_serverLoading = false;
|
_serverLoading = false;
|
||||||
|
|
||||||
|
CacheManager = new CacheManager();
|
||||||
OnGameServerSteamAPIActivated();
|
OnGameServerSteamAPIActivated();
|
||||||
OnMapStart(string.Empty);
|
OnMapStart(string.Empty);
|
||||||
|
|
||||||
@@ -149,4 +151,10 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
|
|||||||
command.ReplyToCommand($"Multiple targets found for \"{command.GetArg(1)}\".");
|
command.ReplyToCommand($"Multiple targets found for \"{command.GetArg(1)}\".");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Unload(bool hotReload)
|
||||||
|
{
|
||||||
|
CacheManager?.Dispose();
|
||||||
|
CacheManager = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +393,7 @@ public partial class CS2_SimpleAdmin
|
|||||||
{
|
{
|
||||||
if (Database == null) return;
|
if (Database == null) return;
|
||||||
|
|
||||||
_ = Instance.CacheManager.ForceReInitializeCacheAsync();
|
_ = Instance.CacheManager?.ForceReInitializeCacheAsync();
|
||||||
command.ReplyToCommand("Reloaded bans");
|
command.ReplyToCommand("Reloaded bans");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
|
UPDATE `sa_players_ips` SET `address` = INET_ATON(address);
|
||||||
|
ALTER TABLE `sa_players_ips` CHANGE `address` `address` INT UNSIGNED NOT NULL;
|
||||||
ALTER TABLE `sa_players_ips` ADD `name` VARCHAR(64) NULL DEFAULT NULL AFTER `steamid`;
|
ALTER TABLE `sa_players_ips` ADD `name` VARCHAR(64) NULL DEFAULT NULL AFTER `steamid`;
|
||||||
@@ -137,7 +137,7 @@ public partial class CS2_SimpleAdmin
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
Logger.LogCritical("[OnClientConnect]");
|
Logger.LogCritical("[OnClientConnect]");
|
||||||
#endif
|
#endif
|
||||||
if (Config.OtherSettings.BanType == 1 && !Instance.CacheManager.IsPlayerBanned(null, ipaddress.Split(":")[0]))
|
if (Config.OtherSettings.BanType == 1 && Instance.CacheManager != null && !Instance.CacheManager.IsPlayerBanned(null, ipaddress.Split(":")[0]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Server.NextFrame((() =>
|
Server.NextFrame((() =>
|
||||||
|
|||||||
@@ -62,14 +62,14 @@ internal static class Helper
|
|||||||
return GetValidPlayers().FirstOrDefault(x => x.IpAddress != null && x.IpAddress.Split(":")[0].Equals(ipAddress));
|
return GetValidPlayers().FirstOrDefault(x => x.IpAddress != null && x.IpAddress.Split(":")[0].Equals(ipAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IReadOnlyList<CCSPlayerController> GetValidPlayers()
|
public static List<CCSPlayerController> GetValidPlayers()
|
||||||
{
|
{
|
||||||
return Utilities.GetPlayers().AsValueEnumerable()
|
return Utilities.GetPlayers().AsValueEnumerable()
|
||||||
.Where(p => p is { IsValid: true, IsBot: false, Connected: PlayerConnectedState.PlayerConnected })
|
.Where(p => p is { IsValid: true, IsBot: false, Connected: PlayerConnectedState.PlayerConnected })
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IReadOnlyList<CCSPlayerController> GetValidPlayersWithBots()
|
public static List<CCSPlayerController> GetValidPlayersWithBots()
|
||||||
{
|
{
|
||||||
return Utilities.GetPlayers().AsValueEnumerable()
|
return Utilities.GetPlayers().AsValueEnumerable()
|
||||||
.Where(p => p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected }).ToList();
|
.Where(p => p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected }).ToList();
|
||||||
@@ -970,3 +970,35 @@ public static class WeaponHelper
|
|||||||
return filteredWeapons; // Return all relevant matches for the partial input
|
return filteredWeapons; // Return all relevant matches for the partial input
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class IpHelper
|
||||||
|
{
|
||||||
|
public static uint IpToUint(string ipAddress)
|
||||||
|
{
|
||||||
|
return (uint)BitConverter.ToInt32(System.Net.IPAddress.Parse(ipAddress).GetAddressBytes().Reverse().ToArray(),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryConvertIpToUint(string ipString, out uint ipUint)
|
||||||
|
{
|
||||||
|
ipUint = 0;
|
||||||
|
if (string.IsNullOrWhiteSpace(ipString))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!System.Net.IPAddress.TryParse(ipString, out var ipAddress))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var bytes = ipAddress.GetAddressBytes();
|
||||||
|
if (bytes.Length != 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ipUint = IpToUint(ipString);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string UintToIp(uint ipAddress)
|
||||||
|
{
|
||||||
|
var bytes = BitConverter.GetBytes(ipAddress).Reverse().ToArray();
|
||||||
|
return new System.Net.IPAddress(bytes).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ using ZLinq;
|
|||||||
|
|
||||||
namespace CS2_SimpleAdmin.Managers;
|
namespace CS2_SimpleAdmin.Managers;
|
||||||
|
|
||||||
internal class CacheManager
|
internal class CacheManager: IDisposable
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<int, BanRecord> _banCache = new();
|
private readonly ConcurrentDictionary<int, BanRecord> _banCache = [];
|
||||||
private readonly ConcurrentDictionary<ulong, (HashSet<string> ips, DateTime usedAt, string playerName)> _playerIpsCache = new();
|
private readonly ConcurrentDictionary<ulong, HashSet<IpRecord>> _playerIpsCache = [];
|
||||||
private HashSet<string> _cachedIgnoredIps;
|
private HashSet<uint> _cachedIgnoredIps = [];
|
||||||
|
|
||||||
private DateTime _lastUpdateTime = DateTime.MinValue;
|
private DateTime _lastUpdateTime = DateTime.MinValue;
|
||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
public async Task InitializeCacheAsync()
|
public async Task InitializeCacheAsync()
|
||||||
{
|
{
|
||||||
@@ -20,10 +21,13 @@ internal class CacheManager
|
|||||||
if (!CS2_SimpleAdmin.ServerLoaded) return;
|
if (!CS2_SimpleAdmin.ServerLoaded) return;
|
||||||
if (_isInitialized) return;
|
if (_isInitialized) return;
|
||||||
|
|
||||||
_cachedIgnoredIps = [..CS2_SimpleAdmin.Instance.Config.OtherSettings.IgnoredIps];
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Clear();
|
||||||
|
_cachedIgnoredIps = new HashSet<uint>(
|
||||||
|
CS2_SimpleAdmin.Instance.Config.OtherSettings.IgnoredIps
|
||||||
|
.Select(IpHelper.IpToUint));
|
||||||
|
|
||||||
await using var connection = await CS2_SimpleAdmin.Database.GetConnectionAsync();
|
await using var connection = await CS2_SimpleAdmin.Database.GetConnectionAsync();
|
||||||
var bans = await connection.QueryAsync<BanRecord>(
|
var bans = await connection.QueryAsync<BanRecord>(
|
||||||
"""
|
"""
|
||||||
@@ -44,26 +48,49 @@ internal class CacheManager
|
|||||||
FROM sa_bans
|
FROM sa_bans
|
||||||
""");
|
""");
|
||||||
var ipHistory =
|
var ipHistory =
|
||||||
await connection.QueryAsync<(ulong steamid, string? name, string address, DateTime used_at)>(
|
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");
|
"SELECT steamid, name, address, used_at FROM sa_players_ips ORDER BY used_at DESC");
|
||||||
|
|
||||||
|
|
||||||
foreach (var ban in bans)
|
foreach (var ban in bans)
|
||||||
{
|
{
|
||||||
_banCache.TryAdd(ban.Id, ban);
|
_banCache.TryAdd(ban.Id, ban);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var group in ipHistory.GroupBy(x => x.steamid))
|
foreach (var group in ipHistory.AsValueEnumerable().GroupBy(x => x.steamid))
|
||||||
{
|
{
|
||||||
var ips = new HashSet<string>(group.Select(x => x.address));
|
var ipSet = new HashSet<IpRecord>(
|
||||||
var lastUsed = group.Max(x => x.used_at);
|
group
|
||||||
var playerName = group.FirstOrDefault(x => !string.IsNullOrEmpty(x.name)).name
|
.GroupBy(x => x.address)
|
||||||
?? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown";
|
.Select(g =>
|
||||||
|
{
|
||||||
|
var latest = g.MaxBy(x => x.used_at);
|
||||||
|
return new IpRecord(
|
||||||
|
g.Key,
|
||||||
|
latest.used_at,
|
||||||
|
!string.IsNullOrEmpty(latest.name)
|
||||||
|
? latest.name
|
||||||
|
: CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
new IpRecordComparer()
|
||||||
|
);
|
||||||
|
|
||||||
_playerIpsCache[group.Key] = (ips, lastUsed, playerName);
|
_playerIpsCache.AddOrUpdate(
|
||||||
|
group.Key,
|
||||||
|
_ => ipSet,
|
||||||
|
(_, existingSet) =>
|
||||||
|
{
|
||||||
|
foreach (var ip in ipSet)
|
||||||
|
{
|
||||||
|
existingSet.Remove(ip);
|
||||||
|
existingSet.Add(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return existingSet;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastUpdateTime = DateTime.Now;
|
_lastUpdateTime = DateTime.Now.AddSeconds(-1);
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -95,53 +122,44 @@ internal class CacheManager
|
|||||||
var updatedBans = (await connection.QueryAsync<BanRecord>(
|
var updatedBans = (await connection.QueryAsync<BanRecord>(
|
||||||
"SELECT * FROM `sa_bans` WHERE updated_at > @lastUpdate OR created > @lastUpdate ORDER BY updated_at DESC",
|
"SELECT * FROM `sa_bans` WHERE updated_at > @lastUpdate OR created > @lastUpdate ORDER BY updated_at DESC",
|
||||||
new { lastUpdate = _lastUpdateTime }
|
new { lastUpdate = _lastUpdateTime }
|
||||||
)).ToList().AsValueEnumerable();
|
)).ToList();
|
||||||
var ipHistory = (await connection.QueryAsync<(ulong steamid, string? name, string address, DateTime used_at)>(
|
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 LIMIT 500")).ToList();
|
"SELECT steamid, name, address, used_at FROM sa_players_ips WHERE used_at >= @lastUpdate ORDER BY used_at DESC LIMIT 300", new {lastUpdate = _lastUpdateTime})).ToList();
|
||||||
|
|
||||||
// foreach (var group in ipHistory.GroupBy(x => x.steamid))
|
foreach (var group in ipHistory.AsValueEnumerable().GroupBy(x => x.steamid))
|
||||||
// {
|
|
||||||
// var ips = new HashSet<string>(group.Select(x => x.address));
|
|
||||||
// var lastUsed = group.Max(x => x.used_at);
|
|
||||||
// _playerIpsCache[group.Key] = (ips, lastUsed);
|
|
||||||
// }
|
|
||||||
|
|
||||||
var groupedData = ipHistory.AsValueEnumerable()
|
|
||||||
.GroupBy(x => x.steamid)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
groupedData.ForEach(group =>
|
|
||||||
{
|
{
|
||||||
var ips = new HashSet<string>(
|
var ipSet = new HashSet<IpRecord>(
|
||||||
group.Select(x => x.address),
|
group
|
||||||
StringComparer.OrdinalIgnoreCase
|
.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)
|
||||||
|
? latest.name
|
||||||
|
: CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
new IpRecordComparer()
|
||||||
);
|
);
|
||||||
|
|
||||||
var lastUsed = group.Max(x => x.used_at);
|
|
||||||
var playerName = group
|
|
||||||
.OrderByDescending(x => x.used_at) // Prefer newer records
|
|
||||||
.Select(x => x.name)
|
|
||||||
.FirstOrDefault(name => !string.IsNullOrEmpty(name))
|
|
||||||
?? CS2_SimpleAdmin._localizer?["sa_unknown"]
|
|
||||||
?? "Unknown";
|
|
||||||
|
|
||||||
_playerIpsCache.AddOrUpdate(
|
_playerIpsCache.AddOrUpdate(
|
||||||
group.Key,
|
group.Key,
|
||||||
// Add new entry
|
_ => ipSet,
|
||||||
_ => (ips, lastUsed, playerName),
|
(_, existingSet) =>
|
||||||
// Update existing
|
|
||||||
(_, existing) =>
|
|
||||||
{
|
{
|
||||||
existing.ips.UnionWith(ips);
|
foreach (var newEntry in ipSet)
|
||||||
return (
|
{
|
||||||
existing.ips,
|
existingSet.Remove(newEntry);
|
||||||
lastUsed > existing.usedAt ? lastUsed : existing.usedAt,
|
existingSet.Add(newEntry);
|
||||||
string.IsNullOrEmpty(existing.playerName) ? playerName : existing.playerName
|
}
|
||||||
);
|
return existingSet;
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
if (updatedBans.Count() == 0)
|
if (updatedBans.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var ban in updatedBans)
|
foreach (var ban in updatedBans)
|
||||||
@@ -149,7 +167,7 @@ internal class CacheManager
|
|||||||
_banCache.AddOrUpdate(ban.Id, ban, (_, _) => ban);
|
_banCache.AddOrUpdate(ban.Id, ban, (_, _) => ban);
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastUpdateTime = DateTime.Now;
|
_lastUpdateTime = DateTime.Now.AddSeconds(-1);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -160,36 +178,54 @@ internal class CacheManager
|
|||||||
public List<BanRecord> GetAllBans() => _banCache.Values.ToList();
|
public List<BanRecord> GetAllBans() => _banCache.Values.ToList();
|
||||||
public List<BanRecord> GetActiveBans() => _banCache.Values.Where(b => b.Status == "ACTIVE").ToList();
|
public List<BanRecord> GetActiveBans() => _banCache.Values.Where(b => b.Status == "ACTIVE").ToList();
|
||||||
public List<BanRecord> GetPlayerBansBySteamId(string steamId) => _banCache.Values.Where(b => b.PlayerSteamId == steamId).ToList();
|
public List<BanRecord> GetPlayerBansBySteamId(string steamId) => _banCache.Values.Where(b => b.PlayerSteamId == steamId).ToList();
|
||||||
public List<(ulong SteamId, string PlayerName)> GetAccountsByIp(string ipAddress)
|
public List<(ulong SteamId, DateTime UsedAt, string PlayerName)> GetAccountsByIp(string ipAddress)
|
||||||
{
|
{
|
||||||
|
var ipAsUint = IpHelper.IpToUint(ipAddress);
|
||||||
|
|
||||||
return _playerIpsCache.AsValueEnumerable()
|
return _playerIpsCache.AsValueEnumerable()
|
||||||
.Where(kvp => kvp.Value.ips.Contains(ipAddress))
|
.SelectMany(kvp => kvp.Value
|
||||||
.Select(kvp => (kvp.Key, kvp.Value.playerName))
|
.Where(entry => entry.Ip == ipAsUint)
|
||||||
|
.Select(entry => (kvp.Key, entry.UsedAt, entry.PlayerName)))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsIpBanned(string ipAddress)
|
private bool IsIpBanned(string ipAddress)
|
||||||
{
|
{
|
||||||
|
var ipUInt = IpHelper.IpToUint(ipAddress);
|
||||||
|
|
||||||
return _banCache.Values.Any(b =>
|
return _banCache.Values.Any(b =>
|
||||||
b.Status == "ACTIVE" &&
|
b is { Status: "ACTIVE", PlayerIp: not null } &&
|
||||||
!string.IsNullOrEmpty(b.PlayerIp) &&
|
IpHelper.IpToUint(b.PlayerIp) == ipUInt &&
|
||||||
b.PlayerIp.Equals(ipAddress, StringComparison.OrdinalIgnoreCase) &&
|
!_cachedIgnoredIps.Contains(ipUInt));
|
||||||
!_cachedIgnoredIps.Contains(ipAddress));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPlayerBanned(string? steamId, string? ipAddress) =>
|
public bool IsPlayerBanned(string? steamId, string? ipAddress)
|
||||||
_banCache.Values.Any(b =>
|
{
|
||||||
b.Status == "ACTIVE" && (
|
if (ipAddress == null)
|
||||||
|
return _banCache.Values.Any(b =>
|
||||||
|
b.Status == "ACTIVE" &&
|
||||||
|
steamId != null &&
|
||||||
|
b.PlayerSteamId != null &&
|
||||||
|
b.PlayerSteamId.Equals(steamId, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
if (!IpHelper.TryConvertIpToUint(ipAddress, out var ipUInt))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _banCache.Values.Any(b =>
|
||||||
|
b is { Status: "ACTIVE", PlayerIp: not null } &&
|
||||||
|
(
|
||||||
(steamId != null &&
|
(steamId != null &&
|
||||||
b.PlayerSteamId != null &&
|
b.PlayerSteamId != null &&
|
||||||
b.PlayerSteamId.Equals(steamId, StringComparison.OrdinalIgnoreCase)) ||
|
b.PlayerSteamId.Equals(steamId, StringComparison.OrdinalIgnoreCase))
|
||||||
(ipAddress != null &&
|
||
|
||||||
b.PlayerIp != null &&
|
(IpHelper.TryConvertIpToUint(b.PlayerIp, out var bIpUint) &&
|
||||||
b.PlayerIp.Equals(ipAddress, StringComparison.OrdinalIgnoreCase) &&
|
bIpUint == ipUInt &&
|
||||||
!_cachedIgnoredIps.Contains(ipAddress))
|
!_cachedIgnoredIps.Contains(ipUInt))
|
||||||
));
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsPlayerOrAnyIpBanned(ulong steamId)
|
public bool IsPlayerOrAnyIpBanned(ulong steamId, string? ipAddress)
|
||||||
{
|
{
|
||||||
var steamIdStr = steamId.ToString();
|
var steamIdStr = steamId.ToString();
|
||||||
if (_banCache.Values.Any(b =>
|
if (_banCache.Values.Any(b =>
|
||||||
@@ -199,13 +235,62 @@ internal class CacheManager
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _playerIpsCache.TryGetValue(steamId, out var ipList) && ipList.ips.Any(ip =>
|
if (!_playerIpsCache.TryGetValue(steamId, out var ipData))
|
||||||
!_cachedIgnoredIps.Contains(ip) && IsIpBanned(ip));
|
return false;
|
||||||
|
|
||||||
|
var now = DateTime.Now;
|
||||||
|
var cutoff = now.AddDays(-7);
|
||||||
|
|
||||||
|
if (ipAddress != null)
|
||||||
|
{
|
||||||
|
var ipAsUint = IpHelper.IpToUint(ipAddress);
|
||||||
|
|
||||||
|
ipData.Add(new IpRecord(
|
||||||
|
ipAsUint,
|
||||||
|
now.AddSeconds(-2),
|
||||||
|
CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipData.Any(x =>
|
||||||
|
x.UsedAt >= cutoff &&
|
||||||
|
!_cachedIgnoredIps.Contains(x.Ip) &&
|
||||||
|
_banCache.Values.Any(b =>
|
||||||
|
b is { Status: "ACTIVE", PlayerIp: not null } &&
|
||||||
|
IpHelper.TryConvertIpToUint(b.PlayerIp, out var banIpUint) &&
|
||||||
|
banIpUint == x.Ip
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasIpForPlayer(ulong steamId, string ipAddress)
|
public bool HasIpForPlayer(ulong steamId, string ipAddress)
|
||||||
{
|
{
|
||||||
return _playerIpsCache.TryGetValue(steamId, out var ipList)
|
if (string.IsNullOrWhiteSpace(ipAddress))
|
||||||
&& ipList.ips.Contains(ipAddress);
|
return false;
|
||||||
|
|
||||||
|
return _playerIpsCache.TryGetValue(steamId, out var ipData)
|
||||||
|
&& ipData.Any(x => x.Ip == IpHelper.IpToUint(ipAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Clear()
|
||||||
|
{
|
||||||
|
_banCache.Clear();
|
||||||
|
_playerIpsCache.Clear();
|
||||||
|
_cachedIgnoredIps.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
Clear();
|
||||||
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class IpRecordComparer : IEqualityComparer<IpRecord>
|
||||||
|
{
|
||||||
|
public bool Equals(IpRecord x, IpRecord y)
|
||||||
|
=> x.Ip == y.Ip;
|
||||||
|
|
||||||
|
public int GetHashCode(IpRecord obj)
|
||||||
|
=> obj.Ip.GetHashCode();
|
||||||
|
}
|
||||||
@@ -27,7 +27,6 @@ public class PlayerManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ipAddress = player.IpAddress?.Split(":")[0];
|
var ipAddress = player.IpAddress?.Split(":")[0];
|
||||||
|
|
||||||
CS2_SimpleAdmin.PlayersInfo[player.UserId.Value] =
|
CS2_SimpleAdmin.PlayersInfo[player.UserId.Value] =
|
||||||
new PlayerInfo(player.UserId.Value, player.Slot, new SteamID(player.SteamID), player.PlayerName, ipAddress);
|
new PlayerInfo(player.UserId.Value, player.Slot, new SteamID(player.SteamID), player.PlayerName, ipAddress);
|
||||||
|
|
||||||
@@ -52,11 +51,11 @@ public class PlayerManager
|
|||||||
// Perform asynchronous database operations within a single method
|
// Perform asynchronous database operations within a single method
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var isBanned = CS2_SimpleAdmin.Instance.Config.OtherSettings.BanType switch
|
var isBanned = CS2_SimpleAdmin.Instance.CacheManager != null && CS2_SimpleAdmin.Instance.Config.OtherSettings.BanType switch
|
||||||
{
|
{
|
||||||
0 => CS2_SimpleAdmin.Instance.CacheManager.IsPlayerBanned(steamId, null),
|
0 => CS2_SimpleAdmin.Instance.CacheManager.IsPlayerBanned(steamId, null),
|
||||||
_ => CS2_SimpleAdmin.Instance.Config.OtherSettings.CheckMultiAccountsByIp
|
_ => CS2_SimpleAdmin.Instance.Config.OtherSettings.CheckMultiAccountsByIp
|
||||||
? CS2_SimpleAdmin.Instance.CacheManager.IsPlayerOrAnyIpBanned(steamId64)
|
? CS2_SimpleAdmin.Instance.CacheManager.IsPlayerOrAnyIpBanned(steamId64, ipAddress)
|
||||||
: CS2_SimpleAdmin.Instance.CacheManager.IsPlayerBanned(steamId, ipAddress)
|
: CS2_SimpleAdmin.Instance.CacheManager.IsPlayerBanned(steamId, ipAddress)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,7 +75,7 @@ public class PlayerManager
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (CS2_SimpleAdmin.Instance.CacheManager.HasIpForPlayer(
|
if (CS2_SimpleAdmin.Instance.CacheManager != null && CS2_SimpleAdmin.Instance.CacheManager.HasIpForPlayer(
|
||||||
CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64, ipAddress))
|
CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64, ipAddress))
|
||||||
{
|
{
|
||||||
await using var connection = await CS2_SimpleAdmin.Database.GetConnectionAsync();
|
await using var connection = await CS2_SimpleAdmin.Database.GetConnectionAsync();
|
||||||
@@ -89,7 +88,7 @@ public class PlayerManager
|
|||||||
await connection.ExecuteAsync(updateQuery, new
|
await connection.ExecuteAsync(updateQuery, new
|
||||||
{
|
{
|
||||||
SteamID = CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64,
|
SteamID = CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64,
|
||||||
IPAddress = ipAddress
|
IPAddress = IpHelper.IpToUint(ipAddress)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -101,7 +100,7 @@ public class PlayerManager
|
|||||||
var recordExists = await connection.ExecuteScalarAsync<int>(selectQuery, new
|
var recordExists = await connection.ExecuteScalarAsync<int>(selectQuery, new
|
||||||
{
|
{
|
||||||
SteamID = CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64,
|
SteamID = CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64,
|
||||||
IPAddress = ipAddress
|
IPAddress = IpHelper.IpToUint(ipAddress)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (recordExists > 0)
|
if (recordExists > 0)
|
||||||
@@ -114,7 +113,7 @@ public class PlayerManager
|
|||||||
await connection.ExecuteAsync(updateQuery, new
|
await connection.ExecuteAsync(updateQuery, new
|
||||||
{
|
{
|
||||||
SteamID = CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64,
|
SteamID = CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64,
|
||||||
IPAddress = ipAddress
|
IPAddress = IpHelper.IpToUint(ipAddress)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -126,7 +125,7 @@ public class PlayerManager
|
|||||||
await connection.ExecuteAsync(insertQuery, new
|
await connection.ExecuteAsync(insertQuery, new
|
||||||
{
|
{
|
||||||
SteamID = CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64,
|
SteamID = CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64,
|
||||||
IPAddress = ipAddress
|
IPAddress = IpHelper.IpToUint(ipAddress)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +138,7 @@ public class PlayerManager
|
|||||||
|
|
||||||
// Get all accounts associated to the player (ip address)
|
// Get all accounts associated to the player (ip address)
|
||||||
CS2_SimpleAdmin.PlayersInfo[userId].AccountsAssociated =
|
CS2_SimpleAdmin.PlayersInfo[userId].AccountsAssociated =
|
||||||
CS2_SimpleAdmin.Instance.CacheManager.GetAccountsByIp(ipAddress);
|
CS2_SimpleAdmin.Instance.CacheManager?.GetAccountsByIp(ipAddress).AsValueEnumerable().Select(x => (x.SteamId, x.PlayerName)).ToList() ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -158,7 +157,7 @@ public class PlayerManager
|
|||||||
var (totalMutes, totalGags, totalSilences) =
|
var (totalMutes, totalGags, totalSilences) =
|
||||||
await CS2_SimpleAdmin.Instance.MuteManager.GetPlayerMutes(CS2_SimpleAdmin.PlayersInfo[userId]);
|
await CS2_SimpleAdmin.Instance.MuteManager.GetPlayerMutes(CS2_SimpleAdmin.PlayersInfo[userId]);
|
||||||
|
|
||||||
CS2_SimpleAdmin.PlayersInfo[userId].TotalBans = CS2_SimpleAdmin.Instance.CacheManager.GetPlayerBansBySteamId(CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64.ToString()).Count;
|
CS2_SimpleAdmin.PlayersInfo[userId].TotalBans = CS2_SimpleAdmin.Instance.CacheManager?.GetPlayerBansBySteamId(CS2_SimpleAdmin.PlayersInfo[userId].SteamId.SteamId64.ToString()).Count ?? 0;
|
||||||
CS2_SimpleAdmin.PlayersInfo[userId].TotalMutes = totalMutes;
|
CS2_SimpleAdmin.PlayersInfo[userId].TotalMutes = totalMutes;
|
||||||
CS2_SimpleAdmin.PlayersInfo[userId].TotalGags = totalGags;
|
CS2_SimpleAdmin.PlayersInfo[userId].TotalGags = totalGags;
|
||||||
CS2_SimpleAdmin.PlayersInfo[userId].TotalSilences = totalSilences;
|
CS2_SimpleAdmin.PlayersInfo[userId].TotalSilences = totalSilences;
|
||||||
@@ -273,85 +272,71 @@ public class PlayerManager
|
|||||||
if (CS2_SimpleAdmin.Database == null)
|
if (CS2_SimpleAdmin.Database == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var players = Helper.GetValidPlayers().ToList();
|
var tempPlayers = Helper.GetValidPlayers()
|
||||||
|
.Select(p => new
|
||||||
var bannedPlayers = players.AsValueEnumerable()
|
|
||||||
.Where(player =>
|
|
||||||
{
|
{
|
||||||
return CS2_SimpleAdmin.Instance.Config.OtherSettings.BanType switch
|
p.SteamID, p.IpAddress, p.UserId, p.Slot,
|
||||||
{
|
|
||||||
0 => CS2_SimpleAdmin.Instance.CacheManager.IsPlayerBanned(player.SteamID.ToString(), null),
|
|
||||||
_ => CS2_SimpleAdmin.Instance.Config.OtherSettings.CheckMultiAccountsByIp
|
|
||||||
? CS2_SimpleAdmin.Instance.CacheManager.IsPlayerOrAnyIpBanned(player.SteamID)
|
|
||||||
: CS2_SimpleAdmin.Instance.CacheManager.IsPlayerBanned(player.SteamID.ToString(), player.IpAddress)
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
foreach (var player in bannedPlayers)
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
Helper.KickPlayer(player, NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED);
|
try
|
||||||
players.Remove(player);
|
{
|
||||||
}
|
var expireTasks = new Task[]
|
||||||
|
{
|
||||||
|
CS2_SimpleAdmin.Instance.BanManager.ExpireOldBans(),
|
||||||
|
CS2_SimpleAdmin.Instance.MuteManager.ExpireOldMutes(),
|
||||||
|
CS2_SimpleAdmin.Instance.WarnManager.ExpireOldWarns(),
|
||||||
|
CS2_SimpleAdmin.Instance.CacheManager?.RefreshCacheAsync() ?? Task.CompletedTask,
|
||||||
|
CS2_SimpleAdmin.Instance.PermissionManager.DeleteOldAdmins()
|
||||||
|
};
|
||||||
|
|
||||||
var onlinePlayers = players.AsValueEnumerable().Select(player => (player.SteamID, player.UserId, player.Slot)).ToList();
|
await Task.WhenAll(expireTasks);
|
||||||
|
}
|
||||||
try
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var expireTasks = new[]
|
CS2_SimpleAdmin._logger?.LogError($"Error processing players timer tasks: {ex.Message}");
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.BanManager.ExpireOldBans(),
|
if (ex is AggregateException aggregate)
|
||||||
CS2_SimpleAdmin.Instance.MuteManager.ExpireOldMutes(),
|
{
|
||||||
CS2_SimpleAdmin.Instance.WarnManager.ExpireOldWarns(),
|
foreach (var inner in aggregate.InnerExceptions)
|
||||||
CS2_SimpleAdmin.Instance.CacheManager.RefreshCacheAsync(),
|
{
|
||||||
CS2_SimpleAdmin.Instance.PermissionManager.DeleteOldAdmins()
|
CS2_SimpleAdmin._logger?.LogError($"Inner exception: {inner.Message}");
|
||||||
};
|
}
|
||||||
|
}
|
||||||
Task.WhenAll(expireTasks).ContinueWith(t =>
|
}
|
||||||
{
|
|
||||||
if (t is not { IsFaulted: true, Exception: not null }) return;
|
var bannedPlayers = tempPlayers.AsValueEnumerable()
|
||||||
|
.Where(player =>
|
||||||
foreach (var ex in t.Exception.InnerExceptions)
|
{
|
||||||
{
|
return CS2_SimpleAdmin.Instance.CacheManager != null && CS2_SimpleAdmin.Instance.Config.OtherSettings.BanType switch
|
||||||
CS2_SimpleAdmin._logger?.LogError($"Error processing players timer tasks: {ex.Message}");
|
{
|
||||||
}
|
0 => CS2_SimpleAdmin.Instance.CacheManager.IsPlayerBanned(player.SteamID.ToString(), null),
|
||||||
});
|
_ => CS2_SimpleAdmin.Instance.Config.OtherSettings.CheckMultiAccountsByIp
|
||||||
|
? CS2_SimpleAdmin.Instance.CacheManager.IsPlayerOrAnyIpBanned(player.SteamID, player.IpAddress?.Split(":")[0])
|
||||||
}
|
: CS2_SimpleAdmin.Instance.CacheManager.IsPlayerBanned(player.SteamID.ToString(), player.IpAddress?.Split(":")[0])
|
||||||
catch (Exception ex)
|
};
|
||||||
{
|
})
|
||||||
CS2_SimpleAdmin._logger?.LogError("Unexpected error: {exception}", ex.Message);
|
.ToList();
|
||||||
}
|
|
||||||
|
foreach (var player in bannedPlayers)
|
||||||
if (players.Count == 0 || onlinePlayers.Count == 0) return;
|
{
|
||||||
|
if (player.UserId.HasValue)
|
||||||
try
|
await Server.NextFrameAsync(() => Helper.KickPlayer((int)player.UserId, NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED));
|
||||||
{
|
}
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
var onlinePlayers = tempPlayers.AsValueEnumerable().Select(player => (player.SteamID, player.UserId, player.Slot)).ToList();
|
||||||
// await CS2_SimpleAdmin.Instance.BanManager.CheckOnlinePlayers(onlinePlayers);
|
if (tempPlayers.Count == 0 || onlinePlayers.Count == 0) return;
|
||||||
|
if (_config.OtherSettings.TimeMode == 0)
|
||||||
if (_config.OtherSettings.TimeMode == 0)
|
{
|
||||||
{
|
await CS2_SimpleAdmin.Instance.MuteManager.CheckOnlineModeMutes(onlinePlayers);
|
||||||
await CS2_SimpleAdmin.Instance.MuteManager.CheckOnlineModeMutes(onlinePlayers);
|
}
|
||||||
}
|
});
|
||||||
}).ContinueWith(t =>
|
|
||||||
{
|
|
||||||
if (t is not { IsFaulted: true, Exception: not null }) return;
|
|
||||||
|
|
||||||
foreach (var ex in t.Exception.InnerExceptions)
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin._logger?.LogError($"Error checking online players: {ex.Message}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin._logger?.LogError($"Unexpected error: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var players = Helper.GetValidPlayers();
|
||||||
var penalizedSlots = players
|
var penalizedSlots = players
|
||||||
.Where(player => PlayerPenaltyManager.IsSlotInPenalties(player.Slot))
|
.Where(player => PlayerPenaltyManager.IsSlotInPenalties(player.Slot))
|
||||||
.Select(player => new
|
.Select(player => new
|
||||||
|
|||||||
@@ -88,8 +88,8 @@ public class ServerManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
CS2_SimpleAdmin.ServerLoaded = true;
|
CS2_SimpleAdmin.ServerLoaded = true;
|
||||||
|
if (CS2_SimpleAdmin.Instance.CacheManager != null)
|
||||||
await CS2_SimpleAdmin.Instance.CacheManager.InitializeCacheAsync();
|
await CS2_SimpleAdmin.Instance.CacheManager.InitializeCacheAsync();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
|
|
||||||
namespace CS2_SimpleAdmin.Models;
|
namespace CS2_SimpleAdmin.Models;
|
||||||
|
|
||||||
public record BanRecord
|
public record struct BanRecord
|
||||||
{
|
{
|
||||||
[Column("id")]
|
[Column("id")]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|||||||
3
CS2-SimpleAdmin/Models/IpRecord.cs
Normal file
3
CS2-SimpleAdmin/Models/IpRecord.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace CS2_SimpleAdmin.Models;
|
||||||
|
|
||||||
|
public readonly record struct IpRecord(uint Ip, DateTime UsedAt, string PlayerName);
|
||||||
@@ -68,5 +68,5 @@ public partial class CS2_SimpleAdmin
|
|||||||
internal BanManager BanManager = new(Database);
|
internal BanManager BanManager = new(Database);
|
||||||
internal MuteManager MuteManager = new(Database);
|
internal MuteManager MuteManager = new(Database);
|
||||||
internal WarnManager WarnManager = new(Database);
|
internal WarnManager WarnManager = new(Database);
|
||||||
internal readonly CacheManager CacheManager = new();
|
internal CacheManager? CacheManager = new();
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user