From 9e06e2d8007400a77762adbe80ca9ece88e6035b Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Fri, 9 Feb 2024 23:14:17 +0100 Subject: [PATCH 01/24] Adding Comments --- CustomCommands/CustomCommands.cs | 2 +- .../CustomCommandsServiceCollection.cs | 1 + CustomCommands/Services/CooldownManager.cs | 8 +++- CustomCommands/Services/EventManager.cs | 1 + CustomCommands/Services/LoadJson.cs | 39 ++++++++++++++++++- CustomCommands/Services/MessageManager.cs | 5 +++ CustomCommands/Services/PluginGlobals.cs | 15 +++++++ CustomCommands/Services/PluginUtilities.cs | 5 +++ CustomCommands/Services/RegisterCommands.cs | 28 +++++++++---- .../Services/ReplaceTagsFunction.cs | 24 +++++++++++- CustomCommands/test.md | 11 ------ 11 files changed, 117 insertions(+), 22 deletions(-) delete mode 100644 CustomCommands/test.md diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index f8a69a5..b56f7bf 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -9,7 +9,7 @@ namespace CustomCommands; public partial class CustomCommands : BasePlugin, IPluginConfig { public override string ModuleName => "CustomCommands"; - public override string ModuleVersion => "2.0.3"; + public override string ModuleVersion => "2.0.4"; public override string ModuleAuthor => "HerrMagic"; public override string ModuleDescription => "Create your own commands per config"; diff --git a/CustomCommands/CustomCommandsServiceCollection.cs b/CustomCommands/CustomCommandsServiceCollection.cs index 30e50c0..517b451 100644 --- a/CustomCommands/CustomCommandsServiceCollection.cs +++ b/CustomCommands/CustomCommandsServiceCollection.cs @@ -9,6 +9,7 @@ public class CustomCommandsServiceCollection : IPluginServiceCollection scan .FromAssemblyOf() .AddClasses() diff --git a/CustomCommands/Services/CooldownManager.cs b/CustomCommands/Services/CooldownManager.cs index 40f6730..642c65b 100644 --- a/CustomCommands/Services/CooldownManager.cs +++ b/CustomCommands/Services/CooldownManager.cs @@ -33,6 +33,13 @@ public bool IsCommandOnCooldown(CCSPlayerController player, Commands cmd) return false; } + /// + /// Checks if a command is on cooldown based on a given condition. + /// + /// The condition to check for each cooldown timer. + /// The player controller. + /// The command. + /// True if the command is on cooldown, false otherwise. public bool IsCommandOnCooldownWithCondition(Func predicate, CCSPlayerController player, Commands cmd) { int index = PluginGlobals.CooldownTimer.FindIndex(x => predicate(x) && x.CooldownTime > DateTime.Now); @@ -129,7 +136,6 @@ public void SetCooldown(CCSPlayerController player, Commands cmd) var cooldownObject = JsonSerializer.Deserialize(cmd.Cooldown.GetRawText()); AddToCooldownList(cooldownObject.IsGlobal, player.UserId ?? 0, cmd.ID, cooldownObject.CooldownTime); - break; default: diff --git a/CustomCommands/Services/EventManager.cs b/CustomCommands/Services/EventManager.cs index 08a49a6..54b476a 100644 --- a/CustomCommands/Services/EventManager.cs +++ b/CustomCommands/Services/EventManager.cs @@ -32,6 +32,7 @@ public void RegisterListeners() { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; + // Register the OnTick event for PrintToCenterHtml duration plugin.RegisterListener(() => { // Client Print To Center diff --git a/CustomCommands/Services/LoadJson.cs b/CustomCommands/Services/LoadJson.cs index 954583c..b47b674 100644 --- a/CustomCommands/Services/LoadJson.cs +++ b/CustomCommands/Services/LoadJson.cs @@ -14,6 +14,11 @@ public LoadJson(ILogger Logger) this.Logger = Logger; } + /// + /// Retrieves a list of commands from JSON files located in the specified path. + /// + /// The path where the JSON files are located. + /// A list of commands. public List GetCommandsFromJsonFiles(string path) { var comms = new List(); @@ -55,7 +60,12 @@ public List GetCommandsFromJsonFiles(string path) } return comms; } - // Check if the Command.json file exists. If not replace it with the example file + + + /// + /// Checks if an .example file exists in the specified path and creates a default config file if it doesn't exist. + /// + /// The path to check for the example file. public void CheckForExampleFile(string path) { if (Directory.Exists(Path.Combine(path, "Commands"))) @@ -73,6 +83,12 @@ public void CheckForExampleFile(string path) Logger.LogInformation("Created default config file."); } } + + /// + /// Checks if the JSON file has a valid syntax. + /// + /// The path to the JSON file. + /// True if the JSON syntax is valid, false otherwise. public bool IsValidJsonSyntax(string path) { try @@ -88,6 +104,13 @@ public bool IsValidJsonSyntax(string path) return false; } } + + /// + /// Validates the list of commands loaded from a JSON file. + /// + /// The list of commands to validate. + /// The path of the JSON file. + /// True if all commands are valid, false otherwise. public bool ValidateObject(List? comms, string path) { if (comms == null) @@ -131,6 +154,10 @@ public bool ValidateObject(List? comms, string path) return true; } + /// + /// Logs the details of a command. + /// + /// The command to log. public void LogCommandDetails(Commands comms) { Logger.LogInformation($"-- Title: {comms.Title}"); @@ -145,6 +172,11 @@ public void LogCommandDetails(Commands comms) Logger.LogInformation("--------------------------------------------------"); } + /// + /// Validates the PrintTo property of the Commands object and checks if the required message properties are set based on the PrintTo value. + /// + /// The Commands object to validate. + /// True if the PrintTo property is valid and the required message properties are set; otherwise, false. public bool PrintToCheck(Commands comms) { if (comms.PrintTo == Sender.ClientChat || comms.PrintTo == Sender.AllChat) @@ -175,6 +207,11 @@ public bool PrintToCheck(Commands comms) return true; } + /// + /// Validates a dynamic message by checking if it is a string or an array. + /// + /// The dynamic message to validate. + /// True if the message is a string or an array, otherwise false. public bool ValidateMessage(dynamic message) { if (message is JsonElement jsonElement) diff --git a/CustomCommands/Services/MessageManager.cs b/CustomCommands/Services/MessageManager.cs index bf54ff9..d6c0d32 100644 --- a/CustomCommands/Services/MessageManager.cs +++ b/CustomCommands/Services/MessageManager.cs @@ -18,6 +18,11 @@ public MessageManager(IPluginGlobals PluginGlobals, IReplaceTagsFunctions Replac this.PluginContext = (PluginContext as PluginContext)!; } + /// + /// Sends a message based on the specified command and target receiver. + /// + /// The player who triggered the command. + /// The command containing the message and target receiver. public void SendMessage(CCSPlayerController player, Commands cmd) { switch (cmd.PrintTo) diff --git a/CustomCommands/Services/PluginGlobals.cs b/CustomCommands/Services/PluginGlobals.cs index 6719506..c293d00 100644 --- a/CustomCommands/Services/PluginGlobals.cs +++ b/CustomCommands/Services/PluginGlobals.cs @@ -4,9 +4,24 @@ namespace CustomCommands.Services; public class PluginGlobals : IPluginGlobals { + /// + /// List of clients that have a message printed to their center. + /// public List centerClientOn { get; set; } = new(); + /// + /// The message that is printed to all players' center. + /// public CenterServerElement centerServerOn { get; set; } = new(); + /// + /// The configuration for the plugin. + /// public CustomCommandsConfig Config { get; set; } = new(); + /// + /// List of cooldown timers for each player. + /// public List CooldownTimer { get; set; } = new(); + /// + /// List of custom commands. + /// public List CustomCommands { get; set; } = new(); } diff --git a/CustomCommands/Services/PluginUtilities.cs b/CustomCommands/Services/PluginUtilities.cs index fb546dc..5737ce3 100644 --- a/CustomCommands/Services/PluginUtilities.cs +++ b/CustomCommands/Services/PluginUtilities.cs @@ -23,6 +23,11 @@ public PluginUtilities(IPluginGlobals PluginGlobals, IReplaceTagsFunctions Repla this.Logger = Logger; } + /// + /// Splits a string by comma, semicolon, or whitespace characters. + /// + /// The string to be split. + /// An array of strings containing the split substrings. public string[] SplitStringByCommaOrSemicolon(string str) { return Regex.Split(str, ",|;|\\s") diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index b908021..4e605ff 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -26,6 +26,10 @@ public RegisterCommands(ILogger Logger, IMessageManager MessageM this.CooldownManager = CooldownManager; } + /// + /// Adds custom commands to the plugin. + /// + /// The command to add. public void AddCommands(Commands com) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; @@ -34,42 +38,51 @@ public void AddCommands(Commands com) for (int i = 0; i < aliases.Length; i++) { - string alias = aliases[i]; - plugin.AddCommand(alias, com.Description, (player, info) => + plugin.AddCommand(aliases[i], com.Description, (player, info) => { if (player == null) return; var command = com; - // Check if the command has arguments and if it does, check if the command exists and is the right one + // Check if the command has arguments and if it does, check if the command really exists in the list if (info.ArgCount > 1) { - var findcommand = PluginGlobals.CustomCommands.Find(x => x.Command.Contains(alias + $" {info.ArgString}")); - // Check if the command is the right one with the right arguments + var findcommand = PluginGlobals.CustomCommands.Find(x => x.Command.Contains(aliases[i] + $" {info.ArgString}")); + // Check if the command is equal to the found command if (findcommand! != command) return; command = findcommand; } - // This will exit the command if the command has arguments but the client didn't provide any - if (command!.Command.Contains(alias + " ") && info.ArgCount <= 1) + // Check if the command has arguments and check if the player uses the command with the alias + if (command!.Command.Contains(aliases[i] + " ") && info.ArgCount <= 1) return; + // Check if the player has the permission to use the command if (command!.Permission.PermissionList.Count > 0 && command.Permission != null) if (!PluginUtilities.RequiresPermissions(player, command.Permission)) return; + // Check if the command is on cooldown if(CooldownManager.IsCommandOnCooldown(player, command)) return; + // Set the cooldown for the command if it has a cooldown set CooldownManager.SetCooldown(player, command); + // Sending the message to the player MessageManager.SendMessage(player, command); + // Execute the server commands PluginUtilities.ExecuteServerCommands(command, player); }); } } + /// + /// Checks for duplicate commands in the provided list and removes them. + /// + /// The list of commands to check for duplicates. + /// A new list of commands without any duplicates. public List CheckForDuplicateCommands(List comms) { List duplicateCommands = new(); @@ -94,6 +107,7 @@ public List CheckForDuplicateCommands(List comms) if (duplicateCommands.Count == 0) return comms; + // Log the duplicate commands Logger.LogError($"------------------------------------------------------------------------"); Logger.LogError($"{PluginGlobals.Config.LogPrefix} Duplicate commands found, removing them from the list. Please check your config file for duplicate commands and remove them."); for (int i = 0; i < comms.Count; i++) diff --git a/CustomCommands/Services/ReplaceTagsFunction.cs b/CustomCommands/Services/ReplaceTagsFunction.cs index efe300b..cbad4d2 100644 --- a/CustomCommands/Services/ReplaceTagsFunction.cs +++ b/CustomCommands/Services/ReplaceTagsFunction.cs @@ -24,6 +24,12 @@ public ReplaceTagsFunctions(IPluginGlobals PluginGlobals, IPluginContext PluginC this.Logger = Logger; } + /// + /// Replaces tags in the input array with their corresponding values. + /// + /// The array of strings containing tags to be replaced. + /// The CCSPlayerController object used for tag replacement. + /// The array of strings with tags replaced. public string[] ReplaceTags(string[] input, CCSPlayerController player) { string[] output = new string[input.Length]; @@ -38,6 +44,14 @@ public string[] ReplaceTags(string[] input, CCSPlayerController player) return output; } + /// + /// Replaces language tags in the input string with the corresponding localized value. + /// Language tags are defined within curly braces, e.g. "{LANG=LocalizerTag}". + /// If a language tag is found, it is replaced with the localized value from the CustomCommands plugin's Localizer. + /// If the localized value is not found, a default message is returned. + /// + /// The input string to process. + /// The input string with language tags replaced with localized values. public string ReplaceLanguageTags(string input) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; @@ -61,6 +75,14 @@ public string ReplaceLanguageTags(string input) return input; } } + + /// + /// Replaces tags in the input string with corresponding values based on the provided player information. + /// + /// The input string containing tags to be replaced. + /// The CCSPlayerController object representing the player. + /// A boolean value indicating whether to replace the {PLAYERNAME} tag. Default is true. + /// The modified string with replaced tags. public string ReplaceMessageTags(string input, CCSPlayerController player, bool safety = true) { SteamID steamId = new SteamID(player.SteamID); @@ -103,7 +125,7 @@ public string ReplaceColorTags(string input) { {"{DEFAULT}", $"{ChatColors.Default}"}, {"{WHITE}", $"{ChatColors.White}"}, - {"{DARKRED}", $"{ChatColors.Darkred}"}, + {"{DARKRED}", $"{ChatColors.DarkRed}"}, {"{RED}", $"{ChatColors.Red}"}, {"{LIGHTRED}", $"{ChatColors.LightRed}"}, {"{GREEN}", $"{ChatColors.Green}"}, diff --git a/CustomCommands/test.md b/CustomCommands/test.md deleted file mode 100644 index e14d17d..0000000 --- a/CustomCommands/test.md +++ /dev/null @@ -1,11 +0,0 @@ -## Test this: - -* [X] Test tag support for server commands -* [X] check if USERID tag is the right one from the console -* [X] check if the string pattern check works -* [X] check cooldown funktion for normal int and than object -* [X] check if padleft color tag works now - * [X] If this works remove all spaced in the example files with color tags -* [X] check if command args works - * [ ] check if duplicated commands still wont work with this feature -* [X] check if toggle feature works From 17d9652ed1fa7acf6200e0e83818ec78ee5619fb Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Tue, 13 Feb 2024 11:10:02 +0100 Subject: [PATCH 02/24] fixed a bug that commands are not tagged as cs# commands --- CustomCommands/Interfaces/IPluginUtilities.cs | 2 ++ CustomCommands/Services/PluginUtilities.cs | 20 +++++++++++++++++++ CustomCommands/Services/RegisterCommands.cs | 3 ++- .../Services/ReplaceTagsFunction.cs | 2 ++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CustomCommands/Interfaces/IPluginUtilities.cs b/CustomCommands/Interfaces/IPluginUtilities.cs index feb444f..fc9e7c6 100644 --- a/CustomCommands/Interfaces/IPluginUtilities.cs +++ b/CustomCommands/Interfaces/IPluginUtilities.cs @@ -5,6 +5,8 @@ namespace CustomCommands.Interfaces; public interface IPluginUtilities { + string[] GettingCommandsFromString(string commands); + string[] AddCSSTagsToAliases(string[] input); string[] SplitStringByCommaOrSemicolon(string str); void ExecuteServerCommands(Commands cmd, CCSPlayerController player); bool RequiresPermissions(CCSPlayerController player, Permission permissions); diff --git a/CustomCommands/Services/PluginUtilities.cs b/CustomCommands/Services/PluginUtilities.cs index 5737ce3..7150191 100644 --- a/CustomCommands/Services/PluginUtilities.cs +++ b/CustomCommands/Services/PluginUtilities.cs @@ -22,6 +22,26 @@ public PluginUtilities(IPluginGlobals PluginGlobals, IReplaceTagsFunctions Repla this.ReplaceTagsFunctions = ReplaceTagsFunctions; this.Logger = Logger; } + public string[] GettingCommandsFromString(string commands) + { + string[] splitCommands = SplitStringByCommaOrSemicolon(commands); + return AddCSSTagsToAliases(splitCommands); + } + /// + /// Adds the css_ prefix to each alias. + /// This will help cs# tell this command belongs to the framework. + /// + /// + /// + public string[] AddCSSTagsToAliases(string[] input) + { + for (int i = 0; i < input.Length; i++) + { + if (!input[i].StartsWith("css_")) + input[i] = "css_" + input[i]; + } + return input; + } /// /// Splits a string by comma, semicolon, or whitespace characters. diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index 4e605ff..0d912bb 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -1,5 +1,6 @@ using System.Text.Json; using CounterStrikeSharp.API.Core.Plugin; +using CounterStrikeSharp.API.Modules.Commands; using CustomCommands.Interfaces; using CustomCommands.Model; using Microsoft.Extensions.Logging; @@ -34,7 +35,7 @@ public void AddCommands(Commands com) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - string[] aliases = PluginUtilities.SplitStringByCommaOrSemicolon(com.Command); + string[] aliases = PluginUtilities.GettingCommandsFromString(com.Command); for (int i = 0; i < aliases.Length; i++) { diff --git a/CustomCommands/Services/ReplaceTagsFunction.cs b/CustomCommands/Services/ReplaceTagsFunction.cs index cbad4d2..c9b55a0 100644 --- a/CustomCommands/Services/ReplaceTagsFunction.cs +++ b/CustomCommands/Services/ReplaceTagsFunction.cs @@ -24,6 +24,8 @@ public ReplaceTagsFunctions(IPluginGlobals PluginGlobals, IPluginContext PluginC this.Logger = Logger; } + + /// /// Replaces tags in the input array with their corresponding values. /// From 0961fe2754e985470cca2376772d70f96e2bbf6c Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Tue, 13 Feb 2024 11:30:37 +0100 Subject: [PATCH 03/24] fixed newline not working in language tags --- .../Interfaces/IReplaceTagsFunctions.cs | 2 +- .../Services/ReplaceTagsFunction.cs | 45 ++++++++++++------- CustomCommands/tests.md | 7 +++ 3 files changed, 36 insertions(+), 18 deletions(-) create mode 100644 CustomCommands/tests.md diff --git a/CustomCommands/Interfaces/IReplaceTagsFunctions.cs b/CustomCommands/Interfaces/IReplaceTagsFunctions.cs index 419e19e..2017a7d 100644 --- a/CustomCommands/Interfaces/IReplaceTagsFunctions.cs +++ b/CustomCommands/Interfaces/IReplaceTagsFunctions.cs @@ -5,7 +5,7 @@ namespace CustomCommands.Interfaces; public interface IReplaceTagsFunctions { string[] ReplaceTags(string[] input, CCSPlayerController player); - string ReplaceLanguageTags(string input); + string[] ReplaceLanguageTags(string[] input); string ReplaceMessageTags(string input, CCSPlayerController player, bool safety = true); string ReplaceColorTags(string input); string[] WrappedLine(dynamic message); diff --git a/CustomCommands/Services/ReplaceTagsFunction.cs b/CustomCommands/Services/ReplaceTagsFunction.cs index c9b55a0..76a33f6 100644 --- a/CustomCommands/Services/ReplaceTagsFunction.cs +++ b/CustomCommands/Services/ReplaceTagsFunction.cs @@ -34,11 +34,10 @@ public ReplaceTagsFunctions(IPluginGlobals PluginGlobals, IPluginContext PluginC /// The array of strings with tags replaced. public string[] ReplaceTags(string[] input, CCSPlayerController player) { - string[] output = new string[input.Length]; + string[] output = ReplaceLanguageTags(input); for (int i = 0; i < input.Length; i++) { - output[i] = ReplaceLanguageTags(input[i]); output[i] = ReplaceMessageTags(output[i], player, false); output[i] = ReplaceColorTags(output[i]); } @@ -54,28 +53,40 @@ public string[] ReplaceTags(string[] input, CCSPlayerController player) /// /// The input string to process. /// The input string with language tags replaced with localized values. - public string ReplaceLanguageTags(string input) + public string[] ReplaceLanguageTags(string[] input) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - + + List output = new List(); + // Define the regex pattern to find "{LANG=...}" string pattern = @"\{LANG=(.*?)\}"; - // Use Regex to find matches - Match match = Regex.Match(input, pattern); - - // Check if a match is found - if (match.Success) - { - // Return the group captured in the regex, which is the string after "=" - string lang = match.Groups[1].Value; - return input.Replace(match.Value, plugin.Localizer[lang] ?? " not found>"); - } - else + for (int i = 0; i < input.Length; i++) { - // Return the original string if no match is found - return input; + // Use Regex to find matches + Match match = Regex.Match(input[i], pattern); + + // Check if a match is found + if (match.Success) + { + // Return the group captured in the regex, which is the string after "=" + string lang = match.Groups[1].Value; + string replacedLang = input[i].Replace(match.Value, plugin.Localizer[lang] ?? " not found>"); + + // Check for \n in the replacedLang and split it into an array + string[] lines = WrappedLine(replacedLang); + + output.AddRange(lines); + } + else + { + // Return the original string if no match is found + output.Add(input[i]); + } } + + return output.ToArray(); } /// diff --git a/CustomCommands/tests.md b/CustomCommands/tests.md new file mode 100644 index 0000000..f0271af --- /dev/null +++ b/CustomCommands/tests.md @@ -0,0 +1,7 @@ +## Test befor publish + +* [ ] check if the css_ problem is working + * [ ] without adding css_ to the command in json + * [ ] with adding css_ to the command in json + * [ ] check if css_ip would work +* [ ] check if newline in language files works From 357f608f4744e40e4c5a367e16fecf6a556b713d Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Tue, 13 Feb 2024 13:04:31 +0100 Subject: [PATCH 04/24] fixed newline not working in LANG tag --- CustomCommands/CustomCommands.cs | 4 +- .../Interfaces/IReplaceTagsFunctions.cs | 6 +- CustomCommands/Services/CooldownManager.cs | 13 ++-- CustomCommands/Services/EventManager.cs | 6 +- CustomCommands/Services/MessageManager.cs | 12 ++-- CustomCommands/Services/RegisterCommands.cs | 32 ++++++---- .../Services/ReplaceTagsFunction.cs | 64 ++++++++----------- CustomCommands/tests.md | 2 + 8 files changed, 67 insertions(+), 72 deletions(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index b56f7bf..abd319e 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -63,8 +63,8 @@ public override void Load(bool hotReload) comms = RegisterCommands.CheckForDuplicateCommands(comms); // Add commands from the JSON file to the server - foreach (var com in comms) - RegisterCommands.AddCommands(com); + foreach (var cmd in comms) + RegisterCommands.AddCommands(cmd); } } } \ No newline at end of file diff --git a/CustomCommands/Interfaces/IReplaceTagsFunctions.cs b/CustomCommands/Interfaces/IReplaceTagsFunctions.cs index 2017a7d..0a0e59a 100644 --- a/CustomCommands/Interfaces/IReplaceTagsFunctions.cs +++ b/CustomCommands/Interfaces/IReplaceTagsFunctions.cs @@ -4,9 +4,9 @@ namespace CustomCommands.Interfaces; public interface IReplaceTagsFunctions { - string[] ReplaceTags(string[] input, CCSPlayerController player); - string[] ReplaceLanguageTags(string[] input); + string[] ReplaceTags(dynamic input, CCSPlayerController player); + string ReplaceLanguageTags(string input); string ReplaceMessageTags(string input, CCSPlayerController player, bool safety = true); string ReplaceColorTags(string input); - string[] WrappedLine(dynamic message); + List WrappedLine(dynamic message); } \ No newline at end of file diff --git a/CustomCommands/Services/CooldownManager.cs b/CustomCommands/Services/CooldownManager.cs index 642c65b..e08e7bb 100644 --- a/CustomCommands/Services/CooldownManager.cs +++ b/CustomCommands/Services/CooldownManager.cs @@ -10,8 +10,8 @@ public class CooldownManager : ICooldownManager public IReplaceTagsFunctions ReplaceTagsFunctions { get; } public CooldownManager(IPluginGlobals PluginGlobals, IReplaceTagsFunctions ReplaceTagsFunctions) { - this.PluginGlobals = PluginGlobals; - this.ReplaceTagsFunctions = ReplaceTagsFunctions; + this.PluginGlobals = PluginGlobals; + this.ReplaceTagsFunctions = ReplaceTagsFunctions; } /// @@ -46,11 +46,10 @@ public bool IsCommandOnCooldownWithCondition(Func predicate if (index != -1) { - double totalSeconds = PluginGlobals.CooldownTimer[index].CooldownTime.Subtract(DateTime.Now).TotalSeconds; - int totalSecondsRounded = (int)Math.Round(totalSeconds); - string timeleft = totalSecondsRounded.ToString(); - - string message = ""; + double totalSeconds = PluginGlobals.CooldownTimer[index].CooldownTime.Subtract(DateTime.Now).TotalSeconds; + int totalSecondsRounded = (int)Math.Round(totalSeconds); + string timeleft = totalSecondsRounded.ToString(); + string message = ""; // This is ugly as fuck try diff --git a/CustomCommands/Services/EventManager.cs b/CustomCommands/Services/EventManager.cs index 54b476a..7c47cce 100644 --- a/CustomCommands/Services/EventManager.cs +++ b/CustomCommands/Services/EventManager.cs @@ -14,9 +14,9 @@ public class EventManager : IEventManager public EventManager(IPluginGlobals PluginGlobals, IPluginContext PluginContext, IReplaceTagsFunctions ReplaceTagsFunctions) { - this.PluginGlobals = PluginGlobals; - this.PluginContext = (PluginContext as PluginContext)!; - this.ReplaceTagsFunctions = ReplaceTagsFunctions; + this.PluginGlobals = PluginGlobals; + this.PluginContext = (PluginContext as PluginContext)!; + this.ReplaceTagsFunctions = ReplaceTagsFunctions; } [GameEventHandler] diff --git a/CustomCommands/Services/MessageManager.cs b/CustomCommands/Services/MessageManager.cs index d6c0d32..630b4c7 100644 --- a/CustomCommands/Services/MessageManager.cs +++ b/CustomCommands/Services/MessageManager.cs @@ -60,9 +60,8 @@ public void PrintToCenterClient(CCSPlayerController player, Commands cmd) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - - string message = ReplaceTagsFunctions.ReplaceLanguageTags(cmd.CenterMessage.Message); - message = ReplaceTagsFunctions.ReplaceMessageTags(message, player); + string message = ReplaceTagsFunctions.ReplaceLanguageTags(cmd.Message); + message = ReplaceTagsFunctions.ReplaceMessageTags(message, player); var CenterClientElement = new CenterClientElement { @@ -77,8 +76,8 @@ public void PrintToAllCenter(Commands cmd) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - PluginGlobals.centerServerOn.Message = cmd.CenterMessage.Message; - PluginGlobals.centerServerOn.IsRunning = true; + PluginGlobals.centerServerOn.Message = cmd.CenterMessage.Message; + PluginGlobals.centerServerOn.IsRunning = true; plugin.AddTimer(cmd.CenterMessage.Time, () => { @@ -100,8 +99,7 @@ public void PrintToChatAndAllCenter(Receiver receiver, CCSPlayerController playe public void PrintToChat(Receiver printToChat, CCSPlayerController player, dynamic message) { - string[] msg = ReplaceTagsFunctions.WrappedLine(message); - msg = ReplaceTagsFunctions.ReplaceTags(msg, player); + string[] msg = ReplaceTagsFunctions.ReplaceTags(message, player); switch (printToChat) { diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index 0d912bb..cea7c9a 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -1,4 +1,3 @@ -using System.Text.Json; using CounterStrikeSharp.API.Core.Plugin; using CounterStrikeSharp.API.Modules.Commands; using CustomCommands.Interfaces; @@ -30,20 +29,28 @@ public RegisterCommands(ILogger Logger, IMessageManager MessageM /// /// Adds custom commands to the plugin. /// - /// The command to add. - public void AddCommands(Commands com) + /// The command to add. + public void AddCommands(Commands cmd) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - string[] aliases = PluginUtilities.GettingCommandsFromString(com.Command); + string[] aliases = PluginUtilities.GettingCommandsFromString(cmd.Command); for (int i = 0; i < aliases.Length; i++) { - plugin.AddCommand(aliases[i], com.Description, (player, info) => + plugin.AddCommand(aliases[i], cmd.Description, + [CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)] + (player, info) => { - if (player == null) return; - - var command = com; + if (player == null) + return; + if (info.ArgCount < aliases[i].Split(' ').Length) + { + player.PrintToChat($"This command requires at least {aliases[i].Split(' ').Length-1} arguments."); + return; + } + + var command = cmd; // Check if the command has arguments and if it does, check if the command really exists in the list if (info.ArgCount > 1) @@ -55,9 +62,6 @@ public void AddCommands(Commands com) command = findcommand; } - // Check if the command has arguments and check if the player uses the command with the alias - if (command!.Command.Contains(aliases[i] + " ") && info.ArgCount <= 1) - return; // Check if the player has the permission to use the command if (command!.Permission.PermissionList.Count > 0 && command.Permission != null) @@ -90,15 +94,15 @@ public List CheckForDuplicateCommands(List comms) List commands = new(); List commandNames = new(); - foreach (var com in comms) + foreach (var cmd in comms) { - string[] aliases = com.Command.Split(','); + string[] aliases = cmd.Command.Split(','); foreach (var alias in aliases) { if (commandNames.Contains(alias.ToLower())) { - duplicateCommands.Add(com); + duplicateCommands.Add(cmd); continue; } commandNames.Add(alias.ToLower()); diff --git a/CustomCommands/Services/ReplaceTagsFunction.cs b/CustomCommands/Services/ReplaceTagsFunction.cs index 76a33f6..0ee203e 100644 --- a/CustomCommands/Services/ReplaceTagsFunction.cs +++ b/CustomCommands/Services/ReplaceTagsFunction.cs @@ -32,17 +32,22 @@ public ReplaceTagsFunctions(IPluginGlobals PluginGlobals, IPluginContext PluginC /// The array of strings containing tags to be replaced. /// The CCSPlayerController object used for tag replacement. /// The array of strings with tags replaced. - public string[] ReplaceTags(string[] input, CCSPlayerController player) + public string[] ReplaceTags(dynamic input, CCSPlayerController player) { - string[] output = ReplaceLanguageTags(input); + List output = WrappedLine(input); - for (int i = 0; i < input.Length; i++) + for (int i = 0; i < output.Count; i++) + output[i] = ReplaceLanguageTags(input[i]); + + output = WrappedLine(output.ToArray()); + + for (int i = 0; i < output.Count; i++) { output[i] = ReplaceMessageTags(output[i], player, false); output[i] = ReplaceColorTags(output[i]); } - return output; + return output.ToArray(); } /// @@ -53,40 +58,28 @@ public string[] ReplaceTags(string[] input, CCSPlayerController player) /// /// The input string to process. /// The input string with language tags replaced with localized values. - public string[] ReplaceLanguageTags(string[] input) + public string ReplaceLanguageTags(string input) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - List output = new List(); - // Define the regex pattern to find "{LANG=...}" string pattern = @"\{LANG=(.*?)\}"; - for (int i = 0; i < input.Length; i++) - { - // Use Regex to find matches - Match match = Regex.Match(input[i], pattern); - - // Check if a match is found - if (match.Success) - { - // Return the group captured in the regex, which is the string after "=" - string lang = match.Groups[1].Value; - string replacedLang = input[i].Replace(match.Value, plugin.Localizer[lang] ?? " not found>"); + // Use Regex to find matches + Match match = Regex.Match(input, pattern); - // Check for \n in the replacedLang and split it into an array - string[] lines = WrappedLine(replacedLang); - - output.AddRange(lines); - } - else - { - // Return the original string if no match is found - output.Add(input[i]); - } + // Check if a match is found + if (match.Success) + { + // Return the group captured in the regex, which is the string after "=" + string lang = match.Groups[1].Value; + return input.Replace(match.Value, plugin.Localizer[lang] ?? " not found>"); + } + else + { + // Return the original string if no match is found + return input; } - - return output.ToArray(); } /// @@ -167,7 +160,7 @@ public string ReplaceColorTags(string input) /// /// This should be a string[] or a string /// An array of strings representing the lines of the input. - public string[] WrappedLine(dynamic input) + public List WrappedLine(dynamic input) { List output = new List(); @@ -177,8 +170,8 @@ public string[] WrappedLine(dynamic input) { case JsonValueKind.String: string result = jsonElement.GetString()!; - return result?.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None) ?? Array.Empty(); - + output.AddRange(result.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)); + break; case JsonValueKind.Array: foreach (var arrayElement in jsonElement.EnumerateArray()) { @@ -189,16 +182,15 @@ public string[] WrappedLine(dynamic input) default: Logger.LogError($"{PluginGlobals.Config.LogPrefix} Message is not a string or array"); - return Array.Empty(); + break; } } else { Logger.LogError($"{PluginGlobals.Config.LogPrefix} Invalid input type"); - return Array.Empty(); } - return output.ToArray(); + return output; } /// diff --git a/CustomCommands/tests.md b/CustomCommands/tests.md index f0271af..67f4e73 100644 --- a/CustomCommands/tests.md +++ b/CustomCommands/tests.md @@ -5,3 +5,5 @@ * [ ] with adding css_ to the command in json * [ ] check if css_ip would work * [ ] check if newline in language files works +* [ ] check if arguments still work + * [ ] check if argument message appears when not giving enough arguments From 10ddfd5bdd5f886c393184e4f6fa004da9c4e703 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Thu, 15 Feb 2024 20:20:42 +0100 Subject: [PATCH 05/24] Adding config option to disable css_ befor the cmd --- CustomCommands/CustomCommandsConfig.cs | 5 +++++ CustomCommands/Services/PluginUtilities.cs | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CustomCommands/CustomCommandsConfig.cs b/CustomCommands/CustomCommandsConfig.cs index 763fd61..fd1791b 100644 --- a/CustomCommands/CustomCommandsConfig.cs +++ b/CustomCommands/CustomCommandsConfig.cs @@ -6,6 +6,8 @@ namespace CustomCommands; public class CustomCommandsConfig : BasePluginConfig { + public override int Version { get; set; } = 2; + [JsonPropertyName("IsPluginEnabled")] public bool IsPluginEnabled { get; set; } = true; @@ -14,4 +16,7 @@ public class CustomCommandsConfig : BasePluginConfig [JsonPropertyName("Prefix")] public string Prefix { get; set; } = $"[{ChatColors.Yellow}Info{ChatColors.Default}] "; + + [JsonPropertyName("RegisterCommandsAsCSSFramework")] + public bool RegisterCommandsAsCSSFramework { get; set; } = true; } \ No newline at end of file diff --git a/CustomCommands/Services/PluginUtilities.cs b/CustomCommands/Services/PluginUtilities.cs index 7150191..dbac5a9 100644 --- a/CustomCommands/Services/PluginUtilities.cs +++ b/CustomCommands/Services/PluginUtilities.cs @@ -22,11 +22,17 @@ public PluginUtilities(IPluginGlobals PluginGlobals, IReplaceTagsFunctions Repla this.ReplaceTagsFunctions = ReplaceTagsFunctions; this.Logger = Logger; } + public string[] GettingCommandsFromString(string commands) { string[] splitCommands = SplitStringByCommaOrSemicolon(commands); - return AddCSSTagsToAliases(splitCommands); + + if (PluginGlobals.Config.RegisterCommandsAsCSSFramework) + return AddCSSTagsToAliases(splitCommands); + + return splitCommands; } + /// /// Adds the css_ prefix to each alias. /// This will help cs# tell this command belongs to the framework. From 9d0708f0be6483e35a30aadc9918c546f29c9799 Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Fri, 16 Feb 2024 13:32:18 +0100 Subject: [PATCH 06/24] Adding Execute Client COmmands --- CustomCommands/CustomCommands.cs | 2 +- CustomCommands/CustomCommands.csproj | 2 +- CustomCommands/Interfaces/IPluginUtilities.cs | 30 ++++++++++++ .../Interfaces/IRegisterCommands.cs | 10 ++++ CustomCommands/Model/CommandsConfig.cs | 2 + CustomCommands/Services/PluginUtilities.cs | 46 +++++++++++-------- CustomCommands/Services/RegisterCommands.cs | 6 +++ Examples/Permissions.json | 8 ++-- 8 files changed, 80 insertions(+), 26 deletions(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index b56f7bf..3dd1398 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -5,7 +5,7 @@ namespace CustomCommands; -[MinimumApiVersion(142)] +[MinimumApiVersion(167)] public partial class CustomCommands : BasePlugin, IPluginConfig { public override string ModuleName => "CustomCommands"; diff --git a/CustomCommands/CustomCommands.csproj b/CustomCommands/CustomCommands.csproj index 6038789..367a3b3 100644 --- a/CustomCommands/CustomCommands.csproj +++ b/CustomCommands/CustomCommands.csproj @@ -10,7 +10,7 @@ - + none runtime compile; build; native; contentfiles; analyzers; buildtransitive diff --git a/CustomCommands/Interfaces/IPluginUtilities.cs b/CustomCommands/Interfaces/IPluginUtilities.cs index feb444f..79747bd 100644 --- a/CustomCommands/Interfaces/IPluginUtilities.cs +++ b/CustomCommands/Interfaces/IPluginUtilities.cs @@ -5,7 +5,37 @@ namespace CustomCommands.Interfaces; public interface IPluginUtilities { + /// + /// Splits a string by comma, semicolon, or whitespace characters. + /// + /// The string to be split. + /// An array of strings containing the split substrings. string[] SplitStringByCommaOrSemicolon(string str); + /// + /// Executes the server commands from the command object + /// + /// + /// void ExecuteServerCommands(Commands cmd, CCSPlayerController player); + /// + /// Issue the specified command to the specified client (mimics that client typing the command at the console). + /// Note: Only works for some commands, marked with the FCVAR_CLIENT_CAN_EXECUTE flag (not many). + /// + /// + /// + void ExecuteClientCommands(Commands cmd, CCSPlayerController player); + /// + /// Issue the specified command directly from the server (mimics the server executing the command with the given player context). + /// Works with server commands like `kill`, `explode`, `noclip`, etc. + /// + /// + /// + void ExecuteClientCommandsFromServer(Commands cmd, CCSPlayerController player); + /// + /// Checks if the player has the required permissions to execute the command + /// + /// + /// + /// bool RequiresPermissions(CCSPlayerController player, Permission permissions); } diff --git a/CustomCommands/Interfaces/IRegisterCommands.cs b/CustomCommands/Interfaces/IRegisterCommands.cs index 2680673..fb81515 100644 --- a/CustomCommands/Interfaces/IRegisterCommands.cs +++ b/CustomCommands/Interfaces/IRegisterCommands.cs @@ -4,6 +4,16 @@ namespace CustomCommands.Interfaces; public interface IRegisterCommands { + /// + /// Adds custom commands to the plugin. + /// + /// The command to add. void AddCommands(Commands cmd); + + /// + /// Checks for duplicate commands in the provided list and removes them. + /// + /// The list of commands to check for duplicates. + /// A new list of commands without any duplicates. List CheckForDuplicateCommands(List comms); } diff --git a/CustomCommands/Model/CommandsConfig.cs b/CustomCommands/Model/CommandsConfig.cs index 1cc96b1..3582430 100644 --- a/CustomCommands/Model/CommandsConfig.cs +++ b/CustomCommands/Model/CommandsConfig.cs @@ -11,6 +11,8 @@ public class Commands public CenterElement CenterMessage { get; set; } = new(); public Sender PrintTo { get; set; } = Sender.ClientChat; public List ServerCommands { get; set; } = new(); + public List ClientCommands { get; set; } = new(); + public List ClientCommandsFromServer { get; set; } = new(); public Permission Permission { get; set; } = new(); } public class Cooldown diff --git a/CustomCommands/Services/PluginUtilities.cs b/CustomCommands/Services/PluginUtilities.cs index 5737ce3..fc5a3fd 100644 --- a/CustomCommands/Services/PluginUtilities.cs +++ b/CustomCommands/Services/PluginUtilities.cs @@ -14,7 +14,7 @@ public class PluginUtilities : IPluginUtilities private readonly IPluginGlobals PluginGlobals; private readonly IReplaceTagsFunctions ReplaceTagsFunctions; private readonly ILogger Logger; - + public PluginUtilities(IPluginGlobals PluginGlobals, IReplaceTagsFunctions ReplaceTagsFunctions, ILogger Logger) { @@ -23,23 +23,14 @@ public PluginUtilities(IPluginGlobals PluginGlobals, IReplaceTagsFunctions Repla this.Logger = Logger; } - /// - /// Splits a string by comma, semicolon, or whitespace characters. - /// - /// The string to be split. - /// An array of strings containing the split substrings. public string[] SplitStringByCommaOrSemicolon(string str) { return Regex.Split(str, ",|;|\\s") .Where(s => !string.IsNullOrEmpty(s)) .ToArray(); } - /// - /// Executes the server commands from the command object - /// - /// - /// - public void ExecuteServerCommands(Commands cmd, CCSPlayerController player) + + public void ExecuteServerCommands(Commands cmd, CCSPlayerController player) { if (cmd.ServerCommands.Count == 0) return; @@ -55,6 +46,26 @@ public void ExecuteServerCommands(Commands cmd, CCSPlayerController player) Server.ExecuteCommand(ReplaceTagsFunctions.ReplaceMessageTags(serverCommand, player)); } } + + public void ExecuteClientCommands(Commands cmd, CCSPlayerController player) + { + if (cmd.ClientCommands.Count == 0) return; + + foreach (var clientCommand in cmd.ClientCommands) + { + player.ExecuteClientCommand(ReplaceTagsFunctions.ReplaceMessageTags(clientCommand, player)); + } + } + + public void ExecuteClientCommandsFromServer(Commands cmd, CCSPlayerController player) + { + if (cmd.ClientCommandsFromServer.Count == 0) return; + + foreach (var clientCommandsFromServer in cmd.ClientCommandsFromServer) + { + player.ExecuteClientCommandFromServer(ReplaceTagsFunctions.ReplaceMessageTags(clientCommandsFromServer, player)); + } + } /// /// Handles the toggle command /// @@ -65,7 +76,7 @@ private void HandleToggleCommand(string serverCommand) var commandCvar = ConVar.Find(commandWithoutToggle); if (commandCvar != null) { - if(commandCvar.GetPrimitiveValue()) + if (commandCvar.GetPrimitiveValue()) Server.ExecuteCommand($"{commandWithoutToggle} 0"); else Server.ExecuteCommand($"{commandWithoutToggle} 1"); @@ -75,19 +86,14 @@ private void HandleToggleCommand(string serverCommand) Logger.LogError($"Couldn't toggle {commandWithoutToggle}. Please check if this command is toggleable"); } } - /// - /// Checks if the player has the required permissions to execute the command - /// - /// - /// - /// + public bool RequiresPermissions(CCSPlayerController player, Permission permissions) { if (!permissions.RequiresAllPermissions) { foreach (var permission in permissions.PermissionList) { - if (AdminManager.PlayerHasPermissions(player, new string[]{permission})) + if (AdminManager.PlayerHasPermissions(player, new string[] { permission })) return true; } player.PrintToChat($"{PluginGlobals.Config.Prefix}You don't have the required permissions to execute this command"); diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index 4e605ff..7646d09 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -74,6 +74,12 @@ public void AddCommands(Commands com) // Execute the server commands PluginUtilities.ExecuteServerCommands(command, player); + + // Execute the client commands + PluginUtilities.ExecuteClientCommands(command, player); + + // Execute the client commands from the server + PluginUtilities.ExecuteClientCommandsFromServer(command, player); }); } } diff --git a/Examples/Permissions.json b/Examples/Permissions.json index b12216c..209cf28 100644 --- a/Examples/Permissions.json +++ b/Examples/Permissions.json @@ -8,10 +8,10 @@ "Permission": { "RequiresPermissionOr": false, // true = Requires one of the permissions in the list | false = Requires all of the permissions in the list "PermissionList": [ - "@css/cvar", // normal css permissions - "@custom/permission", // create your own permissions - "#css/simple-admin" // needs to be in the simple-admin group + "@css/cvar", // normal css permissions + "@custom/permission", // create your own permissions + "#css/simple-admin" // needs to be in the simple-admin group ] - } + } } ] \ No newline at end of file From 1e800101b52f00e50bad183329b8332a2453b214 Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Fri, 16 Feb 2024 14:31:59 +0100 Subject: [PATCH 07/24] Updating Examples to markdown with more explanation --- CustomCommands/Interfaces/IPluginUtilities.cs | 17 ++++++ CustomCommands/Services/PluginUtilities.cs | 11 ---- CustomCommands/tests.md | 2 + ...thColor.json => CenterMessageWithColor.md} | 13 +++-- Examples/ClientCommands.md | 53 +++++++++++++++++++ Examples/{Colors.json => Colors.md} | 20 ++++++- ...Arguments.json => CommandWithArguments.md} | 9 +++- Examples/{Cooldown.json => Cooldown.md} | 13 ++++- ...anguageSupport.json => LanguageSupport.md} | 11 +++- ...d.json => MulitpleAliasesForOneCommand.md} | 11 +++- Examples/{NewLines.json => NewLines.md} | 9 +++- Examples/{Permissions.json => Permissions.md} | 12 ++++- Examples/{PrintTo.json => PrintTo.md} | 20 ++++++- Examples/README.md | 15 ++++++ ...{ServerCommands.json => ServerCommands.md} | 20 +++++-- ...{SimpleCommands.json => SimpleCommands.md} | 9 +++- Examples/{Tags.json => Tags.md} | 11 +++- Examples/ToggleServerCommands.json | 21 -------- Examples/ToggleServerCommands.md | 28 ++++++++++ 19 files changed, 254 insertions(+), 51 deletions(-) rename Examples/{CenterMessageWithColor.json => CenterMessageWithColor.md} (58%) create mode 100644 Examples/ClientCommands.md rename Examples/{Colors.json => Colors.md} (62%) rename Examples/{CommandWithArguments.json => CommandWithArguments.md} (77%) rename Examples/{Cooldown.json => Cooldown.md} (70%) rename Examples/{LanguageSupport.json => LanguageSupport.md} (54%) rename Examples/{MulitpleAliasesForOneCommand.json => MulitpleAliasesForOneCommand.md} (58%) rename Examples/{NewLines.json => NewLines.md} (90%) rename Examples/{Permissions.json => Permissions.md} (71%) rename Examples/{PrintTo.json => PrintTo.md} (78%) rename Examples/{ServerCommands.json => ServerCommands.md} (79%) rename Examples/{SimpleCommands.json => SimpleCommands.md} (82%) rename Examples/{Tags.json => Tags.md} (92%) delete mode 100644 Examples/ToggleServerCommands.json create mode 100644 Examples/ToggleServerCommands.md diff --git a/CustomCommands/Interfaces/IPluginUtilities.cs b/CustomCommands/Interfaces/IPluginUtilities.cs index 0a34bc8..4741aad 100644 --- a/CustomCommands/Interfaces/IPluginUtilities.cs +++ b/CustomCommands/Interfaces/IPluginUtilities.cs @@ -5,20 +5,35 @@ namespace CustomCommands.Interfaces; public interface IPluginUtilities { + /// + /// Splits the commands string into an array of strings. + /// + /// + /// string[] GettingCommandsFromString(string commands); + + /// + /// Adds the css_ prefix to each alias. + /// This will help cs# tell this command belongs to the framework. + /// + /// + /// string[] AddCSSTagsToAliases(string[] input); + /// /// Splits a string by comma, semicolon, or whitespace characters. /// /// The string to be split. /// An array of strings containing the split substrings. string[] SplitStringByCommaOrSemicolon(string str); + /// /// Executes the server commands from the command object /// /// /// void ExecuteServerCommands(Commands cmd, CCSPlayerController player); + /// /// Issue the specified command to the specified client (mimics that client typing the command at the console). /// Note: Only works for some commands, marked with the FCVAR_CLIENT_CAN_EXECUTE flag (not many). @@ -26,6 +41,7 @@ public interface IPluginUtilities /// /// void ExecuteClientCommands(Commands cmd, CCSPlayerController player); + /// /// Issue the specified command directly from the server (mimics the server executing the command with the given player context). /// Works with server commands like `kill`, `explode`, `noclip`, etc. @@ -33,6 +49,7 @@ public interface IPluginUtilities /// /// void ExecuteClientCommandsFromServer(Commands cmd, CCSPlayerController player); + /// /// Checks if the player has the required permissions to execute the command /// diff --git a/CustomCommands/Services/PluginUtilities.cs b/CustomCommands/Services/PluginUtilities.cs index e093e80..9c80659 100644 --- a/CustomCommands/Services/PluginUtilities.cs +++ b/CustomCommands/Services/PluginUtilities.cs @@ -33,12 +33,6 @@ public string[] GettingCommandsFromString(string commands) return splitCommands; } - /// - /// Adds the css_ prefix to each alias. - /// This will help cs# tell this command belongs to the framework. - /// - /// - /// public string[] AddCSSTagsToAliases(string[] input) { for (int i = 0; i < input.Length; i++) @@ -49,11 +43,6 @@ public string[] AddCSSTagsToAliases(string[] input) return input; } - /// - /// Splits a string by comma, semicolon, or whitespace characters. - /// - /// The string to be split. - /// An array of strings containing the split substrings. public string[] SplitStringByCommaOrSemicolon(string str) { return Regex.Split(str, ",|;|\\s") diff --git a/CustomCommands/tests.md b/CustomCommands/tests.md index 67f4e73..4a2c1dd 100644 --- a/CustomCommands/tests.md +++ b/CustomCommands/tests.md @@ -7,3 +7,5 @@ * [ ] check if newline in language files works * [ ] check if arguments still work * [ ] check if argument message appears when not giving enough arguments +* [ ] Test Client commands +* [ ] Test ClientServer Commands diff --git a/Examples/CenterMessageWithColor.json b/Examples/CenterMessageWithColor.md similarity index 58% rename from Examples/CenterMessageWithColor.json rename to Examples/CenterMessageWithColor.md index a60590e..e232bbb 100644 --- a/Examples/CenterMessageWithColor.json +++ b/Examples/CenterMessageWithColor.md @@ -1,10 +1,16 @@ +## Center Message with color: + +It is possible to add HTML to the center Message that means its possible to add any color to it. Here are some examples. + + +```json [ { "Title": "Center Message with color", "Description": "Center Message with color", "Command": "colorcenter", "CenterMessage": { - "Message": "Cool color here", + "Message": "``Cool color here``", "Time": 5 // Seconds }, "PrintTo": 2 @@ -15,9 +21,10 @@ "Description": "With html", "Command": "htmlcenter", "CenterMessage": { - "Message": "
Steam Group

