- MultiServerMode fix
- New feature `TimeMode`
This commit is contained in:
Dawid Bepierszcz
2024-05-06 22:56:57 +02:00
parent d5a6ceacb6
commit 4244104d6e
9 changed files with 172 additions and 70 deletions

View File

@@ -22,9 +22,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v3 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: 8.0.x dotnet-version: 8.0.x
- name: Restore - name: Restore
@@ -38,9 +38,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v3 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: 8.0.x dotnet-version: 8.0.x
- name: Restore - name: Restore
@@ -55,13 +55,13 @@ jobs:
${{ env.OUTPUT_PATH }}/Microsoft.DotNet.PlatformAbstractions.dll \ ${{ env.OUTPUT_PATH }}/Microsoft.DotNet.PlatformAbstractions.dll \
${{ env.OUTPUT_PATH }}/Microsoft.Extensions.DependencyModel.dll \ ${{ env.OUTPUT_PATH }}/Microsoft.Extensions.DependencyModel.dll \
- name: Zip - name: Zip
uses: thedoctor0/zip-release@0.7.5 uses: thedoctor0/zip-release@0.7.6
with: with:
type: 'zip' type: 'zip'
filename: '${{ env.PROJECT_NAME }}.zip' filename: '${{ env.PROJECT_NAME }}.zip'
path: ${{ env.OUTPUT_PATH }} path: ${{ env.OUTPUT_PATH }}
- name: CS2-SimpleAdmin - name: CS2-SimpleAdmin
uses: ncipollo/release-action@v1.12.0 uses: ncipollo/release-action@v1.14.0
with: with:
artifacts: "${{ env.PROJECT_NAME }}.zip" artifacts: "${{ env.PROJECT_NAME }}.zip"
name: "Build ${{ env.BUILD_NUMBER }}" name: "Build ${{ env.BUILD_NUMBER }}"

View File

@@ -11,7 +11,7 @@ using System.Collections.Concurrent;
namespace CS2_SimpleAdmin; namespace CS2_SimpleAdmin;
[MinimumApiVersion(220)] [MinimumApiVersion(225)]
public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdminConfig> public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdminConfig>
{ {
public static CS2_SimpleAdmin Instance { get; private set; } = new(); public static CS2_SimpleAdmin Instance { get; private set; } = new();
@@ -37,7 +37,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
public override string ModuleName => "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)"); public override string ModuleName => "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)");
public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)"; public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)";
public override string ModuleAuthor => "daffyy & Dliix66"; public override string ModuleAuthor => "daffyy & Dliix66";
public override string ModuleVersion => "1.4.3d"; public override string ModuleVersion => "1.4.4a";
public CS2_SimpleAdminConfig Config { get; set; } = new(); public CS2_SimpleAdminConfig Config { get; set; } = new();

View File

@@ -10,7 +10,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.225" /> <PackageReference Include="CounterStrikeSharp.API" Version="1.0.228" />
<PackageReference Include="Dapper" Version="2.1.35" /> <PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="Discord.Net.Webhook" Version="3.14.1" /> <PackageReference Include="Discord.Net.Webhook" Version="3.14.1" />
<PackageReference Include="MySqlConnector" Version="2.3.7" /> <PackageReference Include="MySqlConnector" Version="2.3.7" />

View File

@@ -142,6 +142,9 @@ namespace CS2_SimpleAdmin
[JsonPropertyName("BanType")] [JsonPropertyName("BanType")]
public int BanType { get; set; } = 1; public int BanType { get; set; } = 1;
[JsonPropertyName("TimeMode")]
public int TimeMode { get; set; } = 1;
[JsonPropertyName("MaxBanDuration")] [JsonPropertyName("MaxBanDuration")]
public int MaxBanDuration { get; set; } = 60 * 24 * 7; // 7 days public int MaxBanDuration { get; set; } = 60 * 24 * 7; // 7 days
[JsonPropertyName("MultiServerMode")] [JsonPropertyName("MultiServerMode")]

View File

