Skip to content

Commit 6ca65f5

Browse files
committed
adding random tag #66
1 parent dade59a commit 6ca65f5

File tree

1 file changed

+86
-55
lines changed

1 file changed

+86
-55
lines changed

CustomCommands/Services/ReplaceTagsFunction.cs

Lines changed: 86 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,23 @@
1010
using CounterStrikeSharp.API.Core.Plugin;
1111

1212
namespace CustomCommands.Services;
13-
public class ReplaceTagsFunctions : IReplaceTagsFunctions
13+
public partial class ReplaceTagsFunctions : IReplaceTagsFunctions
1414
{
15-
private readonly IPluginGlobals PluginGlobals;
16-
private readonly PluginContext PluginContext;
17-
private readonly ILogger<CustomCommands> Logger;
15+
private readonly IPluginGlobals _pluginGlobals;
16+
private readonly PluginContext _pluginContext;
17+
private readonly ILogger<CustomCommands> _logger;
1818

1919
public ReplaceTagsFunctions(IPluginGlobals PluginGlobals, IPluginContext PluginContext,
2020
ILogger<CustomCommands> Logger)
2121
{
22-
this.PluginGlobals = PluginGlobals;
23-
this.PluginContext = (PluginContext as PluginContext)!;
24-
this.Logger = Logger;
22+
_pluginGlobals = PluginGlobals;
23+
_pluginContext = (PluginContext as PluginContext)!;
24+
_logger = Logger;
2525
}
2626

27-
28-
29-
/// <summary>
30-
/// Replaces tags in the input array with their corresponding values.
31-
/// </summary>
32-
/// <param name="input">The array of strings containing tags to be replaced.</param>
33-
/// <param name="player">The CCSPlayerController object used for tag replacement.</param>
34-
/// <returns>The array of strings with tags replaced.</returns>
3527
public string[] ReplaceTags(dynamic input, CCSPlayerController player)
3628
{
37-
List<string> output = WrappedLine(input);
29+
var output = WrappedLine(input);
3830

3931
for (int i = 0; i < output.Count; i++)
4032
output[i] = ReplaceLanguageTags(output[i]);
@@ -44,58 +36,102 @@ public string[] ReplaceTags(dynamic input, CCSPlayerController player)
4436
for (int i = 0; i < output.Count; i++)
4537
{
4638
output[i] = ReplaceMessageTags(output[i], player, false);
39+
output[i] = ReplaceRandomTags(output[i]);
4740
output[i] = ReplaceColorTags(output[i]);
4841
}
4942

50-
return output.ToArray<string>();
43+
return output.ToArray();
5144
}
5245

53-
/// <summary>
54-
/// Replaces language tags in the input string with the corresponding localized value.
55-
/// Language tags are defined within curly braces, e.g. "{LANG=LocalizerTag}".
56-
/// If a language tag is found, it is replaced with the localized value from the CustomCommands plugin's Localizer.
57-
/// If the localized value is not found, a default message is returned.
58-
/// </summary>
59-
/// <param name="input">The input string to process.</param>
60-
/// <returns>The input string with language tags replaced with localized values.</returns>
46+
[GeneratedRegex(@"\{LANG=(.*?)\}")]
47+
private static partial Regex ReplaceLanguageTagsRegex();
48+
6149
public string ReplaceLanguageTags(string input)
6250
{
63-
CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!;
64-
65-
// Define the regex pattern to find "{LANG=...}"
66-
string pattern = @"\{LANG=(.*?)\}";
67-
6851
// Use Regex to find matches
69-
Match match = Regex.Match(input, pattern);
52+
var match = ReplaceLanguageTagsRegex().Match(input);
7053

7154
// Check if a match is found
7255
if (match.Success)
7356
{
7457
// Return the group captured in the regex, which is the string after "="
75-
string lang = match.Groups[1].Value;
76-
return input.Replace(match.Value, plugin.Localizer[lang] ?? "<LANG in CustomCommands/lang/<language.json> not found>");
58+
var lang = match.Groups[1].Value;
59+
var context = (_pluginContext.Plugin as CustomCommands)!;
60+
61+
return input.Replace(match.Value, context.Localizer[lang] ?? "<LANG in CustomCommands/lang/<language.json> not found>");
7762
}
7863
else
7964
{
8065
// Return the original string if no match is found
8166
return input;
8267
}
8368
}
84-
69+
8570
/// <summary>
86-
/// Replaces tags in the input string with corresponding values based on the provided player information.
71+
/// Use regex to find the RNDNO tag pattern {RNDNO={min, max}}
8772
/// </summary>
88-
/// <param name="input">The input string containing tags to be replaced.</param>
89-
/// <param name="player">The CCSPlayerController object representing the player.</param>
90-
/// <param name="safety">A boolean value indicating whether to replace the {PLAYERNAME} tag. Default is true.</param>
91-
/// <returns>The modified string with replaced tags.</returns>
73+
/// <returns></returns>
74+
[GeneratedRegex(@"\{RNDNO=\((\d+(?:\.\d+)?),\s*(\d+(?:\.\d+)?)\)\}")]
75+
private static partial Regex ReplaceRandomTagsRegex();
76+
77+
public string ReplaceRandomTags(string message)
78+
{
79+
// Replace all occurrences of the RNDNO tag in the message
80+
var match = ReplaceRandomTagsRegex().Match(message);
81+
82+
// Extract min and max from the regex match groups
83+
string minStr = match.Groups[1].Value;
84+
string maxStr = match.Groups[2].Value;
85+
86+
// Determine if the min and max are integers or floats
87+
bool isMinFloat = float.TryParse(minStr, out float minFloat);
88+
bool isMaxFloat = float.TryParse(maxStr, out float maxFloat);
89+
90+
var random = new Random();
91+
92+
if (isMinFloat || isMaxFloat)
93+
{
94+
// Generate a random float between min and max (inclusive)
95+
float randomFloat = (float)(random.NextDouble() * (maxFloat - minFloat) + minFloat);
96+
97+
// Determine the maximum precision from the min and max values
98+
int maxDecimalPlaces = Math.Max(GetDecimalPlaces(minStr), GetDecimalPlaces(maxStr));
99+
100+
// Use the determined precision to format the float
101+
message = message.Replace(match.Value, randomFloat.ToString($"F{maxDecimalPlaces}"));
102+
}
103+
else
104+
{
105+
// Parse as integers
106+
int min = int.Parse(minStr);
107+
int max = int.Parse(maxStr);
108+
109+
// Generate a random integer between min and max (inclusive)
110+
int randomValue = random.Next(min, max + 1); // max is exclusive, so add 1
111+
message = message.Replace(match.Value, randomValue.ToString());
112+
}
113+
114+
return message;
115+
}
116+
117+
// Method to get the number of decimal places in a number string
118+
private static int GetDecimalPlaces(string numberStr)
119+
{
120+
int decimalIndex = numberStr.IndexOf('.');
121+
if (decimalIndex == -1)
122+
{
123+
return 0; // No decimal point, return 0
124+
}
125+
return numberStr.Length - decimalIndex - 1; // Count digits after the decimal point
126+
}
127+
92128
public string ReplaceMessageTags(string input, CCSPlayerController player, bool safety = true)
93129
{
94-
SteamID steamId = new SteamID(player.SteamID);
130+
var steamId = new SteamID(player.SteamID);
95131

96132
Dictionary<string, string> replacements = new()
97133
{
98-
{"{PREFIX}", PluginGlobals.Config.Prefix ?? "<PREFIX not found>"},
134+
{"{PREFIX}", _pluginGlobals.Config.Prefix ?? "<PREFIX not found>"},
99135
{"{MAP}", NativeAPI.GetMapName() ?? "<MAP not found>"},
100136
{"{TIME}", DateTime.Now.ToString("HH:mm:ss") ?? "<TIME not found>"},
101137
{"{DATE}", DateTime.Now.ToString("dd.MM.yyyy") ?? "<DATE not found>"},
@@ -109,7 +145,7 @@ public string ReplaceMessageTags(string input, CCSPlayerController player, bool
109145
{"{PORT}", ConVar.Find("hostport")!.GetPrimitiveValue<int>().ToString() ?? "<PORT not found>"},
110146
{"{MAXPLAYERS}", Server.MaxPlayers.ToString() ?? "<MAXPLAYERS not found>"},
111147
{"{PLAYERS}",
112-
Utilities.GetPlayers().Count(u => u.PlayerPawn.Value != null && u.PlayerPawn.Value.IsValid).ToString() ?? "<PLAYERS not found>"}
148+
Utilities.GetPlayers().Count(u => u.PlayerPawn.Value != null && u.PlayerPawn.Value.IsValid).ToString() ?? "<PLAYERS not found>"},
113149
};
114150

115151
// Prevent vounrability by not replacing {PLAYERNAME} if safety is true/ServerCommands are being executed
@@ -155,46 +191,41 @@ public string ReplaceColorTags(string input)
155191
return input;
156192
}
157193

158-
/// <summary>
159-
/// Splits the input into an array of strings. If the input is a string, it will be split by newlines. If the input is an array, each element will be split by newlines.
160-
/// </summary>
161-
/// <param name="input">This should be a string[] or a string</param>
162-
/// <returns>An array of strings representing the lines of the input.</returns>
163194
public List<string> WrappedLine(dynamic input)
164195
{
165-
List<string> output = new List<string>();
196+
var output = new List<string>();
166197

167198
if (input is JsonElement jsonElement)
168199
{
169200
switch (jsonElement.ValueKind)
170201
{
171202
case JsonValueKind.String:
172-
string result = jsonElement.GetString()!;
203+
var result = jsonElement.GetString()!;
173204
output.AddRange(result.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None));
174205
break;
175206
case JsonValueKind.Array:
176207
foreach (var arrayElement in jsonElement.EnumerateArray())
177208
{
178-
string[] lines = arrayElement.GetString()?.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None) ?? Array.Empty<string>();
209+
var lines = arrayElement.GetString()?.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None) ?? Array.Empty<string>();
179210
output.AddRange(lines);
180211
}
181212
break;
182213

183214
default:
184-
Logger.LogError($"{PluginGlobals.Config.LogPrefix} Message is not a string or array");
215+
_logger.LogError($"{_pluginGlobals.Config.LogPrefix} Message is not a string or array");
185216
break;
186217
}
187218
} else if (input is Array inputArray)
188219
{
189220
foreach (string arrayElement in inputArray)
190221
{
191-
string[] lines = arrayElement.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None) ?? Array.Empty<string>();
222+
var lines = arrayElement.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None) ?? Array.Empty<string>();
192223
output.AddRange(lines);
193224
}
194225
}
195226
else
196227
{
197-
Logger.LogError($"{PluginGlobals.Config.LogPrefix} Invalid input type");
228+
_logger.LogError($"{_pluginGlobals.Config.LogPrefix} Invalid input type");
198229
}
199230

200231
return output;
@@ -206,9 +237,9 @@ public List<string> WrappedLine(dynamic input)
206237
/// </summary>
207238
/// <param name="input"></param>
208239
/// <returns></returns>
209-
private string PadLeftColorTag(string input)
240+
private static string PadLeftColorTag(string input)
210241
{
211-
string[] colorTagList = new string[] {
242+
var colorTagList = new string[] {
212243
"{DEFAULT}",
213244
"{WHITE}",
214245
"{DARKRED}",

0 commit comments

Comments
 (0)