https...
", + "Message": "`
`Steam Group`

``
`https...`
`", "Time": 5 // Seconds }, "PrintTo": 2 } -] \ No newline at end of file +] +``` diff --git a/Examples/ClientCommands.md b/Examples/ClientCommands.md new file mode 100644 index 0000000..2993978 --- /dev/null +++ b/Examples/ClientCommands.md @@ -0,0 +1,53 @@ +## Execute Client Commands + +If you want to execute Commands for the client here are to different ways of doing it. + +#### Execute Client Command: + +This means you are simulating typing the command in the players console. Be aware this only works for commands that can be executed by the client. + +Example: + +```json +[ + { + "Title": "Open Buy menu", + "Description": "Opens the buy menu for the player", + "Command": "buy", + "Message": "Opening buy Menu...", + "PrintTo": 0, + "ClientCommands": [ + "buymenu" + ] + } +] +``` + + +#### Execute Client Command from Server: + +Issue the specified command directly from the server (mimics the server executing the command with the given player context). + +Works with server commands like `kill`, `explode`, `noclip`, etc. + +Example: + +```json +[ + { + "Title": "Noclip", + "Description": "Noclips player", + "Command": "noclip", + "Message": "Noclip...", + "PrintTo": 0, + "ServerCommands": [ + "noclip" + ] + } +] +``` + + +### Important! + +Its always recommended to Permission to the command so not every player can use the command and execute commands on your server diff --git a/Examples/Colors.json b/Examples/Colors.md similarity index 62% rename from Examples/Colors.json rename to Examples/Colors.md index 84f798a..93fcc49 100644 --- a/Examples/Colors.json +++ b/Examples/Colors.md @@ -1,9 +1,24 @@ +## Colored Messages + +If you want to add Color to your chat message you need to use the color tags. + +Here are all color tags: + +### Colorlist + +![CS2Colors](../.github/img/ColorsCS2.png "CS2Colors") + +### Note + +If you want to add color to the Center Message check this out: [Color For CenterMessage](./CenterMessageWithColor.md) + +```json [ { "Title": "Rainbow", "Description": "rainbow command", "Command": "rainbow", - "Message": "{RED}R{ORANGE}A{YELLOW}I{GREEN}N{BLUE}B{DARKBLUE}O{PURPLE}W", + "Message": "{RED}R{ORANGE}A{YELLOW}I{GREEN}N{BLUE}B{DARKBLUE}O{PURPLE}W", "PrintTo": 0 }, { @@ -13,4 +28,5 @@ "Message": "{DEFAULT}1, {WHITE}2 \n{DARKRED}3, {RED}4, {LIGHTRED}5\n{GREEN}6, {LIME}7, {OLIVE}8\n{ORANGE}9, {GOLD}10, {YELLOW}11\n{BLUE}12, {DARKBLUE}13\n{LIGHTPURPLE}14 {PURPLE}15 \n,{GREY}18", "PrintTo": 0 } -] \ No newline at end of file +] +``` diff --git a/Examples/CommandWithArguments.json b/Examples/CommandWithArguments.md similarity index 77% rename from Examples/CommandWithArguments.json rename to Examples/CommandWithArguments.md index 873555b..9c273fb 100644 --- a/Examples/CommandWithArguments.json +++ b/Examples/CommandWithArguments.md @@ -1,3 +1,9 @@ +## Command with Arguments + +You can also create your own commands with arguments/numbers after it. + + +```json [ { "Title": "Arguments 1", @@ -13,4 +19,5 @@ "Message": "Help me with 2 argument", "PrintTo": 0 } -] \ No newline at end of file +] +``` diff --git a/Examples/Cooldown.json b/Examples/Cooldown.md similarity index 70% rename from Examples/Cooldown.json rename to Examples/Cooldown.md index 34b8286..2d85b32 100644 --- a/Examples/Cooldown.json +++ b/Examples/Cooldown.md @@ -1,3 +1,13 @@ +## Cooldown for commands + +Here are two ways to add a cooldown for a command. + +The simple command is just a cooldown for the current player who used the command + +In the Advanced command example you can add a "IsGlobal" flag so the whole server has a cooldown for this command not just the Player who uses it + + +```json [ //Simple cooldown command { @@ -21,4 +31,5 @@ "Message": "Cool cooldown message!", "PrintTo": 0 } -] \ No newline at end of file +] +``` diff --git a/Examples/LanguageSupport.json b/Examples/LanguageSupport.md similarity index 54% rename from Examples/LanguageSupport.json rename to Examples/LanguageSupport.md index 5bff262..310659f 100644 --- a/Examples/LanguageSupport.json +++ b/Examples/LanguageSupport.md @@ -1,3 +1,11 @@ +## Language support for Commands + +If you have a server with players from all over the world you probably want a way to output the message into multiple languages. + +Here in the example you can see there is a {LANG} tag. The 'test' after the LANG= points to the language tag in CustomCommands/lang. + + +```json [ { "Title": "Sentance", @@ -11,4 +19,5 @@ "Time": 10 } } -] \ No newline at end of file +] +``` diff --git a/Examples/MulitpleAliasesForOneCommand.json b/Examples/MulitpleAliasesForOneCommand.md similarity index 58% rename from Examples/MulitpleAliasesForOneCommand.json rename to Examples/MulitpleAliasesForOneCommand.md index 2c03bba..6ae7c0b 100644 --- a/Examples/MulitpleAliasesForOneCommand.json +++ b/Examples/MulitpleAliasesForOneCommand.md @@ -1,3 +1,11 @@ +## Multiple Aliases for one Command + +Here is a way of creating aliases for a command. + +For example there are many ways a user would try to get the discord link. Using a "," or ";" solve the issue + + +```json [ { "Title": "Discord", @@ -6,4 +14,5 @@ "Message": "{PREFIX}Discord: https://discord.gg/Z9JfJ9Y57C", "PrintTo": 0 } -] \ No newline at end of file +] +``` diff --git a/Examples/NewLines.json b/Examples/NewLines.md similarity index 90% rename from Examples/NewLines.json rename to Examples/NewLines.md index 631a90b..4e39c39 100644 --- a/Examples/NewLines.json +++ b/Examples/NewLines.md @@ -1,3 +1,9 @@ +## New Lines + +Here are two ways of breaking the message into two or more lines. + + +```json [ { "Title": "Steam group", @@ -31,4 +37,5 @@ ], "PrintTo": 0 } -] \ No newline at end of file +] +``` diff --git a/Examples/Permissions.json b/Examples/Permissions.md similarity index 71% rename from Examples/Permissions.json rename to Examples/Permissions.md index 209cf28..42831ec 100644 --- a/Examples/Permissions.json +++ b/Examples/Permissions.md @@ -1,3 +1,12 @@ +## Permissions + +Adding Permission check who can execute the command. + +This is just like adding Permissions for player just for the command + +[How it works:](https://docs.cssharp.dev/docs/admin-framework/defining-admins.html) + +```json [ { "Title": "Ping", @@ -14,4 +23,5 @@ ] } } -] \ No newline at end of file +] +``` diff --git a/Examples/PrintTo.json b/Examples/PrintTo.md similarity index 78% rename from Examples/PrintTo.json rename to Examples/PrintTo.md index 8e34708..24a361b 100644 --- a/Examples/PrintTo.json +++ b/Examples/PrintTo.md @@ -1,9 +1,24 @@ +## Print To / Decide where the message gets displayed + +Here are all combinations listed where you can print the message. + +The default values are + +0 - Client Chat = Only the player who executed the command gets the message + +1 - All Chat = The whole server gets the message when a player executes the command + +2 - Client Center = The player who executed the command gets a message in the center + +3 - All Center = The whole server gets the message to the center when a player executes the command + +```json [ { "Title": "Client Chat", "Description": "Client Chat message", "Command": "clientchat", - "Message": "ClientChat", + "Message": "ClientChat", "PrintTo": 0 }, { @@ -77,4 +92,5 @@ }, "PrintTo": 7 } -] \ No newline at end of file +] +``` diff --git a/Examples/README.md b/Examples/README.md index 1bc9407..4512e4d 100644 --- a/Examples/README.md +++ b/Examples/README.md @@ -1,3 +1,18 @@ ## Examples These are some examples what is possible with this plugin. + +1. [Print To](./PrintTo.md) +2. [Simple Command Examples](./SimpleCommands.md) +3. [Colored Messages](./Colors.md) +4. [Tags](./Tags.md) +5. [Cooldown](./Cooldown.md) +6. [Language Support for commands](./LanguageSupport.md) +7. [Center Message with Colors](./CenterMessageWithColor.md) +8. [Commands with Arguments](./CommandWithArguments.md) +9. [Multiple Aliases for one Command](./MultipleAliasesForOneCommand.md) +10. [New Line](./NewLines.md) +11. [Permissions](./Permissions.md) +12. [Server Commands](./ServerCommands.md) +13. [Toggle Server Commands](./ToggleServerCommands.md) +14. [Execute Client Commands](./ClientCommands.md) diff --git a/Examples/ServerCommands.json b/Examples/ServerCommands.md similarity index 79% rename from Examples/ServerCommands.json rename to Examples/ServerCommands.md index d0e85c8..2d77962 100644 --- a/Examples/ServerCommands.json +++ b/Examples/ServerCommands.md @@ -1,3 +1,14 @@ +## Execute Server Commands + +If you want to execute server commands with you command this is the way of doing it. + + +### Important! + +Its always recommended to Permission to the command so not every player can use the command and execute commands on your server + + +```json [ { "Title": "Restart", @@ -31,7 +42,7 @@ "cl_ragdoll_gravity 0", "sv_accelerate 10", "sv_airaccelerate 1400", - "sv_gravity 800.0" + "sv_gravity 800.0" ], "Permission": { "RequiresPermissionOr": true, @@ -45,10 +56,11 @@ "Title": "Kickme", "Description": "command that kicks yourself", "Command": "kickme", - "Message": "Getting Kicket", + "Message": "Getting Kicked", "PrintTo": 0, "ServerCommands": [ - "kick {PLAYERNAME}" // Tags work for commands as well + "kick {USERID}" // Tags work for commands as well ] } -] \ No newline at end of file +] +``` diff --git a/Examples/SimpleCommands.json b/Examples/SimpleCommands.md similarity index 82% rename from Examples/SimpleCommands.json rename to Examples/SimpleCommands.md index 11cbe0e..05f7a64 100644 --- a/Examples/SimpleCommands.json +++ b/Examples/SimpleCommands.md @@ -1,3 +1,9 @@ +## Simple Commands + +Here are some examples for very simple commands + + +```json [ { "Title": "Ping", @@ -13,4 +19,5 @@ "Message": "test", "PrintTo": 0 } -] \ No newline at end of file +] +``` diff --git a/Examples/Tags.json b/Examples/Tags.md similarity index 92% rename from Examples/Tags.json rename to Examples/Tags.md index 4ccc25c..c4f3abf 100644 --- a/Examples/Tags.json +++ b/Examples/Tags.md @@ -1,3 +1,11 @@ +## Tags for Dynamic Command + +Here is a list of tags you can add to the message. Its also possible to use some tags with the combination of Executing commands. + +The tags are always in {TAG} + + +``` [ { "Title": "Prefix", @@ -83,4 +91,5 @@ "Message": "Current players userid: {USERID}", // If you want to use this tag for commands add a # before the tag "PrintTo": 0 } -] \ No newline at end of file +] +``` diff --git a/Examples/ToggleServerCommands.json b/Examples/ToggleServerCommands.json deleted file mode 100644 index 611a54a..0000000 --- a/Examples/ToggleServerCommands.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "Title": "Toggle sv_cheats", - "Description": "Command for toggling sv_cheats", - "Command": "cheats", - "Message": "Toggled sv_cheats", - "PrintTo": 0, - "ServerCommands": [ - // if you add toggle befor the command it will toggle the value. If it was 1 it will be 0 and if it was 0 it will be 1 - // if you add toggle to the start of the command you dont need to add a number after it - // This only works with commands that have 0 or 1 as a value - "toggle sv_cheats" - ], - "Permission": { - "RequiresPermissionOr": false, - "PermissionList": [ - "#css/moderator" - ] - } - } -] \ No newline at end of file diff --git a/Examples/ToggleServerCommands.md b/Examples/ToggleServerCommands.md new file mode 100644 index 0000000..9fefe2f --- /dev/null +++ b/Examples/ToggleServerCommands.md @@ -0,0 +1,28 @@ +## Toggling Server Commands + +Do you dont want to create two commands for switching Server Commands on and of here is a way to do this easier. + +If you add toggle befor the command it will toggle the value. If it was 1 it will be 0 and if it was 0 it will be 1 +if you add toggle to the start of the command you dont need to add a number after it +Be aware this only works with commands that have 0 or 1 as a value! + +```json +[ + { + "Title": "Toggle sv_cheats", + "Description": "Command for toggling sv_cheats", + "Command": "cheats", + "Message": "Toggled sv_cheats", + "PrintTo": 0, + "ServerCommands": [ + "toggle sv_cheats" + ], + "Permission": { + "RequiresPermissionOr": false, + "PermissionList": [ + "#css/moderator" + ] + } + } +] +``` From a64b78120f3eb32b48c984abd52e48fb57b287b4 Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Sun, 21 Apr 2024 21:09:39 +0200 Subject: [PATCH 08/24] update to dotnet 8 --- CustomCommands/CustomCommands.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CustomCommands/CustomCommands.csproj b/CustomCommands/CustomCommands.csproj index 367a3b3..887cd4f 100644 --- a/CustomCommands/CustomCommands.csproj +++ b/CustomCommands/CustomCommands.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false @@ -10,7 +10,7 @@ - + none runtime compile; build; native; contentfiles; analyzers; buildtransitive From 4b0c62e32bde2e69dcd9b2f0ff1a390d971b0fc3 Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Sun, 21 Apr 2024 21:10:36 +0200 Subject: [PATCH 09/24] update css to 213 and normal v to 2.1.0 --- CustomCommands/CustomCommands.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index 92c3961..59bd1f2 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -5,11 +5,11 @@ namespace CustomCommands; -[MinimumApiVersion(167)] +[MinimumApiVersion(213)] public partial class CustomCommands : BasePlugin, IPluginConfig { public override string ModuleName => "CustomCommands"; - public override string ModuleVersion => "2.0.4"; + public override string ModuleVersion => "2.1.0"; public override string ModuleAuthor => "HerrMagic"; public override string ModuleDescription => "Create your own commands per config"; From 96e0b9a697128a9a3c26b913aa55db523edcca69 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 26 May 2024 14:44:27 +0200 Subject: [PATCH 10/24] fixed WrappedLine accepting normal Array --- CustomCommands/Services/RegisterCommands.cs | 10 ++++++---- CustomCommands/Services/ReplaceTagsFunction.cs | 9 ++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index 0edec86..cf99ec3 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -38,15 +38,17 @@ public void AddCommands(Commands cmd) for (int i = 0; i < aliases.Length; i++) { - plugin.AddCommand(aliases[i], cmd.Description, + string alias = aliases[i]; + plugin.AddCommand(alias, cmd.Description, [CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)] (player, info) => { if (player == null) return; - if (info.ArgCount < aliases[i].Split(' ').Length) + + if (info.ArgCount < alias.Split(' ').Length) { - player.PrintToChat($"This command requires at least {aliases[i].Split(' ').Length-1} arguments."); + player.PrintToChat($"This command requires at least {alias.Split(' ').Length-1} arguments."); return; } @@ -55,7 +57,7 @@ public void AddCommands(Commands cmd) // Check if the command has arguments and if it does, check if the command really exists in the list if (info.ArgCount > 1) { - var findcommand = PluginGlobals.CustomCommands.Find(x => x.Command.Contains(aliases[i] + $" {info.ArgString}")); + var findcommand = PluginGlobals.CustomCommands.Find(x => x.Command.Contains(alias + $" {info.ArgString}")); // Check if the command is equal to the found command if (findcommand! != command) return; diff --git a/CustomCommands/Services/ReplaceTagsFunction.cs b/CustomCommands/Services/ReplaceTagsFunction.cs index 0ee203e..77209e3 100644 --- a/CustomCommands/Services/ReplaceTagsFunction.cs +++ b/CustomCommands/Services/ReplaceTagsFunction.cs @@ -37,7 +37,7 @@ public string[] ReplaceTags(dynamic input, CCSPlayerController player) List output = WrappedLine(input); for (int i = 0; i < output.Count; i++) - output[i] = ReplaceLanguageTags(input[i]); + output[i] = ReplaceLanguageTags(output[i]); output = WrappedLine(output.ToArray()); @@ -184,6 +184,13 @@ public List WrappedLine(dynamic input) Logger.LogError($"{PluginGlobals.Config.LogPrefix} Message is not a string or array"); break; } + } else if (input is Array inputArray) + { + foreach (string arrayElement in inputArray) + { + string[] lines = arrayElement.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None) ?? Array.Empty(); + output.AddRange(lines); + } } else { From 83dcb5fa9490eb9cfd1eb44d89485516e390bce6 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 26 May 2024 14:47:36 +0200 Subject: [PATCH 11/24] fixed wrong Tag showing in Cooldown Examples --- Examples/Cooldown.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/Cooldown.md b/Examples/Cooldown.md index 2d85b32..ecb9736 100644 --- a/Examples/Cooldown.md +++ b/Examples/Cooldown.md @@ -26,7 +26,7 @@ In the Advanced command example you can add a "IsGlobal" flag so the whole serve "Cooldown": { "CooldownTime": 5, // required, Cooldown in seconds "IsGlobal": false, // If true, cooldown will be global for all users - "CooldownMessage": "This command is on cooldown for {TIME} more seconds!" + "CooldownMessage": "This command is on cooldown for {TIMELEFT} more seconds!" }, "Message": "Cool cooldown message!", "PrintTo": 0 From 805cf584f6e95d9d22ccc8ebc700509a3ffd623b Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 26 May 2024 15:00:05 +0200 Subject: [PATCH 12/24] update ServerCommand Kick example --- Examples/ServerCommands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/ServerCommands.md b/Examples/ServerCommands.md index 2d77962..eec8295 100644 --- a/Examples/ServerCommands.md +++ b/Examples/ServerCommands.md @@ -59,7 +59,7 @@ Its always recommended to Permission to the command so not every player can use "Message": "Getting Kicked", "PrintTo": 0, "ServerCommands": [ - "kick {USERID}" // Tags work for commands as well + "css_kick #{USERID}" // Tags work for commands as well. This command works with Simple Admin ] } ] From 87f760e79975893a306b2234949f66efee521996 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 26 May 2024 15:06:13 +0200 Subject: [PATCH 13/24] Fixed CenterMessage not working --- CustomCommands/Services/MessageManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CustomCommands/Services/MessageManager.cs b/CustomCommands/Services/MessageManager.cs index 630b4c7..6a27e07 100644 --- a/CustomCommands/Services/MessageManager.cs +++ b/CustomCommands/Services/MessageManager.cs @@ -60,7 +60,7 @@ public void PrintToCenterClient(CCSPlayerController player, Commands cmd) { CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - string message = ReplaceTagsFunctions.ReplaceLanguageTags(cmd.Message); + string message = ReplaceTagsFunctions.ReplaceLanguageTags(cmd.CenterMessage.Message); message = ReplaceTagsFunctions.ReplaceMessageTags(message, player); var CenterClientElement = new CenterClientElement From 02d8e16e23e51c5741885c887436cb69ef55ad95 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 26 May 2024 16:13:17 +0200 Subject: [PATCH 14/24] args still not working --- CustomCommands/Interfaces/IPluginUtilities.cs | 2 +- CustomCommands/Services/PluginUtilities.cs | 49 ++++++++++++++++--- CustomCommands/Services/RegisterCommands.cs | 2 + 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/CustomCommands/Interfaces/IPluginUtilities.cs b/CustomCommands/Interfaces/IPluginUtilities.cs index 4741aad..97f1c09 100644 --- a/CustomCommands/Interfaces/IPluginUtilities.cs +++ b/CustomCommands/Interfaces/IPluginUtilities.cs @@ -18,7 +18,7 @@ public interface IPluginUtilities ///
/// /// - string[] AddCSSTagsToAliases(string[] input); + string[] AddCSSTagsToAliases(List input); /// /// Splits a string by comma, semicolon, or whitespace characters. diff --git a/CustomCommands/Services/PluginUtilities.cs b/CustomCommands/Services/PluginUtilities.cs index 9c80659..6c8fd21 100644 --- a/CustomCommands/Services/PluginUtilities.cs +++ b/CustomCommands/Services/PluginUtilities.cs @@ -26,26 +26,63 @@ public PluginUtilities(IPluginGlobals PluginGlobals, IReplaceTagsFunctions Repla public string[] GettingCommandsFromString(string commands) { string[] splitCommands = SplitStringByCommaOrSemicolon(commands); + List commandsList = new List(); + // Removes arguments from the command when spaces are present + for (int i = 0; i < splitCommands.Length; i++) + { + if (splitCommands[i].Contains(' ')) + { + Logger.LogInformation($"Contains space!"); + if (splitCommands[i].IndexOf(' ') == 0) + { + commandsList.Add(splitCommands[i]); + continue; + } + Logger.LogInformation($"Is multiple args"); + string sub = splitCommands[i].Substring(0, splitCommands[i].IndexOf(' ')); + Logger.LogInformation($"Sub: {sub}"); + if (commandsList.Contains(sub)) + { + Logger.LogInformation("In IF"); + continue; + } + + if (!contains) + commandsList.Add(sub); + } + else + { + if (!commandsList.Contains(splitCommands[i])) + commandsList.Add(splitCommands[i]); + } + } + + + foreach (var command in commandsList) + { + Logger.LogInformation($"Command: {command}"); + } if (PluginGlobals.Config.RegisterCommandsAsCSSFramework) - return AddCSSTagsToAliases(splitCommands); + return AddCSSTagsToAliases(commandsList); - return splitCommands; + + return commandsList.ToArray(); } - public string[] AddCSSTagsToAliases(string[] input) + public string[] AddCSSTagsToAliases(List input) { - for (int i = 0; i < input.Length; i++) + for (int i = 0; i < input.Count; i++) { if (!input[i].StartsWith("css_")) input[i] = "css_" + input[i]; } - return input; + return input.ToArray(); } public string[] SplitStringByCommaOrSemicolon(string str) { - return Regex.Split(str, ",|;|\\s") + return Regex.Split(str, "[,;]") .Where(s => !string.IsNullOrEmpty(s)) .ToArray(); } diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index cf99ec3..e329b02 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -39,12 +39,14 @@ public void AddCommands(Commands cmd) for (int i = 0; i < aliases.Length; i++) { string alias = aliases[i]; + // System.Console.WriteLine($"Pre Command: {alias}."); plugin.AddCommand(alias, cmd.Description, [CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)] (player, info) => { if (player == null) return; + System.Console.WriteLine($"Post Command: {alias}."); if (info.ArgCount < alias.Split(' ').Length) { From 12258fb8a1be04baa13841d2de6db7c6c004cf00 Mon Sep 17 00:00:00 2001 From: Nils Schucka Date: Tue, 4 Jun 2024 10:07:02 +0200 Subject: [PATCH 15/24] adding unicode support --- CustomCommands/Services/LoadJson.cs | 7 ++++++- CustomCommands/Services/RegisterCommands.cs | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CustomCommands/Services/LoadJson.cs b/CustomCommands/Services/LoadJson.cs index b47b674..6d83a0e 100644 --- a/CustomCommands/Services/LoadJson.cs +++ b/CustomCommands/Services/LoadJson.cs @@ -1,3 +1,4 @@ +using System.Text; using System.Text.Json; using CustomCommands.Interfaces; using CustomCommands.Model; @@ -48,7 +49,11 @@ public List GetCommandsFromJsonFiles(string path) foreach (var file in files) { - var json = File.ReadAllText(file); + string json; + + // Read Unicode Characters + using (StreamReader sr = new StreamReader(file, Encoding.UTF8)) + json = sr.ReadToEnd(); // Validate the JSON file if (!IsValidJsonSyntax(file)) diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index 0edec86..13b6222 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -44,6 +44,7 @@ public void AddCommands(Commands cmd) { if (player == null) return; + if (info.ArgCount < aliases[i].Split(' ').Length) { player.PrintToChat($"This command requires at least {aliases[i].Split(' ').Length-1} arguments."); From d077c68e4fa1835da3b1ecbaddfb73a87286163d Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Fri, 28 Jun 2024 17:59:44 +0200 Subject: [PATCH 16/24] change version to v2.2.0 --- CustomCommands/CustomCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index 59bd1f2..443f147 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -9,7 +9,7 @@ namespace CustomCommands; public partial class CustomCommands : BasePlugin, IPluginConfig { public override string ModuleName => "CustomCommands"; - public override string ModuleVersion => "2.1.0"; + public override string ModuleVersion => "2.2.0"; public override string ModuleAuthor => "HerrMagic"; public override string ModuleDescription => "Create your own commands per config"; From 139e34a8121f4a257075171b11c0a5bf89260f71 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sat, 5 Oct 2024 23:40:33 +0200 Subject: [PATCH 17/24] set some vars to var. added clone function to object --- CustomCommands/CustomCommands.cs | 5 ++-- CustomCommands/Model/CommandsConfig.cs | 33 ++++++++++++++++++++-- CustomCommands/Services/CooldownManager.cs | 12 ++++---- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index 443f147..bbbea9b 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -61,9 +61,10 @@ public override void Load(bool hotReload) { PluginGlobals.CustomCommands = comms; - comms = RegisterCommands.CheckForDuplicateCommands(comms); + PluginGlobals.CustomCommands = RegisterCommands.CheckForDuplicateCommands(comms); + // Add commands from the JSON file to the server - foreach (var cmd in comms) + foreach (var cmd in PluginGlobals.CustomCommands) RegisterCommands.AddCommands(cmd); } } diff --git a/CustomCommands/Model/CommandsConfig.cs b/CustomCommands/Model/CommandsConfig.cs index 3582430..eebbdb1 100644 --- a/CustomCommands/Model/CommandsConfig.cs +++ b/CustomCommands/Model/CommandsConfig.cs @@ -1,8 +1,9 @@ namespace CustomCommands.Model; -public class Commands +public class Commands : ICloneable { public Guid ID { get; set; } = Guid.NewGuid(); + public string? Argument { get; set; } public string Title { get; set; } = ""; public string Description { get; set; } = "Description"; public string Command { get; set; } = ""; @@ -13,7 +14,27 @@ public class Commands public List ServerCommands { get; set; } = new(); public List ClientCommands { get; set; } = new(); public List ClientCommandsFromServer { get; set; } = new(); - public Permission Permission { get; set; } = new(); + public Permission? Permission { get; set; } = new(); + + public object Clone() + { + return new Commands() + { + ID = ID, + Argument = Argument, + Title = Title, + Description = Description, + Command = Command, + Cooldown = Cooldown, + Message = Message, + CenterMessage = CenterMessage, + PrintTo = PrintTo, + ServerCommands = new List(ServerCommands), + ClientCommands = new List(ClientCommands), + ClientCommandsFromServer = new List(ClientCommandsFromServer), + Permission = Permission?.Clone() as Permission + }; + } } public class Cooldown { @@ -21,10 +42,16 @@ public class Cooldown public bool IsGlobal { get; set; } = false; public string CooldownMessage { get; set; } = ""; } -public class Permission +public class Permission : ICloneable { public bool RequiresAllPermissions { get; set; } = false; public List PermissionList { get; set; } = new(); + + public object Clone() + { + return MemberwiseClone(); + } + } public class CenterElement { diff --git a/CustomCommands/Services/CooldownManager.cs b/CustomCommands/Services/CooldownManager.cs index e08e7bb..ab4c7af 100644 --- a/CustomCommands/Services/CooldownManager.cs +++ b/CustomCommands/Services/CooldownManager.cs @@ -42,19 +42,19 @@ public bool IsCommandOnCooldown(CCSPlayerController player, Commands cmd) /// True if the command is on cooldown, false otherwise. public bool IsCommandOnCooldownWithCondition(Func predicate, CCSPlayerController player, Commands cmd) { - int index = PluginGlobals.CooldownTimer.FindIndex(x => predicate(x) && x.CooldownTime > DateTime.Now); + var index = PluginGlobals.CooldownTimer.FindIndex(x => predicate(x) && x.CooldownTime > DateTime.Now); if (index != -1) { - double totalSeconds = PluginGlobals.CooldownTimer[index].CooldownTime.Subtract(DateTime.Now).TotalSeconds; - int totalSecondsRounded = (int)Math.Round(totalSeconds); - string timeleft = totalSecondsRounded.ToString(); - string message = ""; + var totalSeconds = (double)PluginGlobals.CooldownTimer[index].CooldownTime.Subtract(DateTime.Now).TotalSeconds; + var totalSecondsRounded = (int)Math.Round(totalSeconds); + var timeleft = totalSecondsRounded.ToString(); + var message = ""; // This is ugly as fuck try { - Cooldown cooldown = JsonSerializer.Deserialize(cmd.Cooldown.GetRawText()); + var cooldown = JsonSerializer.Deserialize(cmd.Cooldown.GetRawText()); Console.WriteLine(cooldown.CooldownMessage); string[] replaceTimeleft = {cooldown.CooldownMessage.Replace("{TIMELEFT}", timeleft)}; message = ReplaceTagsFunctions.ReplaceTags(replaceTimeleft, player)[0]; From 9f02b60953677e19f51856a09beefb79324d52b1 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 6 Oct 2024 00:58:44 +0200 Subject: [PATCH 18/24] fixing argument problems --- CustomCommands/CustomCommands.cs | 4 +- CustomCommands/Interfaces/IPluginUtilities.cs | 7 - .../Interfaces/IRegisterCommands.cs | 13 +- CustomCommands/Model/CommandsConfig.cs | 4 +- CustomCommands/Services/PluginUtilities.cs | 49 +----- CustomCommands/Services/RegisterCommands.cs | 153 +++++++++++------- 6 files changed, 110 insertions(+), 120 deletions(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index bbbea9b..eaf15a9 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -2,6 +2,7 @@ using CounterStrikeSharp.API.Core.Attributes; using CustomCommands.Interfaces; using Microsoft.Extensions.Logging; +using System.Text.Json; namespace CustomCommands; @@ -61,7 +62,8 @@ public override void Load(bool hotReload) { PluginGlobals.CustomCommands = comms; - PluginGlobals.CustomCommands = RegisterCommands.CheckForDuplicateCommands(comms); + RegisterCommands.CheckForDuplicateCommands(); + RegisterCommands.ConvertingCommandsForRegister(); // Add commands from the JSON file to the server foreach (var cmd in PluginGlobals.CustomCommands) diff --git a/CustomCommands/Interfaces/IPluginUtilities.cs b/CustomCommands/Interfaces/IPluginUtilities.cs index 97f1c09..7d4c378 100644 --- a/CustomCommands/Interfaces/IPluginUtilities.cs +++ b/CustomCommands/Interfaces/IPluginUtilities.cs @@ -5,13 +5,6 @@ namespace CustomCommands.Interfaces; public interface IPluginUtilities { - /// - /// Splits the commands string into an array of strings. - /// - /// - /// - string[] GettingCommandsFromString(string commands); - /// /// Adds the css_ prefix to each alias. /// This will help cs# tell this command belongs to the framework. diff --git a/CustomCommands/Interfaces/IRegisterCommands.cs b/CustomCommands/Interfaces/IRegisterCommands.cs index fb81515..f698073 100644 --- a/CustomCommands/Interfaces/IRegisterCommands.cs +++ b/CustomCommands/Interfaces/IRegisterCommands.cs @@ -13,7 +13,14 @@ public interface IRegisterCommands /// /// Checks for duplicate commands in the provided list and removes them. /// - /// The list of commands to check for duplicates. - /// A new list of commands without any duplicates. - List CheckForDuplicateCommands(List comms); + void CheckForDuplicateCommands(); + + /// + /// Converts custom commands stored in the global plugin state by processing each command string, + /// splitting it by commas or semicolons, and adjusting the command structure. + /// + /// The method clones each command, assigns a new unique ID, and processes its arguments. + /// Each split command is then added back to the global list with updated formatting. + /// + void ConvertingCommandsForRegister(); } diff --git a/CustomCommands/Model/CommandsConfig.cs b/CustomCommands/Model/CommandsConfig.cs index eebbdb1..fbf6f8f 100644 --- a/CustomCommands/Model/CommandsConfig.cs +++ b/CustomCommands/Model/CommandsConfig.cs @@ -15,6 +15,7 @@ public class Commands : ICloneable public List ClientCommands { get; set; } = new(); public List ClientCommandsFromServer { get; set; } = new(); public Permission? Permission { get; set; } = new(); + public bool IsRegisterable { get; set; } = true; public object Clone() { @@ -32,7 +33,8 @@ public object Clone() ServerCommands = new List(ServerCommands), ClientCommands = new List(ClientCommands), ClientCommandsFromServer = new List(ClientCommandsFromServer), - Permission = Permission?.Clone() as Permission + Permission = Permission?.Clone() as Permission, + IsRegisterable = IsRegisterable }; } } diff --git a/CustomCommands/Services/PluginUtilities.cs b/CustomCommands/Services/PluginUtilities.cs index 6c8fd21..37f78b8 100644 --- a/CustomCommands/Services/PluginUtilities.cs +++ b/CustomCommands/Services/PluginUtilities.cs @@ -22,54 +22,7 @@ public PluginUtilities(IPluginGlobals PluginGlobals, IReplaceTagsFunctions Repla this.ReplaceTagsFunctions = ReplaceTagsFunctions; this.Logger = Logger; } - - public string[] GettingCommandsFromString(string commands) - { - string[] splitCommands = SplitStringByCommaOrSemicolon(commands); - List commandsList = new List(); - // Removes arguments from the command when spaces are present - for (int i = 0; i < splitCommands.Length; i++) - { - if (splitCommands[i].Contains(' ')) - { - Logger.LogInformation($"Contains space!"); - if (splitCommands[i].IndexOf(' ') == 0) - { - commandsList.Add(splitCommands[i]); - continue; - } - Logger.LogInformation($"Is multiple args"); - string sub = splitCommands[i].Substring(0, splitCommands[i].IndexOf(' ')); - Logger.LogInformation($"Sub: {sub}"); - if (commandsList.Contains(sub)) - { - Logger.LogInformation("In IF"); - continue; - } - - if (!contains) - commandsList.Add(sub); - } - else - { - if (!commandsList.Contains(splitCommands[i])) - commandsList.Add(splitCommands[i]); - } - } - - - foreach (var command in commandsList) - { - Logger.LogInformation($"Command: {command}"); - } - - if (PluginGlobals.Config.RegisterCommandsAsCSSFramework) - return AddCSSTagsToAliases(commandsList); - - - return commandsList.ToArray(); - } - + public string[] AddCSSTagsToAliases(List input) { for (int i = 0; i < input.Count; i++) diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index e329b02..18db3dc 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -26,83 +26,79 @@ public RegisterCommands(ILogger Logger, IMessageManager MessageM this.CooldownManager = CooldownManager; } - /// - /// Adds custom commands to the plugin. - /// - /// The command to add. public void AddCommands(Commands cmd) { - CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - - string[] aliases = PluginUtilities.GettingCommandsFromString(cmd.Command); + if (!cmd.IsRegisterable) + return; + + var pluginContext = (PluginContext.Plugin as CustomCommands)!; - for (int i = 0; i < aliases.Length; i++) + pluginContext.AddCommand(cmd.Command, cmd.Description, + [CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)] + (player, info) => { - string alias = aliases[i]; - // System.Console.WriteLine($"Pre Command: {alias}."); - plugin.AddCommand(alias, cmd.Description, - [CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)] - (player, info) => - { - if (player == null) - return; - System.Console.WriteLine($"Post Command: {alias}."); + if (player == null) + return; - if (info.ArgCount < alias.Split(' ').Length) + var command = cmd; + + // Check if the command has arguments and if it does, check if the command exists and is the right one + if (info.ArgCount > 1) + { + var findcommand = PluginGlobals.CustomCommands.Find(x => x.Command == command.Command && x.Argument == info.ArgString); + // Check if the command is the right one with the right arguments + if (findcommand is null) { - player.PrintToChat($"This command requires at least {alias.Split(' ').Length-1} arguments."); + player.PrintToChat("This command requires no Arguments or you added to many"); return; } - - var command = cmd; - - // Check if the command has arguments and if it does, check if the command really exists in the list - if (info.ArgCount > 1) + + if (!findcommand.Argument!.Equals(info.ArgString)) { - var findcommand = PluginGlobals.CustomCommands.Find(x => x.Command.Contains(alias + $" {info.ArgString}")); - // Check if the command is equal to the found command - if (findcommand! != command) - return; - - command = findcommand; + player.PrintToChat("Wrong Arguments"); + return; } - // Check if the player has the permission to use the command - if (command!.Permission.PermissionList.Count > 0 && command.Permission != null) - if (!PluginUtilities.RequiresPermissions(player, command.Permission)) - return; + command = findcommand; + } + + // This will exit the command if the command has arguments but the client didn't provide any + if (info.ArgCount <= 1 && !string.IsNullOrEmpty(command.Argument!)) + { + player.PrintToChat("This command requires Arguments"); + return; + } - // Check if the command is on cooldown - if(CooldownManager.IsCommandOnCooldown(player, command)) return; + // Check if the player has the permission to use the command + if (command!.Permission?.PermissionList.Count > 0 && command.Permission != null) + if (!PluginUtilities.RequiresPermissions(player, command.Permission)) + return; + + // Check if the command is on cooldown + if(CooldownManager.IsCommandOnCooldown(player, command)) return; - // Set the cooldown for the command if it has a cooldown set - CooldownManager.SetCooldown(player, command); + // Set the cooldown for the command if it has a cooldown set + CooldownManager.SetCooldown(player, command); - // Sending the message to the player - MessageManager.SendMessage(player, command); + // Sending the message to the player + MessageManager.SendMessage(player, command); - // Execute the server commands - PluginUtilities.ExecuteServerCommands(command, player); + // Execute the server commands + PluginUtilities.ExecuteServerCommands(command, player); - // Execute the client commands - PluginUtilities.ExecuteClientCommands(command, player); + // Execute the client commands + PluginUtilities.ExecuteClientCommands(command, player); - // Execute the client commands from the server - PluginUtilities.ExecuteClientCommandsFromServer(command, player); - }); - } + // Execute the client commands from the server + PluginUtilities.ExecuteClientCommandsFromServer(command, player); + }); } - /// - /// Checks for duplicate commands in the provided list and removes them. - /// - /// The list of commands to check for duplicates. - /// A new list of commands without any duplicates. - public List CheckForDuplicateCommands(List comms) + public void CheckForDuplicateCommands() { - List duplicateCommands = new(); - List commands = new(); - List commandNames = new(); + var comms = PluginGlobals.CustomCommands; + var duplicateCommands = new List(); + var commandNames = new List(); foreach (var cmd in comms) { @@ -120,7 +116,7 @@ public List CheckForDuplicateCommands(List comms) } if (duplicateCommands.Count == 0) - return comms; + return; // Log the duplicate commands Logger.LogError($"------------------------------------------------------------------------"); @@ -136,10 +132,47 @@ public List CheckForDuplicateCommands(List comms) continue; } - commands.Add(comms[i]); + comms.Add(comms[i]); } Logger.LogError($"------------------------------------------------------------------------"); + } + + public void ConvertingCommandsForRegister() + { + var newCmds = new List(); + + foreach (var cmd in PluginGlobals.CustomCommands) + { + var splitCommands = PluginUtilities.SplitStringByCommaOrSemicolon(cmd.Command); + splitCommands = PluginUtilities.AddCSSTagsToAliases(splitCommands.ToList()); + + foreach (var split in splitCommands) + { + var args = split.Split(' '); + + if(args.Length == 1) + { + var newCmd = cmd.Clone() as Commands; + newCmd!.ID = Guid.NewGuid(); + newCmd.Command = split.Trim(); + newCmds.Add(newCmd); + } + else if (args.Length > 1) + { + var newCmd = cmd.Clone() as Commands; + + if (newCmds.Any(p => p.Command.Contains(args[0]))) + newCmd!.IsRegisterable = false; + + newCmd!.ID = Guid.NewGuid(); + newCmd.Command = args[0].Trim(); + args[0] = ""; + newCmd.Argument = string.Join(" ", args).Trim(); + newCmds.Add(newCmd); + } + } + } - return commands; + PluginGlobals.CustomCommands = newCmds; } } \ No newline at end of file From 78bed95356b41c9654ddaa474fd635e8ae29f74b Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 6 Oct 2024 02:57:32 +0200 Subject: [PATCH 19/24] fixing args not working --- CustomCommands/CustomCommands.cs | 35 +++++----- CustomCommands/Services/RegisterCommands.cs | 74 ++++++++++----------- 2 files changed, 54 insertions(+), 55 deletions(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index eaf15a9..5ca8235 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -2,7 +2,6 @@ using CounterStrikeSharp.API.Core.Attributes; using CustomCommands.Interfaces; using Microsoft.Extensions.Logging; -using System.Text.Json; namespace CustomCommands; @@ -10,24 +9,24 @@ namespace CustomCommands; public partial class CustomCommands : BasePlugin, IPluginConfig { public override string ModuleName => "CustomCommands"; - public override string ModuleVersion => "2.2.0"; + public override string ModuleVersion => "2.3.0"; public override string ModuleAuthor => "HerrMagic"; public override string ModuleDescription => "Create your own commands per config"; public CustomCommandsConfig Config { get; set; } = new(); - private readonly IRegisterCommands RegisterCommands; - private readonly IPluginGlobals PluginGlobals; - private readonly ILoadJson LoadJson; - private readonly IEventManager EventManager; + private readonly IRegisterCommands _registerCommands; + private readonly IPluginGlobals _pluginGlobals; + private readonly ILoadJson _loadJson; + private readonly IEventManager _eventManager; public CustomCommands(IRegisterCommands RegisterCommands, ILogger Logger, IPluginGlobals PluginGlobals, ILoadJson LoadJson, IEventManager EventManager) { this.Logger = Logger; - this.RegisterCommands = RegisterCommands; - this.PluginGlobals = PluginGlobals; - this.LoadJson = LoadJson; - this.EventManager = EventManager; + _registerCommands = RegisterCommands; + _pluginGlobals = PluginGlobals; + _loadJson = LoadJson; + _eventManager = EventManager; } public void OnConfigParsed(CustomCommandsConfig config) @@ -46,9 +45,9 @@ public override void Load(bool hotReload) Logger.LogInformation( $"{ModuleName} loaded!"); - PluginGlobals.Config = Config; + _pluginGlobals.Config = Config; - var comms = LoadJson.GetCommandsFromJsonFiles(ModuleDirectory); + var comms = Task.Run(async () => await _loadJson.GetCommandsFromJsonFiles(ModuleDirectory)).Result; if (comms == null) { @@ -56,18 +55,18 @@ public override void Load(bool hotReload) return; } - EventManager.RegisterListeners(); + _eventManager.RegisterListeners(); if (comms != null) { - PluginGlobals.CustomCommands = comms; + _pluginGlobals.CustomCommands = comms; - RegisterCommands.CheckForDuplicateCommands(); - RegisterCommands.ConvertingCommandsForRegister(); + _registerCommands.CheckForDuplicateCommands(); + _registerCommands.ConvertingCommandsForRegister(); // Add commands from the JSON file to the server - foreach (var cmd in PluginGlobals.CustomCommands) - RegisterCommands.AddCommands(cmd); + foreach (var cmd in _pluginGlobals.CustomCommands) + _registerCommands.AddCommands(cmd); } } } \ No newline at end of file diff --git a/CustomCommands/Services/RegisterCommands.cs b/CustomCommands/Services/RegisterCommands.cs index 18db3dc..7d0f1dc 100644 --- a/CustomCommands/Services/RegisterCommands.cs +++ b/CustomCommands/Services/RegisterCommands.cs @@ -7,23 +7,23 @@ namespace CustomCommands.Services; public class RegisterCommands : IRegisterCommands { - private readonly ILogger Logger; - private readonly IMessageManager MessageManager; - private readonly IPluginGlobals PluginGlobals; - private readonly PluginContext PluginContext; - private readonly IPluginUtilities PluginUtilities; - private readonly ICooldownManager CooldownManager; + private readonly ILogger _logger; + private readonly IMessageManager _messageManager; + private readonly IPluginGlobals _pluginGlobals; + private readonly PluginContext _pluginContext; + private readonly IPluginUtilities _pluginUtilities; + private readonly ICooldownManager _cooldownManager; public RegisterCommands(ILogger Logger, IMessageManager MessageManager, IPluginGlobals PluginGlobals, IPluginContext PluginContext, IPluginUtilities PluginUtilities, ICooldownManager CooldownManager) { - this.Logger = Logger; - this.MessageManager = MessageManager; - this.PluginGlobals = PluginGlobals; - this.PluginContext = (PluginContext as PluginContext)!; - this.PluginUtilities = PluginUtilities; - this.CooldownManager = CooldownManager; + _logger = Logger; + _messageManager = MessageManager; + _pluginGlobals = PluginGlobals; + _pluginContext = (PluginContext as PluginContext)!; + _pluginUtilities = PluginUtilities; + _cooldownManager = CooldownManager; } public void AddCommands(Commands cmd) @@ -31,9 +31,9 @@ public void AddCommands(Commands cmd) if (!cmd.IsRegisterable) return; - var pluginContext = (PluginContext.Plugin as CustomCommands)!; - - pluginContext.AddCommand(cmd.Command, cmd.Description, + var context = (_pluginContext.Plugin as CustomCommands)!; + + context.AddCommand(cmd.Command, cmd.Description, [CommandHelper(whoCanExecute: CommandUsage.CLIENT_ONLY)] (player, info) => { @@ -45,7 +45,7 @@ public void AddCommands(Commands cmd) // Check if the command has arguments and if it does, check if the command exists and is the right one if (info.ArgCount > 1) { - var findcommand = PluginGlobals.CustomCommands.Find(x => x.Command == command.Command && x.Argument == info.ArgString); + var findcommand = _pluginGlobals.CustomCommands.Find(x => x.Command == command.Command && x.Argument == info.ArgString); // Check if the command is the right one with the right arguments if (findcommand is null) { @@ -71,32 +71,32 @@ public void AddCommands(Commands cmd) // Check if the player has the permission to use the command if (command!.Permission?.PermissionList.Count > 0 && command.Permission != null) - if (!PluginUtilities.RequiresPermissions(player, command.Permission)) + if (!_pluginUtilities.RequiresPermissions(player, command.Permission)) return; // Check if the command is on cooldown - if(CooldownManager.IsCommandOnCooldown(player, command)) return; + if(_cooldownManager.IsCommandOnCooldown(player, command)) return; // Set the cooldown for the command if it has a cooldown set - CooldownManager.SetCooldown(player, command); + _cooldownManager.SetCooldown(player, command); // Sending the message to the player - MessageManager.SendMessage(player, command); - - // Execute the server commands - PluginUtilities.ExecuteServerCommands(command, player); + _messageManager.SendMessage(player, command); // Execute the client commands - PluginUtilities.ExecuteClientCommands(command, player); + _pluginUtilities.ExecuteClientCommands(command, player); // Execute the client commands from the server - PluginUtilities.ExecuteClientCommandsFromServer(command, player); + _pluginUtilities.ExecuteClientCommandsFromServer(command, player); + + // Execute the server commands + _pluginUtilities.ExecuteServerCommands(command, player); }); } public void CheckForDuplicateCommands() { - var comms = PluginGlobals.CustomCommands; + var comms = _pluginGlobals.CustomCommands; var duplicateCommands = new List(); var commandNames = new List(); @@ -119,32 +119,32 @@ public void CheckForDuplicateCommands() return; // Log the duplicate commands - Logger.LogError($"------------------------------------------------------------------------"); - Logger.LogError($"{PluginGlobals.Config.LogPrefix} Duplicate commands found, removing them from the list. Please check your config file for duplicate commands and remove them."); + _logger.LogError($"------------------------------------------------------------------------"); + _logger.LogError($"{_pluginGlobals.Config.LogPrefix} Duplicate commands found, removing them from the list. Please check your config file for duplicate commands and remove them."); for (int i = 0; i < comms.Count; i++) { if(duplicateCommands.Contains(comms[i])) { - Logger.LogError($"{PluginGlobals.Config.LogPrefix} Duplicate command found index {i+1}: "); - Logger.LogError($"{PluginGlobals.Config.LogPrefix} - {comms[i].Title} "); - Logger.LogError($"{PluginGlobals.Config.LogPrefix} - {comms[i].Description}"); - Logger.LogError($"{PluginGlobals.Config.LogPrefix} - {comms[i].Command}"); + _logger.LogError($"{_pluginGlobals.Config.LogPrefix} Duplicate command found index {i+1}: "); + _logger.LogError($"{_pluginGlobals.Config.LogPrefix} - {comms[i].Title} "); + _logger.LogError($"{_pluginGlobals.Config.LogPrefix} - {comms[i].Description}"); + _logger.LogError($"{_pluginGlobals.Config.LogPrefix} - {comms[i].Command}"); continue; } comms.Add(comms[i]); } - Logger.LogError($"------------------------------------------------------------------------"); + _logger.LogError($"------------------------------------------------------------------------"); } public void ConvertingCommandsForRegister() { var newCmds = new List(); - foreach (var cmd in PluginGlobals.CustomCommands) + foreach (var cmd in _pluginGlobals.CustomCommands) { - var splitCommands = PluginUtilities.SplitStringByCommaOrSemicolon(cmd.Command); - splitCommands = PluginUtilities.AddCSSTagsToAliases(splitCommands.ToList()); + var splitCommands = _pluginUtilities.SplitStringByCommaOrSemicolon(cmd.Command); + splitCommands = _pluginUtilities.AddCSSTagsToAliases(splitCommands.ToList()); foreach (var split in splitCommands) { @@ -173,6 +173,6 @@ public void ConvertingCommandsForRegister() } } - PluginGlobals.CustomCommands = newCmds; + _pluginGlobals.CustomCommands = newCmds; } } \ No newline at end of file From dade59ab01186967955cf13ecba01f40dc8bc562 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 6 Oct 2024 02:57:57 +0200 Subject: [PATCH 20/24] small impovements --- CustomCommands/Interfaces/ILoadJson.cs | 45 ++++++- CustomCommands/Interfaces/IMessageManager.cs | 5 + .../Interfaces/IReplaceTagsFunctions.cs | 31 +++++ CustomCommands/Services/CooldownManager.cs | 31 ++--- CustomCommands/Services/EventManager.cs | 32 ++--- CustomCommands/Services/LoadJson.cs | 122 +++++++----------- CustomCommands/Services/MessageManager.cs | 41 +++--- CustomCommands/Services/PluginUtilities.cs | 45 ++++--- 8 files changed, 203 insertions(+), 149 deletions(-) diff --git a/CustomCommands/Interfaces/ILoadJson.cs b/CustomCommands/Interfaces/ILoadJson.cs index e564de8..5d865fc 100644 --- a/CustomCommands/Interfaces/ILoadJson.cs +++ b/CustomCommands/Interfaces/ILoadJson.cs @@ -4,11 +4,52 @@ namespace CustomCommands.Interfaces; public interface ILoadJson { - List GetCommandsFromJsonFiles(string path); + /// + /// Retrieves a list of commands from JSON files located in the specified path. + /// + /// The path where the JSON files are located. + /// A list of commands. + Task> GetCommandsFromJsonFiles(string path); + + /// + /// Checks if an .example file exists in the specified path and creates a default config file if it doesn't exist. + /// + /// The path to check for the example file. void CheckForExampleFile(string path); - bool IsValidJsonSyntax(string jsonString); + + /// + /// Checks if the JSON file has a valid syntax. + /// + /// The path to the JSON file. + /// The json string. + /// True if the JSON syntax is valid, false otherwise. + bool IsValidJsonSyntax(string json, string path); + + /// + /// Validates the list of commands loaded from a JSON file. + /// + /// The list of commands to validate. + /// The path of the JSON file. + /// True if all commands are valid, false otherwise. bool ValidateObject(List? comms, string path); + + /// + /// Logs the details of a command. + /// + /// The command to log. void LogCommandDetails(Commands comms); + + /// + /// Validates the PrintTo property of the Commands object and checks if the required message properties are set based on the PrintTo value. + /// + /// The Commands object to validate. + /// True if the PrintTo property is valid and the required message properties are set; otherwise, false. bool PrintToCheck(Commands comms); + + /// + /// Validates a dynamic message by checking if it is a string or an array. + /// + /// The dynamic message to validate. + /// True if the message is a string or an array, otherwise false. bool ValidateMessage(dynamic message); } \ No newline at end of file diff --git a/CustomCommands/Interfaces/IMessageManager.cs b/CustomCommands/Interfaces/IMessageManager.cs index c2be909..edf7fbf 100644 --- a/CustomCommands/Interfaces/IMessageManager.cs +++ b/CustomCommands/Interfaces/IMessageManager.cs @@ -5,6 +5,11 @@ namespace CustomCommands.Interfaces; public interface IMessageManager { + /// + /// Sends a message based on the specified command and target receiver. + /// + /// The player who triggered the command. + /// The command containing the message and target receiver. void SendMessage(CCSPlayerController player, Commands cmd); void PrintToCenterClient(CCSPlayerController player, Commands cmd); void PrintToAllCenter(Commands cmd); diff --git a/CustomCommands/Interfaces/IReplaceTagsFunctions.cs b/CustomCommands/Interfaces/IReplaceTagsFunctions.cs index 0a0e59a..0d6f85b 100644 --- a/CustomCommands/Interfaces/IReplaceTagsFunctions.cs +++ b/CustomCommands/Interfaces/IReplaceTagsFunctions.cs @@ -4,9 +4,40 @@ namespace CustomCommands.Interfaces; public interface IReplaceTagsFunctions { + /// + /// Replaces tags in the input array with their corresponding values. + /// + /// The array of strings containing tags to be replaced. + /// The CCSPlayerController object used for tag replacement. + /// The array of strings with tags replaced. string[] ReplaceTags(dynamic input, CCSPlayerController player); + + /// + /// Replaces language tags in the input string with the corresponding localized value. + /// Language tags are defined within curly braces, e.g. "{LANG=LocalizerTag}". + /// If a language tag is found, it is replaced with the localized value from the CustomCommands plugin's Localizer. + /// If the localized value is not found, a default message is returned. + /// + /// The input string to process. + /// The input string with language tags replaced with localized values. string ReplaceLanguageTags(string input); + + /// + /// Replaces tags in the input string with corresponding values based on the provided player information. + /// + /// The input string containing tags to be replaced. + /// The CCSPlayerController object representing the player. + /// A boolean value indicating whether to replace the {PLAYERNAME} tag. Default is true. + /// The modified string with replaced tags. string ReplaceMessageTags(string input, CCSPlayerController player, bool safety = true); string ReplaceColorTags(string input); + + /// + /// 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. + /// + /// This should be a string[] or a string + /// An array of strings representing the lines of the input. List WrappedLine(dynamic message); + + string ReplaceRandomTags(string message); } \ No newline at end of file diff --git a/CustomCommands/Services/CooldownManager.cs b/CustomCommands/Services/CooldownManager.cs index ab4c7af..36d1434 100644 --- a/CustomCommands/Services/CooldownManager.cs +++ b/CustomCommands/Services/CooldownManager.cs @@ -6,12 +6,13 @@ namespace CustomCommands.Interfaces; public class CooldownManager : ICooldownManager { - public IPluginGlobals PluginGlobals { get; } - public IReplaceTagsFunctions ReplaceTagsFunctions { get; } + public IPluginGlobals _pluginGlobals { get; } + public IReplaceTagsFunctions _replaceTagsFunctions { get; } + public CooldownManager(IPluginGlobals PluginGlobals, IReplaceTagsFunctions ReplaceTagsFunctions) { - this.PluginGlobals = PluginGlobals; - this.ReplaceTagsFunctions = ReplaceTagsFunctions; + _pluginGlobals = PluginGlobals; + _replaceTagsFunctions = ReplaceTagsFunctions; } /// @@ -42,11 +43,11 @@ public bool IsCommandOnCooldown(CCSPlayerController player, Commands cmd) /// True if the command is on cooldown, false otherwise. public bool IsCommandOnCooldownWithCondition(Func predicate, CCSPlayerController player, Commands cmd) { - var index = PluginGlobals.CooldownTimer.FindIndex(x => predicate(x) && x.CooldownTime > DateTime.Now); + var index = _pluginGlobals.CooldownTimer.FindIndex(x => predicate(x) && x.CooldownTime > DateTime.Now); if (index != -1) { - var totalSeconds = (double)PluginGlobals.CooldownTimer[index].CooldownTime.Subtract(DateTime.Now).TotalSeconds; + var totalSeconds = (double)_pluginGlobals.CooldownTimer[index].CooldownTime.Subtract(DateTime.Now).TotalSeconds; var totalSecondsRounded = (int)Math.Round(totalSeconds); var timeleft = totalSecondsRounded.ToString(); var message = ""; @@ -57,14 +58,14 @@ public bool IsCommandOnCooldownWithCondition(Func predicate var cooldown = JsonSerializer.Deserialize(cmd.Cooldown.GetRawText()); Console.WriteLine(cooldown.CooldownMessage); string[] replaceTimeleft = {cooldown.CooldownMessage.Replace("{TIMELEFT}", timeleft)}; - message = ReplaceTagsFunctions.ReplaceTags(replaceTimeleft, player)[0]; + message = _replaceTagsFunctions.ReplaceTags(replaceTimeleft, player)[0]; } catch (JsonException) { message = $"This command is for {timeleft} seconds on cooldown"; } - player.PrintToChat($"{PluginGlobals.Config.Prefix}{message}"); + player.PrintToChat($"{_pluginGlobals.Config.Prefix}{message}"); return true; } @@ -89,25 +90,25 @@ public void AddToCooldownList(bool isGlobal, int playerID, Guid commandID, int c if (isGlobal) { - int index = PluginGlobals.CooldownTimer.FindIndex(x => + int index = _pluginGlobals.CooldownTimer.FindIndex(x => x.IsGlobal == true && x.CommandID == commandID); if (index != -1) - PluginGlobals.CooldownTimer[index].CooldownTime = timer.CooldownTime; + _pluginGlobals.CooldownTimer[index].CooldownTime = timer.CooldownTime; else - PluginGlobals.CooldownTimer.Add(timer); + _pluginGlobals.CooldownTimer.Add(timer); } else { timer.PlayerID = playerID; - int index = PluginGlobals.CooldownTimer.FindIndex(x => + int index = _pluginGlobals.CooldownTimer.FindIndex(x => x.PlayerID == playerID && x.CommandID == commandID); if (index != -1) - PluginGlobals.CooldownTimer[index].CooldownTime = timer.CooldownTime; + _pluginGlobals.CooldownTimer[index].CooldownTime = timer.CooldownTime; else - PluginGlobals.CooldownTimer.Add(timer); + _pluginGlobals.CooldownTimer.Add(timer); } } @@ -124,7 +125,7 @@ public void SetCooldown(CCSPlayerController player, Commands cmd) { case JsonValueKind.Number: - int cooldown = cmd.Cooldown.GetInt32(); + var cooldown = cmd.Cooldown.GetInt32(); if (cooldown == 0) break; diff --git a/CustomCommands/Services/EventManager.cs b/CustomCommands/Services/EventManager.cs index 7c47cce..441af7a 100644 --- a/CustomCommands/Services/EventManager.cs +++ b/CustomCommands/Services/EventManager.cs @@ -8,37 +8,37 @@ namespace CustomCommands.Services; public class EventManager : IEventManager { - private readonly IPluginGlobals PluginGlobals; - private readonly PluginContext PluginContext; - private readonly IReplaceTagsFunctions ReplaceTagsFunctions; + private readonly IPluginGlobals _pluginGlobals; + private readonly PluginContext _pluginContext; + private readonly IReplaceTagsFunctions _replaceTagsFunctions; public EventManager(IPluginGlobals PluginGlobals, IPluginContext PluginContext, IReplaceTagsFunctions ReplaceTagsFunctions) { - this.PluginGlobals = PluginGlobals; - this.PluginContext = (PluginContext as PluginContext)!; - this.ReplaceTagsFunctions = ReplaceTagsFunctions; + _pluginGlobals = PluginGlobals; + _pluginContext = (PluginContext as PluginContext)!; + _replaceTagsFunctions = ReplaceTagsFunctions; } [GameEventHandler] public HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo _) { - PluginGlobals.centerClientOn.RemoveAll(p => p.ClientId == @event.Userid.UserId); - PluginGlobals.CooldownTimer.RemoveAll(p => p.PlayerID == @event.Userid.UserId); + _pluginGlobals.centerClientOn.RemoveAll(p => p.ClientId == @event.Userid.UserId); + _pluginGlobals.CooldownTimer.RemoveAll(p => p.PlayerID == @event.Userid.UserId); return HookResult.Continue; } public void RegisterListeners() { - CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; + var plugin = (_pluginContext.Plugin as CustomCommands)!; // Register the OnTick event for PrintToCenterHtml duration plugin.RegisterListener(() => { // Client Print To Center - if(PluginGlobals.centerClientOn != null && PluginGlobals.centerClientOn.Count !> 0 ) + if(_pluginGlobals.centerClientOn != null && _pluginGlobals.centerClientOn.Count !> 0 ) { - foreach (var player in PluginGlobals.centerClientOn) + foreach (var player in _pluginGlobals.centerClientOn) { var targetPlayer = Utilities.GetPlayerFromUserid(player.ClientId); if (player != null && targetPlayer != null) @@ -49,14 +49,14 @@ public void RegisterListeners() } // Server Print To Center - if (PluginGlobals.centerServerOn.IsRunning) + if (_pluginGlobals.centerServerOn.IsRunning) { Utilities.GetPlayers().ForEach(controller => { if (!controller.IsValid || controller.SteamID == 0) return; - string message = ReplaceTagsFunctions.ReplaceLanguageTags(PluginGlobals.centerServerOn.Message); - message = ReplaceTagsFunctions.ReplaceMessageTags(message, controller); + var message = _replaceTagsFunctions.ReplaceLanguageTags(_pluginGlobals.centerServerOn.Message); + message = _replaceTagsFunctions.ReplaceMessageTags(message, controller); controller.PrintToCenterHtml(message, 1); }); } @@ -64,8 +64,8 @@ public void RegisterListeners() plugin.RegisterListener(() => { - PluginGlobals.centerClientOn.Clear(); - PluginGlobals.CooldownTimer.Clear(); + _pluginGlobals.centerClientOn.Clear(); + _pluginGlobals.CooldownTimer.Clear(); }); } } \ No newline at end of file diff --git a/CustomCommands/Services/LoadJson.cs b/CustomCommands/Services/LoadJson.cs index 6d83a0e..7b5a7b2 100644 --- a/CustomCommands/Services/LoadJson.cs +++ b/CustomCommands/Services/LoadJson.cs @@ -8,23 +8,18 @@ namespace CustomCommands.Services; public class LoadJson : ILoadJson { - private readonly ILogger Logger; + private readonly ILogger _logger; public LoadJson(ILogger Logger) { - this.Logger = Logger; + _logger = Logger; } - /// - /// Retrieves a list of commands from JSON files located in the specified path. - /// - /// The path where the JSON files are located. - /// A list of commands. - public List GetCommandsFromJsonFiles(string path) + public async Task> GetCommandsFromJsonFiles(string path) { var comms = new List(); - string defaultconfigpath = Path.Combine(path, "Commands.json"); + var defaultconfigpath = Path.Combine(path, "Commands.json"); CheckForExampleFile(path); @@ -39,38 +34,43 @@ public List GetCommandsFromJsonFiles(string path) if (File.Exists(defaultconfigpath)) { files.Add(defaultconfigpath); - Logger.LogInformation("Found default config file."); + _logger.LogInformation("Found default config file."); } else if (!File.Exists(defaultconfigpath) && files.Count == 0) { - Logger.LogWarning("No Config file found. Please create plugins/CustomCommands/Commands.json or in plugins/CustomCommands/Commands/.json"); + _logger.LogWarning("No Config file found. Please create plugins/CustomCommands/Commands.json or in plugins/CustomCommands/Commands/.json"); return comms; } - foreach (var file in files) + // Create a list of tasks to handle each file asynchronously + var tasks = files.Select(async file => { - string json; + var json = string.Empty; - // Read Unicode Characters - using (StreamReader sr = new StreamReader(file, Encoding.UTF8)) - json = sr.ReadToEnd(); + // Read Unicode Characters asynchronously + using (var sr = new StreamReader(file, Encoding.UTF8)) + json = await sr.ReadToEndAsync(); // Validate the JSON file - if (!IsValidJsonSyntax(file)) - continue; + if (!IsValidJsonSyntax(json, file)) + return; + // Deserialize and validate the commands var commands = JsonSerializer.Deserialize>(json); if (ValidateObject(commands, file)) - comms.AddRange(commands!); - } + { + lock (comms) // Ensure thread-safety while adding to the shared list + { + comms.AddRange(commands!); + } + } + }); + + await Task.WhenAll(tasks); + return comms; } - - /// - /// Checks if an .example file exists in the specified path and creates a default config file if it doesn't exist. - /// - /// The path to check for the example file. public void CheckForExampleFile(string path) { if (Directory.Exists(Path.Combine(path, "Commands"))) @@ -85,64 +85,52 @@ public void CheckForExampleFile(string path) if (!File.Exists(defaultconfigpath)) { File.Copy(exampleconfigpath, defaultconfigpath); - Logger.LogInformation("Created default config file."); + _logger.LogInformation("Created default config file."); } } - /// - /// Checks if the JSON file has a valid syntax. - /// - /// The path to the JSON file. - /// True if the JSON syntax is valid, false otherwise. - public bool IsValidJsonSyntax(string path) + public bool IsValidJsonSyntax(string json, string path) { try { - var json = File.ReadAllText(path); var document = JsonDocument.Parse(json); return true; } catch (JsonException ex) { - Logger.LogError($"Invalid JSON syntax in {path}. Please check the docs on how to create a valid JSON file"); - Logger.LogError(ex.Message); + _logger.LogError($"Invalid JSON syntax in {path}. Please check the docs on how to create a valid JSON file"); + _logger.LogError(ex.Message); return false; } } - /// - /// Validates the list of commands loaded from a JSON file. - /// - /// The list of commands to validate. - /// The path of the JSON file. - /// True if all commands are valid, false otherwise. public bool ValidateObject(List? comms, string path) { if (comms == null) { - Logger.LogError($"Invalid JSON format in {path}. Please check the docs on how to create a valid JSON file"); + _logger.LogError($"Invalid JSON format in {path}. Please check the docs on how to create a valid JSON file"); return false; } - bool commandstatus = true; + var commandstatus = true; for (int i = 0; i < comms.Count; i++) { commandstatus = true; // Title if (string.IsNullOrEmpty(comms[i].Title)) { - Logger.LogWarning($"Title not set in {path}. Title is not required but recommended"); + _logger.LogWarning($"Title not set in {path}. Title is not required but recommended"); commandstatus = false; } // Description if (string.IsNullOrEmpty(comms[i].Description)) { - Logger.LogWarning($"Description not set in {path}. Description is not required but recommended. This will be shown in the help command"); + _logger.LogWarning($"Description not set in {path}. Description is not required but recommended. This will be shown in the help command"); commandstatus = false; } // Command if (string.IsNullOrEmpty(comms[i].Command)) { - Logger.LogError($"Command not set in {path}"); + _logger.LogError($"Command not set in {path}"); commandstatus = false; } if (!PrintToCheck(comms[i])) @@ -150,7 +138,7 @@ public bool ValidateObject(List? comms, string path) if (!commandstatus) { - Logger.LogError($"Command {comms[i].Command} will not be loaded. Index: {i}"); + _logger.LogError($"Command {comms[i].Command} will not be loaded. Index: {i}"); LogCommandDetails(comms[i]); } } @@ -159,29 +147,20 @@ public bool ValidateObject(List? comms, string path) return true; } - /// - /// Logs the details of a command. - /// - /// The command to log. public void LogCommandDetails(Commands comms) { - Logger.LogInformation($"-- Title: {comms.Title}"); - Logger.LogInformation($"-- Description: {comms.Description}"); - Logger.LogInformation($"-- Command: {comms.Command}"); - Logger.LogInformation($"-- Message: {comms.Message}"); - Logger.LogInformation($"-- CenterMessage: {comms.CenterMessage.Message}"); - Logger.LogInformation($"-- CenterMessageTime: {comms.CenterMessage.Time}"); - Logger.LogInformation($"-- PrintTo: {comms.PrintTo}"); - Logger.LogInformation($"-- ServerCommands: {JsonSerializer.Serialize(comms.ServerCommands)}"); - Logger.LogInformation($"-- PermissionList: {JsonSerializer.Serialize(comms.Permission)}"); - Logger.LogInformation("--------------------------------------------------"); + _logger.LogInformation($"-- Title: {comms.Title}"); + _logger.LogInformation($"-- Description: {comms.Description}"); + _logger.LogInformation($"-- Command: {comms.Command}"); + _logger.LogInformation($"-- Message: {comms.Message}"); + _logger.LogInformation($"-- CenterMessage: {comms.CenterMessage.Message}"); + _logger.LogInformation($"-- CenterMessageTime: {comms.CenterMessage.Time}"); + _logger.LogInformation($"-- PrintTo: {comms.PrintTo}"); + _logger.LogInformation($"-- ServerCommands: {JsonSerializer.Serialize(comms.ServerCommands)}"); + _logger.LogInformation($"-- PermissionList: {JsonSerializer.Serialize(comms.Permission)}"); + _logger.LogInformation("--------------------------------------------------"); } - /// - /// Validates the PrintTo property of the Commands object and checks if the required message properties are set based on the PrintTo value. - /// - /// The Commands object to validate. - /// True if the PrintTo property is valid and the required message properties are set; otherwise, false. public bool PrintToCheck(Commands comms) { if (comms.PrintTo == Sender.ClientChat || comms.PrintTo == Sender.AllChat) @@ -189,7 +168,7 @@ public bool PrintToCheck(Commands comms) if (!ValidateMessage(comms.Message)) { - Logger.LogError($"Message not set but needs to be set because PrintTo is set to {comms.PrintTo}"); + _logger.LogError($"Message not set but needs to be set because PrintTo is set to {comms.PrintTo}"); return false; } } @@ -197,7 +176,7 @@ public bool PrintToCheck(Commands comms) { if (string.IsNullOrEmpty(comms.CenterMessage.Message)) { - Logger.LogError($"CenterMessage is not set but needs to be set because PrintTo is set to {comms.PrintTo}"); + _logger.LogError($"CenterMessage is not set but needs to be set because PrintTo is set to {comms.PrintTo}"); return false; } } @@ -205,18 +184,13 @@ public bool PrintToCheck(Commands comms) { if (!ValidateMessage(comms.Message) && string.IsNullOrEmpty(comms.CenterMessage.Message)) { - Logger.LogError($"Message and CenterMessage are not set but needs to be set because PrintTo is set to {comms.PrintTo}"); + _logger.LogError($"Message and CenterMessage are not set but needs to be set because PrintTo is set to {comms.PrintTo}"); return false; } } return true; } - /// - /// Validates a dynamic message by checking if it is a string or an array. - /// - /// The dynamic message to validate. - /// True if the message is a string or an array, otherwise false. public bool ValidateMessage(dynamic message) { if (message is JsonElement jsonElement) diff --git a/CustomCommands/Services/MessageManager.cs b/CustomCommands/Services/MessageManager.cs index 6a27e07..3389cd3 100644 --- a/CustomCommands/Services/MessageManager.cs +++ b/CustomCommands/Services/MessageManager.cs @@ -7,22 +7,17 @@ namespace CustomCommands.Services; public class MessageManager : IMessageManager { - private readonly IPluginGlobals PluginGlobals; - private readonly IReplaceTagsFunctions ReplaceTagsFunctions; - private readonly PluginContext PluginContext; + private readonly IPluginGlobals _pluginGlobals; + private readonly IReplaceTagsFunctions _replaceTagsFunctions; + private readonly PluginContext _pluginContext; public MessageManager(IPluginGlobals PluginGlobals, IReplaceTagsFunctions ReplaceTagsFunctions, IPluginContext PluginContext) { - this.PluginGlobals = PluginGlobals; - this.ReplaceTagsFunctions = ReplaceTagsFunctions; - this.PluginContext = (PluginContext as PluginContext)!; + _pluginGlobals = PluginGlobals; + _replaceTagsFunctions = ReplaceTagsFunctions; + _pluginContext = (PluginContext as PluginContext)!; } - /// - /// Sends a message based on the specified command and target receiver. - /// - /// The player who triggered the command. - /// The command containing the message and target receiver. public void SendMessage(CCSPlayerController player, Commands cmd) { switch (cmd.PrintTo) @@ -58,30 +53,28 @@ public void SendMessage(CCSPlayerController player, Commands cmd) public void PrintToCenterClient(CCSPlayerController player, Commands cmd) { - CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - - string message = ReplaceTagsFunctions.ReplaceLanguageTags(cmd.CenterMessage.Message); - message = ReplaceTagsFunctions.ReplaceMessageTags(message, player); + var context = (_pluginContext.Plugin as CustomCommands)!; + var message = _replaceTagsFunctions.ReplaceLanguageTags(cmd.CenterMessage.Message); + message = _replaceTagsFunctions.ReplaceMessageTags(message, player); var CenterClientElement = new CenterClientElement { ClientId = player.UserId!.Value, Message = message }; - PluginGlobals.centerClientOn.Add(CenterClientElement); - plugin.AddTimer(cmd.CenterMessage.Time, () => PluginGlobals.centerClientOn.Remove(CenterClientElement)); + _pluginGlobals.centerClientOn.Add(CenterClientElement); + context.AddTimer(cmd.CenterMessage.Time, () => _pluginGlobals.centerClientOn.Remove(CenterClientElement)); } public void PrintToAllCenter(Commands cmd) { - CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - - PluginGlobals.centerServerOn.Message = cmd.CenterMessage.Message; - PluginGlobals.centerServerOn.IsRunning = true; + var context = (_pluginContext.Plugin as CustomCommands)!; + _pluginGlobals.centerServerOn.Message = cmd.CenterMessage.Message; + _pluginGlobals.centerServerOn.IsRunning = true; - plugin.AddTimer(cmd.CenterMessage.Time, () => + context.AddTimer(cmd.CenterMessage.Time, () => { - PluginGlobals.centerServerOn.IsRunning = false; + _pluginGlobals.centerServerOn.IsRunning = false; }); } @@ -99,7 +92,7 @@ public void PrintToChatAndAllCenter(Receiver receiver, CCSPlayerController playe public void PrintToChat(Receiver printToChat, CCSPlayerController player, dynamic message) { - string[] msg = ReplaceTagsFunctions.ReplaceTags(message, player); + var msg = _replaceTagsFunctions.ReplaceTags(message, player); switch (printToChat) { diff --git a/CustomCommands/Services/PluginUtilities.cs b/CustomCommands/Services/PluginUtilities.cs index 37f78b8..f13b6c0 100644 --- a/CustomCommands/Services/PluginUtilities.cs +++ b/CustomCommands/Services/PluginUtilities.cs @@ -9,18 +9,18 @@ namespace CustomCommands.Services; -public class PluginUtilities : IPluginUtilities +public partial class PluginUtilities : IPluginUtilities { - private readonly IPluginGlobals PluginGlobals; - private readonly IReplaceTagsFunctions ReplaceTagsFunctions; - private readonly ILogger Logger; + private readonly IPluginGlobals _pluginGlobals; + private readonly IReplaceTagsFunctions _replaceTagsFunctions; + private readonly ILogger _logger; public PluginUtilities(IPluginGlobals PluginGlobals, IReplaceTagsFunctions ReplaceTagsFunctions, ILogger Logger) { - this.PluginGlobals = PluginGlobals; - this.ReplaceTagsFunctions = ReplaceTagsFunctions; - this.Logger = Logger; + _pluginGlobals = PluginGlobals; + _replaceTagsFunctions = ReplaceTagsFunctions; + _logger = Logger; } public string[] AddCSSTagsToAliases(List input) @@ -32,17 +32,21 @@ public string[] AddCSSTagsToAliases(List input) } return input.ToArray(); } + + [GeneratedRegex("[,;]")] + private static partial Regex SplitStringByCommaOrSemicolonRegex(); public string[] SplitStringByCommaOrSemicolon(string str) { - return Regex.Split(str, "[,;]") + return SplitStringByCommaOrSemicolonRegex().Split(str) .Where(s => !string.IsNullOrEmpty(s)) .ToArray(); } public void ExecuteServerCommands(Commands cmd, CCSPlayerController player) { - if (cmd.ServerCommands.Count == 0) return; + if (cmd.ServerCommands.Count == 0) + return; foreach (var serverCommand in cmd.ServerCommands) { @@ -53,37 +57,42 @@ public void ExecuteServerCommands(Commands cmd, CCSPlayerController player) continue; } - Server.ExecuteCommand(ReplaceTagsFunctions.ReplaceMessageTags(serverCommand, player)); + + Server.ExecuteCommand(_replaceTagsFunctions.ReplaceMessageTags(serverCommand, player)); } } public void ExecuteClientCommands(Commands cmd, CCSPlayerController player) { - if (cmd.ClientCommands.Count == 0) return; + if (cmd.ClientCommands.Count == 0) + return; foreach (var clientCommand in cmd.ClientCommands) { - player.ExecuteClientCommand(ReplaceTagsFunctions.ReplaceMessageTags(clientCommand, player)); + player.ExecuteClientCommand(_replaceTagsFunctions.ReplaceMessageTags(clientCommand, player)); } } public void ExecuteClientCommandsFromServer(Commands cmd, CCSPlayerController player) { - if (cmd.ClientCommandsFromServer.Count == 0) return; + if (cmd.ClientCommandsFromServer.Count == 0) + return; foreach (var clientCommandsFromServer in cmd.ClientCommandsFromServer) { - player.ExecuteClientCommandFromServer(ReplaceTagsFunctions.ReplaceMessageTags(clientCommandsFromServer, player)); + player.ExecuteClientCommandFromServer(_replaceTagsFunctions.ReplaceMessageTags(clientCommandsFromServer, player)); } } + /// /// Handles the toggle command /// /// private void HandleToggleCommand(string serverCommand) { - string commandWithoutToggle = serverCommand.Replace("toggle ", ""); + var commandWithoutToggle = serverCommand.Replace("toggle ", ""); var commandCvar = ConVar.Find(commandWithoutToggle); + if (commandCvar != null) { if (commandCvar.GetPrimitiveValue()) @@ -93,7 +102,7 @@ private void HandleToggleCommand(string serverCommand) } else { - Logger.LogError($"Couldn't toggle {commandWithoutToggle}. Please check if this command is toggleable"); + _logger.LogError($"Couldn't toggle {commandWithoutToggle}. Please check if this command is toggleable"); } } @@ -106,14 +115,14 @@ public bool RequiresPermissions(CCSPlayerController player, Permission permissio if (AdminManager.PlayerHasPermissions(player, new string[] { permission })) return true; } - player.PrintToChat($"{PluginGlobals.Config.Prefix}You don't have the required permissions to execute this command"); + player.PrintToChat($"{_pluginGlobals.Config.Prefix}You don't have the required permissions to execute this command"); return false; } else { if (!AdminManager.PlayerHasPermissions(player, permissions.PermissionList.ToArray())) { - player.PrintToChat($"{PluginGlobals.Config.Prefix}You don't have the required permissions to execute this command"); + player.PrintToChat($"{_pluginGlobals.Config.Prefix}You don't have the required permissions to execute this command"); return false; } return true; From 6ca65f5775fe487751132ae23117f1a0fc15e68d Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 6 Oct 2024 03:02:47 +0200 Subject: [PATCH 21/24] adding random tag #66 --- .../Services/ReplaceTagsFunction.cs | 141 +++++++++++------- 1 file changed, 86 insertions(+), 55 deletions(-) diff --git a/CustomCommands/Services/ReplaceTagsFunction.cs b/CustomCommands/Services/ReplaceTagsFunction.cs index 77209e3..88775ef 100644 --- a/CustomCommands/Services/ReplaceTagsFunction.cs +++ b/CustomCommands/Services/ReplaceTagsFunction.cs @@ -10,31 +10,23 @@ using CounterStrikeSharp.API.Core.Plugin; namespace CustomCommands.Services; -public class ReplaceTagsFunctions : IReplaceTagsFunctions +public partial class ReplaceTagsFunctions : IReplaceTagsFunctions { - private readonly IPluginGlobals PluginGlobals; - private readonly PluginContext PluginContext; - private readonly ILogger Logger; + private readonly IPluginGlobals _pluginGlobals; + private readonly PluginContext _pluginContext; + private readonly ILogger _logger; public ReplaceTagsFunctions(IPluginGlobals PluginGlobals, IPluginContext PluginContext, ILogger Logger) { - this.PluginGlobals = PluginGlobals; - this.PluginContext = (PluginContext as PluginContext)!; - this.Logger = Logger; + _pluginGlobals = PluginGlobals; + _pluginContext = (PluginContext as PluginContext)!; + _logger = Logger; } - - - /// - /// Replaces tags in the input array with their corresponding values. - /// - /// The array of strings containing tags to be replaced. - /// The CCSPlayerController object used for tag replacement. - /// The array of strings with tags replaced. public string[] ReplaceTags(dynamic input, CCSPlayerController player) { - List output = WrappedLine(input); + var output = WrappedLine(input); for (int i = 0; i < output.Count; i++) output[i] = ReplaceLanguageTags(output[i]); @@ -44,36 +36,29 @@ public string[] ReplaceTags(dynamic input, CCSPlayerController player) for (int i = 0; i < output.Count; i++) { output[i] = ReplaceMessageTags(output[i], player, false); + output[i] = ReplaceRandomTags(output[i]); output[i] = ReplaceColorTags(output[i]); } - return output.ToArray(); + return output.ToArray(); } - /// - /// Replaces language tags in the input string with the corresponding localized value. - /// Language tags are defined within curly braces, e.g. "{LANG=LocalizerTag}". - /// If a language tag is found, it is replaced with the localized value from the CustomCommands plugin's Localizer. - /// If the localized value is not found, a default message is returned. - /// - /// The input string to process. - /// The input string with language tags replaced with localized values. + [GeneratedRegex(@"\{LANG=(.*?)\}")] + private static partial Regex ReplaceLanguageTagsRegex(); + public string ReplaceLanguageTags(string input) { - CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!; - - // Define the regex pattern to find "{LANG=...}" - string pattern = @"\{LANG=(.*?)\}"; - // Use Regex to find matches - Match match = Regex.Match(input, pattern); + var match = ReplaceLanguageTagsRegex().Match(input); // Check if a match is found if (match.Success) { // Return the group captured in the regex, which is the string after "=" - string lang = match.Groups[1].Value; - return input.Replace(match.Value, plugin.Localizer[lang] ?? " not found>"); + var lang = match.Groups[1].Value; + var context = (_pluginContext.Plugin as CustomCommands)!; + + return input.Replace(match.Value, context.Localizer[lang] ?? " not found>"); } else { @@ -81,21 +66,72 @@ public string ReplaceLanguageTags(string input) return input; } } - + /// - /// Replaces tags in the input string with corresponding values based on the provided player information. + /// Use regex to find the RNDNO tag pattern {RNDNO={min, max}} /// - /// The input string containing tags to be replaced. - /// The CCSPlayerController object representing the player. - /// A boolean value indicating whether to replace the {PLAYERNAME} tag. Default is true. - /// The modified string with replaced tags. + /// + [GeneratedRegex(@"\{RNDNO=\((\d+(?:\.\d+)?),\s*(\d+(?:\.\d+)?)\)\}")] + private static partial Regex ReplaceRandomTagsRegex(); + + public string ReplaceRandomTags(string message) + { + // Replace all occurrences of the RNDNO tag in the message + var match = ReplaceRandomTagsRegex().Match(message); + + // Extract min and max from the regex match groups + string minStr = match.Groups[1].Value; + string maxStr = match.Groups[2].Value; + + // Determine if the min and max are integers or floats + bool isMinFloat = float.TryParse(minStr, out float minFloat); + bool isMaxFloat = float.TryParse(maxStr, out float maxFloat); + + var random = new Random(); + + if (isMinFloat || isMaxFloat) + { + // Generate a random float between min and max (inclusive) + float randomFloat = (float)(random.NextDouble() * (maxFloat - minFloat) + minFloat); + + // Determine the maximum precision from the min and max values + int maxDecimalPlaces = Math.Max(GetDecimalPlaces(minStr), GetDecimalPlaces(maxStr)); + + // Use the determined precision to format the float + message = message.Replace(match.Value, randomFloat.ToString($"F{maxDecimalPlaces}")); + } + else + { + // Parse as integers + int min = int.Parse(minStr); + int max = int.Parse(maxStr); + + // Generate a random integer between min and max (inclusive) + int randomValue = random.Next(min, max + 1); // max is exclusive, so add 1 + message = message.Replace(match.Value, randomValue.ToString()); + } + + return message; + } + + // Method to get the number of decimal places in a number string + private static int GetDecimalPlaces(string numberStr) + { + int decimalIndex = numberStr.IndexOf('.'); + if (decimalIndex == -1) + { + return 0; // No decimal point, return 0 + } + return numberStr.Length - decimalIndex - 1; // Count digits after the decimal point + } + public string ReplaceMessageTags(string input, CCSPlayerController player, bool safety = true) { - SteamID steamId = new SteamID(player.SteamID); + var steamId = new SteamID(player.SteamID); Dictionary replacements = new() { - {"{PREFIX}", PluginGlobals.Config.Prefix ?? ""}, + {"{PREFIX}", _pluginGlobals.Config.Prefix ?? ""}, {"{MAP}", NativeAPI.GetMapName() ?? ""}, {"{TIME}", DateTime.Now.ToString("HH:mm:ss") ?? " /// /// - private string PadLeftColorTag(string input) + private static string PadLeftColorTag(string input) { - string[] colorTagList = new string[] { + var colorTagList = new string[] { "{DEFAULT}", "{WHITE}", "{DARKRED}", From 6a4a09e49cc536a0c8c7fb01c1ca269250437387 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 6 Oct 2024 03:03:46 +0200 Subject: [PATCH 22/24] renaming name of workflow --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 22d2763..4c82bbd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: .NET 7 Build and Release +name: .NET 8 Build and Release on: pull_request: From ac24f1689455a563c3184ec4647e528e2e41b342 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 6 Oct 2024 03:16:53 +0200 Subject: [PATCH 23/24] adding color tags to prefix #62 --- CustomCommands/CustomCommands.cs | 5 ++- .../Services/ReplaceTagsFunction.cs | 37 +++++++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index 5ca8235..01d1a20 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -18,15 +18,17 @@ public partial class CustomCommands : BasePlugin, IPluginConfig Logger, - IPluginGlobals PluginGlobals, ILoadJson LoadJson, IEventManager EventManager) + IPluginGlobals PluginGlobals, ILoadJson LoadJson, IEventManager EventManager, IReplaceTagsFunctions ReplaceTagsFunctions) { this.Logger = Logger; _registerCommands = RegisterCommands; _pluginGlobals = PluginGlobals; _loadJson = LoadJson; _eventManager = EventManager; + _replaceTagsFunctions = ReplaceTagsFunctions; } public void OnConfigParsed(CustomCommandsConfig config) @@ -46,6 +48,7 @@ public override void Load(bool hotReload) $"{ModuleName} loaded!"); _pluginGlobals.Config = Config; + Config.Prefix = _replaceTagsFunctions.ReplaceColorTags(Config.Prefix); var comms = Task.Run(async () => await _loadJson.GetCommandsFromJsonFiles(ModuleDirectory)).Result; diff --git a/CustomCommands/Services/ReplaceTagsFunction.cs b/CustomCommands/Services/ReplaceTagsFunction.cs index 88775ef..b52d067 100644 --- a/CustomCommands/Services/ReplaceTagsFunction.cs +++ b/CustomCommands/Services/ReplaceTagsFunction.cs @@ -15,6 +15,8 @@ public partial class ReplaceTagsFunctions : IReplaceTagsFunctions private readonly IPluginGlobals _pluginGlobals; private readonly PluginContext _pluginContext; private readonly ILogger _logger; + + private static readonly Random _random = new Random(); public ReplaceTagsFunctions(IPluginGlobals PluginGlobals, IPluginContext PluginContext, ILogger Logger) @@ -79,20 +81,30 @@ public string ReplaceRandomTags(string message) // Replace all occurrences of the RNDNO tag in the message var match = ReplaceRandomTagsRegex().Match(message); + // Check if the match is successful + if (!match.Success) + { + return message; // Return original message if no match is found + } + // Extract min and max from the regex match groups string minStr = match.Groups[1].Value; string maxStr = match.Groups[2].Value; + // Check for empty strings + if (string.IsNullOrWhiteSpace(minStr) || string.IsNullOrWhiteSpace(maxStr)) + { + return message; // Return original message if min or max is empty + } + // Determine if the min and max are integers or floats bool isMinFloat = float.TryParse(minStr, out float minFloat); bool isMaxFloat = float.TryParse(maxStr, out float maxFloat); - var random = new Random(); - - if (isMinFloat || isMaxFloat) + if (isMinFloat && isMaxFloat) { // Generate a random float between min and max (inclusive) - float randomFloat = (float)(random.NextDouble() * (maxFloat - minFloat) + minFloat); + float randomFloat = (float)(_random.NextDouble() * (maxFloat - minFloat) + minFloat); // Determine the maximum precision from the min and max values int maxDecimalPlaces = Math.Max(GetDecimalPlaces(minStr), GetDecimalPlaces(maxStr)); @@ -100,17 +112,18 @@ public string ReplaceRandomTags(string message) // Use the determined precision to format the float message = message.Replace(match.Value, randomFloat.ToString($"F{maxDecimalPlaces}")); } - else + else if (int.TryParse(minStr, out int min) && int.TryParse(maxStr, out int max)) { - // Parse as integers - int min = int.Parse(minStr); - int max = int.Parse(maxStr); - - // Generate a random integer between min and max (inclusive) - int randomValue = random.Next(min, max + 1); // max is exclusive, so add 1 + /// Generate a random integer between min and max (inclusive) + int randomValue = _random.Next(min, max + 1); // max is exclusive, so add 1 message = message.Replace(match.Value, randomValue.ToString()); } - + else + { + // If neither min nor max is valid, return the original message + return message; + } + return message; } From b2d64921598ca06a7ca694d03e0724bad5710891 Mon Sep 17 00:00:00 2001 From: HerrMagic Date: Sun, 6 Oct 2024 19:09:55 +0200 Subject: [PATCH 24/24] change version --- CustomCommands/CustomCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CustomCommands/CustomCommands.cs b/CustomCommands/CustomCommands.cs index 01d1a20..b5b7879 100644 --- a/CustomCommands/CustomCommands.cs +++ b/CustomCommands/CustomCommands.cs @@ -9,7 +9,7 @@ namespace CustomCommands; public partial class CustomCommands : BasePlugin, IPluginConfig { public override string ModuleName => "CustomCommands"; - public override string ModuleVersion => "2.3.0"; + public override string ModuleVersion => "3.0.0"; public override string ModuleAuthor => "HerrMagic"; public override string ModuleDescription => "Create your own commands per config";