@@ -148,7 +148,6 @@ public partial class CS2_SimpleAdmin
string muteType = mute.type; string muteType = mute.type;
DateTime ends = mute.ends; DateTime ends = mute.ends;
int duration = mute.duration; int duration = mute.duration;
switch (muteType) switch (muteType)
{ {
// Apply mute penalty based on mute type // Apply mute penalty based on mute type
@@ -275,7 +274,7 @@ public partial class CS2_SimpleAdmin
{ {
var ipAddress = ConVar.Find("ip")?.StringValue; var ipAddress = ConVar.Find("ip")?.StringValue;
if (string.IsNullOrEmpty(ipAddress)) if (string.IsNullOrEmpty(ipAddress) || ipAddress.StartsWith("0.0.0"))
{ {
Logger.LogError("Unable to get server ip, Check that you have added the correct start parameter \"-ip <ip>\""); Logger.LogError("Unable to get server ip, Check that you have added the correct start parameter \"-ip <ip>\"");
} }
@@ -352,8 +351,8 @@ public partial class CS2_SimpleAdmin
var players = Helper.GetValidPlayers(); var players = Helper.GetValidPlayers();
var onlinePlayers = players var onlinePlayers = players
.Where(player => player.IpAddress != null && player.SteamID.ToString().Length == 17) .Where(player => player.IpAddress != null)
.Select(player => (player.IpAddress, player.SteamID, player.UserId)) .Select(player => (player.IpAddress, player.SteamID, player.UserId, player.Slot))
.ToList(); .ToList();
Task.Run(async () => Task.Run(async () =>
@@ -363,18 +362,25 @@ public partial class CS2_SimpleAdmin
MuteManager muteManager = new(_database); MuteManager muteManager = new(_database);
await banManager.ExpireOldBans(); await banManager.ExpireOldBans();
await muteManager.ExpireOldMutes();
await adminManager.DeleteOldAdmins(); await adminManager.DeleteOldAdmins();
BannedPlayers.Clear(); BannedPlayers.Clear();
if (onlinePlayers.Count > 0) if (onlinePlayers.Count > 0)
{ {
try try
{ {
await banManager.CheckOnlinePlayers(onlinePlayers); await banManager.CheckOnlinePlayers(onlinePlayers);
if (Config.TimeMode == 0)
{
await muteManager.CheckOnlineModeMutes(onlinePlayers);
}
} }
catch { } catch { }
} }
await muteManager.ExpireOldMutes();
await Server.NextFrameAsync(() => await Server.NextFrameAsync(() =>
{ {
try try

View File

@@ -165,8 +165,8 @@ internal class BanManager(Database.Database database, CS2_SimpleAdminConfig conf
var sql = ""; var sql = "";
sql = config.MultiServerMode sql = config.MultiServerMode
? "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP) AND server_id = @serverid" ? "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP)"
: "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP)"; : "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP) AND server_id = @serverid";
int banCount; int banCount;
@@ -210,16 +210,10 @@ internal class BanManager(Database.Database database, CS2_SimpleAdminConfig conf
{ {
await using var connection = await database.GetConnectionAsync(); await using var connection = await database.GetConnectionAsync();
string sqlRetrieveBans; var sqlRetrieveBans = config.MultiServerMode
if (config.MultiServerMode) ? "SELECT id FROM sa_bans WHERE (player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern) AND status = 'ACTIVE'"
{ : "SELECT id FROM sa_bans WHERE (player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern) AND status = 'ACTIVE' AND server_id = @serverid";
sqlRetrieveBans = "SELECT id FROM sa_bans WHERE (player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern) AND status = 'ACTIVE' " +
"AND server_id = @serverid";
}
else
{
sqlRetrieveBans = "SELECT id FROM sa_bans WHERE (player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern) AND status = 'ACTIVE'";
}
var bans = await connection.QueryAsync(sqlRetrieveBans, new { pattern = playerPattern, serverid = CS2_SimpleAdmin.ServerId }); var bans = await connection.QueryAsync(sqlRetrieveBans, new { pattern = playerPattern, serverid = CS2_SimpleAdmin.ServerId });
var bansList = bans as dynamic[] ?? bans.ToArray(); var bansList = bans as dynamic[] ?? bans.ToArray();
@@ -262,25 +256,18 @@ internal class BanManager(Database.Database database, CS2_SimpleAdminConfig conf
catch { } catch { }
} }
public async Task CheckOnlinePlayers(List<(string? IpAddress, ulong SteamID, int? UserId)> players) public async Task CheckOnlinePlayers(List<(string? IpAddress, ulong SteamID, int? UserId, int Slot)> players)
{ {
try try
{ {
await using var connection = await database.GetConnectionAsync(); await using var connection = await database.GetConnectionAsync();
string sql;
bool checkIpBans = config.BanType > 0; bool checkIpBans = config.BanType > 0;
if (config.MultiServerMode) var sql = config.MultiServerMode
{ ? "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP) AND status = 'ACTIVE'"
sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP) AND status = 'ACTIVE' AND" + : "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP) AND status = 'ACTIVE' AND server_id = @serverid";
" server_id = @serverid";
}
else
{
sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP) AND status = 'ACTIVE'";
}
foreach (var (IpAddress, SteamID, UserId) in players) foreach (var (IpAddress, SteamID, UserId, Slot) in players)
{ {
if (!UserId.HasValue) continue; if (!UserId.HasValue) continue;
@@ -336,7 +323,6 @@ internal class BanManager(Database.Database database, CS2_SimpleAdminConfig conf
`duration` > 0 `duration` > 0
AND AND
ends <= @currentTime ends <= @currentTime
AND server_id = @serverid
""" : """ """ : """
UPDATE sa_bans UPDATE sa_bans
@@ -348,6 +334,7 @@ internal class BanManager(Database.Database database, CS2_SimpleAdminConfig conf
`duration` > 0 `duration` > 0
AND AND
ends <= @currentTime ends <= @currentTime
AND server_id = @serverid
"""; """;
await connection.ExecuteAsync(sql, new { currentTime, serverid = CS2_SimpleAdmin.ServerId }); await connection.ExecuteAsync(sql, new { currentTime, serverid = CS2_SimpleAdmin.ServerId });
@@ -364,7 +351,6 @@ internal class BanManager(Database.Database database, CS2_SimpleAdminConfig conf
status = 'ACTIVE' status = 'ACTIVE'
AND AND
ends <= @ipBansTime ends <= @ipBansTime
AND server_id = @serverid
""" : """ """ : """
UPDATE sa_bans UPDATE sa_bans
@@ -374,6 +360,7 @@ internal class BanManager(Database.Database database, CS2_SimpleAdminConfig conf
status = 'ACTIVE' status = 'ACTIVE'
AND AND
ends <= @ipBansTime ends <= @ipBansTime
AND server_id = @serverid
"""; """;
await connection.ExecuteAsync(sql, new { ipBansTime, CS2_SimpleAdmin.ServerId }); await connection.ExecuteAsync(sql, new { ipBansTime, CS2_SimpleAdmin.ServerId });

View File

@@ -1,4 +1,5 @@
using Dapper; using CounterStrikeSharp.API.Core;
using Dapper;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace CS2_SimpleAdmin; namespace CS2_SimpleAdmin;
@@ -96,16 +97,20 @@ internal class MuteManager(Database.Database database)
{ {
await using var connection = await database.GetConnectionAsync(); await using var connection = await database.GetConnectionAsync();
var currentTime = DateTime.UtcNow.ToLocalTime(); var currentTime = DateTime.UtcNow.ToLocalTime();
string sql; var sql = "";
if (CS2_SimpleAdmin.Instance.Config.MultiServerMode) if (CS2_SimpleAdmin.Instance.Config.MultiServerMode)
{ {
sql = "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime) " + sql = CS2_SimpleAdmin.Instance.Config.TimeMode == 1
"AND server_id = @serverid"; ? "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime)"
: "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR duration > COALESCE(passed, 0))";
} }
else else
{ {
sql = "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime)"; sql = CS2_SimpleAdmin.Instance.Config.TimeMode == 1
? "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime) AND server_id = @serverid"
: "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR duration > COALESCE(passed, 0)) AND server_id = @serverid";
} }
var parameters = new { PlayerSteamID = steamId, CurrentTime = currentTime, serverid = CS2_SimpleAdmin.ServerId }; var parameters = new { PlayerSteamID = steamId, CurrentTime = currentTime, serverid = CS2_SimpleAdmin.ServerId };
@@ -125,8 +130,8 @@ internal class MuteManager(Database.Database database)
await using var connection = await database.GetConnectionAsync(); await using var connection = await database.GetConnectionAsync();
var sql = CS2_SimpleAdmin.Instance.Config.MultiServerMode var sql = CS2_SimpleAdmin.Instance.Config.MultiServerMode
? "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND server_id = @serverid" ? "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID"
: "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID"; : "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND server_id = @serverid";
var muteCount = await connection.ExecuteScalarAsync<int>(sql, new { PlayerSteamID = steamId, serverid = CS2_SimpleAdmin.ServerId }); var muteCount = await connection.ExecuteScalarAsync<int>(sql, new { PlayerSteamID = steamId, serverid = CS2_SimpleAdmin.ServerId });
return muteCount; return muteCount;
@@ -137,6 +142,56 @@ internal class MuteManager(Database.Database database)
} }
} }
public async Task CheckOnlineModeMutes(List<(string? IpAddress, ulong SteamID, int? UserId, int Slot)> players)
{
try
{
int batchSize = 10;
await using var connection = await database.GetConnectionAsync();
var sql = CS2_SimpleAdmin.Instance.Config.MultiServerMode
? "UPDATE `sa_mutes` SET passed = COALESCE(passed, 0) + 1 WHERE (player_steamid = @PlayerSteamID) AND duration > 0 AND status = 'ACTIVE'"
: "UPDATE `sa_mutes` SET passed = COALESCE(passed, 0) + 1 WHERE (player_steamid = @PlayerSteamID) AND duration > 0 AND status = 'ACTIVE' AND server_id = @serverid";
/*
foreach (var (IpAddress, SteamID, UserId, Slot) in players)
{
await connection.ExecuteAsync(sql,
new { PlayerSteamID = SteamID, serverid = CS2_SimpleAdmin.ServerId });
}*/
for (var i = 0; i < players.Count; i += batchSize)
{
var batch = players.Skip(i).Take(batchSize);
var parametersList = new List<object>();
foreach (var (IpAddress, SteamID, UserId, Slot) in batch)
{
parametersList.Add(new { PlayerSteamID = SteamID, serverid = CS2_SimpleAdmin.ServerId });
}
await connection.ExecuteAsync(sql, parametersList);
}
sql = CS2_SimpleAdmin.Instance.Config.MultiServerMode
? "SELECT * FROM `sa_mutes` WHERE player_steamid = @PlayerSteamID AND passed >= duration AND duration > 0 AND status = 'ACTIVE'"
: "SELECT * FROM `sa_mutes` WHERE player_steamid = @PlayerSteamID AND passed >= duration AND duration > 0 AND status = 'ACTIVE' AND server_id = @serverid";
foreach (var (IpAddress, SteamID, UserId, Slot) in players)
{
var muteRecords = await connection.QueryAsync(sql, new { PlayerSteamID = SteamID, serverid = CS2_SimpleAdmin.ServerId });
foreach (var muteRecord in muteRecords)
{
DateTime endDateTime = muteRecord.ends;
PlayerPenaltyManager.RemovePenaltiesByDateTime(Slot, endDateTime);
}
}
}
catch { }
}
public async Task UnmutePlayer(string playerPattern, string adminSteamId, string reason, int type = 0) public async Task UnmutePlayer(string playerPattern, string adminSteamId, string reason, int type = 0)
{ {
if (playerPattern.Length <= 1) if (playerPattern.Length <= 1)
@@ -160,12 +215,12 @@ internal class MuteManager(Database.Database database)
if (CS2_SimpleAdmin.Instance.Config.MultiServerMode) if (CS2_SimpleAdmin.Instance.Config.MultiServerMode)
{ {
sqlRetrieveMutes = "SELECT id FROM sa_mutes WHERE (player_steamid = @pattern OR player_name = @pattern) AND " + sqlRetrieveMutes = "SELECT id FROM sa_mutes WHERE (player_steamid = @pattern OR player_name = @pattern) AND " +
"type = @muteType AND status = 'ACTIVE' AND server_id = @serverid"; "type = @muteType AND status = 'ACTIVE'";
} }
else else
{ {
sqlRetrieveMutes = "SELECT id FROM sa_mutes WHERE (player_steamid = @pattern OR player_name = @pattern) AND " + sqlRetrieveMutes = "SELECT id FROM sa_mutes WHERE (player_steamid = @pattern OR player_name = @pattern) AND " +
"type = @muteType AND status = 'ACTIVE'"; "type = @muteType AND status = 'ACTIVE' AND server_id = @serverid";
} }
var mutes = await connection.QueryAsync(sqlRetrieveMutes, new { pattern = playerPattern, muteType, serverid = CS2_SimpleAdmin.ServerId }); var mutes = await connection.QueryAsync(sqlRetrieveMutes, new { pattern = playerPattern, muteType, serverid = CS2_SimpleAdmin.ServerId });
@@ -212,10 +267,20 @@ internal class MuteManager(Database.Database database)
try try
{ {
await using var connection = await database.GetConnectionAsync(); await using var connection = await database.GetConnectionAsync();
var sql = "";
var sql = CS2_SimpleAdmin.Instance.Config.MultiServerMode if (CS2_SimpleAdmin.Instance.Config.MultiServerMode)
{
sql = CS2_SimpleAdmin.Instance.Config.TimeMode == 1
? "UPDATE sa_mutes SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime"
: "UPDATE sa_mutes SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND `passed` >= `duration`";
}
else
{
sql = CS2_SimpleAdmin.Instance.Config.TimeMode == 1
? "UPDATE sa_mutes SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime AND server_id = @serverid" ? "UPDATE sa_mutes SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime AND server_id = @serverid"
: "UPDATE sa_mutes SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime"; : "UPDATE sa_mutes SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND `passed` >= `duration` AND server_id = @serverid";
}
await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.UtcNow.ToLocalTime(), serverid = CS2_SimpleAdmin.ServerId }); await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.UtcNow.ToLocalTime(), serverid = CS2_SimpleAdmin.ServerId });
} }

View File

@@ -11,18 +11,18 @@ public enum PenaltyType
public class PlayerPenaltyManager public class PlayerPenaltyManager
{ {
private static readonly ConcurrentDictionary<int, Dictionary<PenaltyType, List<(DateTime EndDateTime, int Duration)>>> Penalties = private static readonly ConcurrentDictionary<int, Dictionary<PenaltyType, List<(DateTime EndDateTime, int Duration, bool Passed)>>> Penalties =
new(); new();
// Add a penalty for a player // Add a penalty for a player
public static void AddPenalty(int slot, PenaltyType penaltyType, DateTime endDateTime, int durationSeconds) public static void AddPenalty(int slot, PenaltyType penaltyType, DateTime endDateTime, int durationInMinutes)
{ {
Penalties.AddOrUpdate(slot, Penalties.AddOrUpdate(slot,
(_) => (_) =>
{ {
var dict = new Dictionary<PenaltyType, List<(DateTime, int)>> var dict = new Dictionary<PenaltyType, List<(DateTime, int, bool)>>
{ {
[penaltyType] = [(endDateTime, durationSeconds)] [penaltyType] = [(endDateTime, durationInMinutes, false)]
}; };
return dict; return dict;
}, },
@@ -30,11 +30,11 @@ public class PlayerPenaltyManager
{ {
if (!existingDict.TryGetValue(penaltyType, out var value)) if (!existingDict.TryGetValue(penaltyType, out var value))
{ {
value = new List<(DateTime, int)>(); value = new List<(DateTime, int, bool)>();
existingDict[penaltyType] = value; existingDict[penaltyType] = value;
} }
value.Add((endDateTime, durationSeconds)); value.Add((endDateTime, durationInMinutes, false));
return existingDict; return existingDict;
}); });
} }
@@ -47,13 +47,16 @@ public class PlayerPenaltyManager
!penaltyDict.TryGetValue(penaltyType, out var penaltiesList)) return false; !penaltyDict.TryGetValue(penaltyType, out var penaltiesList)) return false;
//Console.WriteLine($"Found penalties for player with slot {slot} and penalty type {penaltyType}"); //Console.WriteLine($"Found penalties for player with slot {slot} and penalty type {penaltyType}");
if (CS2_SimpleAdmin.Instance.Config.TimeMode == 0)
return penaltiesList.Count != 0;
var now = DateTime.UtcNow.ToLocalTime(); var now = DateTime.UtcNow.ToLocalTime();
// Check if any active penalties exist // Check if any active penalties exist
foreach (var penalty in penaltiesList.ToList()) foreach (var penalty in penaltiesList.ToList())
{ {
// Check if the penalty is still active // Check if the penalty is still active
if (penalty.Duration > 0 && now >= penalty.EndDateTime.AddSeconds(penalty.Duration)) if (penalty.Duration > 0 && now >= penalty.EndDateTime)
{ {
//Console.WriteLine($"Removing expired penalty for player with slot {slot} and penalty type {penaltyType}"); //Console.WriteLine($"Removing expired penalty for player with slot {slot} and penalty type {penaltyType}");
penaltiesList.Remove(penalty); // Remove expired penalty penaltiesList.Remove(penalty); // Remove expired penalty
@@ -80,7 +83,7 @@ public class PlayerPenaltyManager
} }
// Get the end datetime and duration of penalties for a player and penalty type // Get the end datetime and duration of penalties for a player and penalty type
public static List<(DateTime EndDateTime, int Duration)> GetPlayerPenalties(int slot, PenaltyType penaltyType) public static List<(DateTime EndDateTime, int Duration, bool Passed)> GetPlayerPenalties(int slot, PenaltyType penaltyType)
{ {
if (Penalties.TryGetValue(slot, out var penaltyDict) && if (Penalties.TryGetValue(slot, out var penaltyDict) &&
penaltyDict.TryGetValue(penaltyType, out var penaltiesList)) penaltyDict.TryGetValue(penaltyType, out var penaltiesList))
@@ -113,26 +116,64 @@ public class PlayerPenaltyManager
// Remove all penalties of a selected type from a specific player // Remove all penalties of a selected type from a specific player
public static void RemovePenaltiesByType(int slot, PenaltyType penaltyType) public static void RemovePenaltiesByType(int slot, PenaltyType penaltyType)
{ {
if (Penalties.TryGetValue(slot, out Dictionary<PenaltyType, List<(DateTime EndDateTime, int Duration)>>? penaltyDict) && if (Penalties.TryGetValue(slot, out var penaltyDict) &&
penaltyDict.ContainsKey(penaltyType)) penaltyDict.ContainsKey(penaltyType))
{ {
penaltyDict.Remove(penaltyType); penaltyDict.Remove(penaltyType);
} }
} }
public static void RemovePenaltiesByDateTime(int slot, DateTime dateTime)
{
if (!Penalties.TryGetValue(slot, out var penaltyDict)) return;
foreach (var penaltiesList in penaltyDict.Values)
{
for (var i = 0; i < penaltiesList.Count; i++)
{
if (penaltiesList[i].EndDateTime != dateTime) continue;
// Create a copy of the penalty
var penalty = penaltiesList[i];
// Update the end datetime of the copied penalty to the current datetime
penalty.Passed = true;
// Replace the original penalty with the modified one
penaltiesList[i] = penalty;
}
}
}
// Remove all expired penalties for all players and penalty types // Remove all expired penalties for all players and penalty types
public static void RemoveExpiredPenalties() public static void RemoveExpiredPenalties()
{ {
var now = DateTime.UtcNow.ToLocalTime(); if (CS2_SimpleAdmin.Instance.Config.TimeMode == 0)
foreach (var kvp in Penalties.ToList()) // Use ToList to avoid modification while iterating {
foreach (var (playerSlot, penaltyDict) in Penalties.ToList()) // Use ToList to avoid modification while iterating
{ {
var playerSlot = kvp.Key;
var penaltyDict = kvp.Value;
// Remove expired penalties for the player // Remove expired penalties for the player
foreach (var penaltiesList in penaltyDict.Values) foreach (var penaltiesList in penaltyDict.Values)
{ {
penaltiesList.RemoveAll(p => p.Duration > 0 && now >= p.EndDateTime.AddSeconds(p.Duration).ToLocalTime()); penaltiesList.RemoveAll(p => p is { Duration: > 0, Passed: true });
}
// Remove player slot if no penalties left
if (penaltyDict.Count == 0)
{
Penalties.TryRemove(playerSlot, out _);
}
}
return;
}
var now = DateTime.UtcNow.ToLocalTime();
foreach (var (playerSlot, penaltyDict) in Penalties.ToList()) // Use ToList to avoid modification while iterating
{
// Remove expired penalties for the player
foreach (var penaltiesList in penaltyDict.Values)
{
penaltiesList.RemoveAll(p => p.Duration > 0 && now >= p.EndDateTime);
} }
// Remove player slot if no penalties left // Remove player slot if no penalties left

View File

@@ -1 +1 @@
1.4.3d 1.4.4a