-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSAMUtils.cs
More file actions
136 lines (116 loc) · 3.48 KB
/
Copy pathSAMUtils.cs
File metadata and controls
136 lines (116 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// SAMUtils.cs
using System.Text.RegularExpressions;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
namespace SimpleAdminMode;
/// <summary>
/// Utility methods for SAM plugin — targeting, duration parsing and chat formatting.
/// </summary>
public static class SAMUtils
{
// Max duration: 1 year in minutes
private const int MaxDurationMinutes = 31536000;
private static readonly (string Unit, long Minutes)[] DurationUnits =
[
("y", 525600L),
("mo", 43800L),
("w", 10080L),
("d", 1440L),
("h", 60L),
("m", 1L)
];
private static readonly (string Name, int Minutes)[] FormatUnits =
[
(" year", 525600),
(" month", 43800),
(" week", 10080),
(" day", 1440),
(" hour", 60),
(" minute", 1)
];
/// <summary>
/// Parses a duration string into minutes.
/// Supports formats like "1y2mo3d", "1h30m", "60" (raw minutes).
/// Returns 0 for permament.
/// </summary>
public static int ParseDuration(string input)
{
input = input.Trim().ToLower();
if(int.TryParse(input, out int directMinutes))
return Math.Clamp(directMinutes, 0, MaxDurationMinutes);
long minutes = 0;
foreach(Match match in Regex.Matches(input, @"(\d{1,9})(y|mo|w|d|h|m)"))
{
long value = long.Parse(match.Groups[1].Value);
string unit = match.Groups[2].Value;
minutes += DurationUnits
.FirstOrDefault(u => u.Unit == unit)
.Minutes * value;
}
return (int)Math.Clamp(minutes, 0L, MaxDurationMinutes);
}
/// <summary>
/// Formats a duration in minutes to a human-readable string.
/// Returns "Indefinitely" for 0 or genative values.
/// </summary>
public static string FormatDuration(int minutes)
{
if(minutes <= 0) return "Indefinitely";
if(minutes <= 1) return "1 minute";
var parts = new List<string>();
foreach(var (name, value) in FormatUnits)
{
int count = minutes / value;
minutes %= value;
if(count > 0)
parts.Add($"{count}{name}{(count> 1 ? "s" : "")}");
if(minutes == 0) break;
}
return parts.Count == 1
? parts[0]
: string.Join(", ", parts[..^1]) + " and " + parts[^1];
}
/// <summary>
/// Resolves a target string to a list of players.
/// Supports: ^ (self), * (all), name, SteamID64, #UserID.
/// </summary>
public static List<CCSPlayerController> GetTargets(CCSPlayerController admin, string target)
{
return target switch
{
"^" => [admin],
"*" => Utilities.GetPlayers().ToList(),
_ => Utilities.GetPlayers()
.Where(p => p.PlayerName.Contains(target, StringComparison.OrdinalIgnoreCase)
|| p.SteamID.ToString() == target
|| $"#{p.UserId}" == target
).ToList()
};
}
/// <summary>
/// Prints a formatted action message to all players in chat.
/// </summary>
public static void PrintActionToChat(
CCSPlayerController? admin,
string targetArg,
List<CCSPlayerController>? targets,
string actionPast,
string optionalText = "")
{
bool hasTargets = targets != null && targets.Count > 0;
string who = hasTargets
? (targetArg == "^" || (targets!.Count == 1 && targets[0].SteamID == admin?.SteamID)
? "Themselves"
: targetArg == "*" || targets!.Count > 1
? "Everyone"
: targets!.FirstOrDefault()?.PlayerName ?? targetArg)
: targetArg;
string adminName = admin != null
? $"{ChatColors.Magenta}{admin.PlayerName}"
: $"{ChatColors.Grey}CONSOLE";
Server.PrintToChatAll(
$" {ChatColors.Red}[SAM] {adminName} {ChatColors.Default}{actionPast} {ChatColors.Lime}{who}{optionalText}"
);
}
}