Skip to content

Commit 4719d44

Browse files
authored
Merge pull request #63 from HerrMagiic/dev
v3.0.0
2 parents d7a62f7 + b2d6492 commit 4719d44

37 files changed

+897
-320
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: .NET 7 Build and Release
1+
name: .NET 8 Build and Release
22

33
on:
44
pull_request:

CustomCommands/CustomCommands.cs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,26 @@ namespace CustomCommands;
99
public partial class CustomCommands : BasePlugin, IPluginConfig<CustomCommandsConfig>
1010
{
1111
public override string ModuleName => "CustomCommands";
12-
public override string ModuleVersion => "2.1.0";
12+
public override string ModuleVersion => "3.0.0";
1313
public override string ModuleAuthor => "HerrMagic";
1414
public override string ModuleDescription => "Create your own commands per config";
1515

1616
public CustomCommandsConfig Config { get; set; } = new();
17-
private readonly IRegisterCommands RegisterCommands;
18-
private readonly IPluginGlobals PluginGlobals;
19-
private readonly ILoadJson LoadJson;
20-
private readonly IEventManager EventManager;
17+
private readonly IRegisterCommands _registerCommands;
18+
private readonly IPluginGlobals _pluginGlobals;
19+
private readonly ILoadJson _loadJson;
20+
private readonly IEventManager _eventManager;
21+
private readonly IReplaceTagsFunctions _replaceTagsFunctions;
2122

2223
public CustomCommands(IRegisterCommands RegisterCommands, ILogger<CustomCommands> Logger,
23-
IPluginGlobals PluginGlobals, ILoadJson LoadJson, IEventManager EventManager)
24+
IPluginGlobals PluginGlobals, ILoadJson LoadJson, IEventManager EventManager, IReplaceTagsFunctions ReplaceTagsFunctions)
2425
{
2526
this.Logger = Logger;
26-
this.RegisterCommands = RegisterCommands;
27-
this.PluginGlobals = PluginGlobals;
28-
this.LoadJson = LoadJson;
29-
this.EventManager = EventManager;
27+
_registerCommands = RegisterCommands;
28+
_pluginGlobals = PluginGlobals;
29+
_loadJson = LoadJson;
30+
_eventManager = EventManager;
31+
_replaceTagsFunctions = ReplaceTagsFunctions;
3032
}
3133

3234
public void OnConfigParsed(CustomCommandsConfig config)
@@ -45,26 +47,29 @@ public override void Load(bool hotReload)
4547
Logger.LogInformation(
4648
$"{ModuleName} loaded!");
4749

48-
PluginGlobals.Config = Config;
50+
_pluginGlobals.Config = Config;
51+
Config.Prefix = _replaceTagsFunctions.ReplaceColorTags(Config.Prefix);
4952

50-
var comms = LoadJson.GetCommandsFromJsonFiles(ModuleDirectory);
53+
var comms = Task.Run(async () => await _loadJson.GetCommandsFromJsonFiles(ModuleDirectory)).Result;
5154

5255
if (comms == null)
5356
{
5457
Logger.LogError("No commands found please create a config file");
5558
return;
5659
}
5760

58-
EventManager.RegisterListeners();
61+
_eventManager.RegisterListeners();
5962

6063
if (comms != null)
6164
{
62-
PluginGlobals.CustomCommands = comms;
65+
_pluginGlobals.CustomCommands = comms;
66+
67+
_registerCommands.CheckForDuplicateCommands();
68+
_registerCommands.ConvertingCommandsForRegister();
6369

64-
comms = RegisterCommands.CheckForDuplicateCommands(comms);
6570
// Add commands from the JSON file to the server
66-
foreach (var com in comms)
67-
RegisterCommands.AddCommands(com);
71+
foreach (var cmd in _pluginGlobals.CustomCommands)
72+
_registerCommands.AddCommands(cmd);
6873
}
6974
}
7075
}

CustomCommands/CustomCommandsConfig.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ namespace CustomCommands;
66

77
public class CustomCommandsConfig : BasePluginConfig
88
{
9+
public override int Version { get; set; } = 2;
10+
911
[JsonPropertyName("IsPluginEnabled")]
1012
public bool IsPluginEnabled { get; set; } = true;
1113

@@ -14,4 +16,7 @@ public class CustomCommandsConfig : BasePluginConfig
1416

1517
[JsonPropertyName("Prefix")]
1618
public string Prefix { get; set; } = $"[{ChatColors.Yellow}Info{ChatColors.Default}] ";
19+
20+
[JsonPropertyName("RegisterCommandsAsCSSFramework")]
21+
public bool RegisterCommandsAsCSSFramework { get; set; } = true;
1722
}

CustomCommands/CustomCommandsServiceCollection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public class CustomCommandsServiceCollection : IPluginServiceCollection<CustomCo
99
{
1010
public void ConfigureServices(IServiceCollection services)
1111
{
12+
// Scans the interface in the CustomCommands.Interfaces namespace and adds the classes that implement the interface to the service collection automatically
1213
services.Scan(scan => scan
1314
.FromAssemblyOf<IRegisterCommands>()
1415
.AddClasses()

CustomCommands/Interfaces/ILoadJson.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,52 @@ namespace CustomCommands.Interfaces;
44

55
public interface ILoadJson
66
{
7-
List<Commands> GetCommandsFromJsonFiles(string path);
7+
/// <summary>
8+
/// Retrieves a list of commands from JSON files located in the specified path.
9+
/// </summary>
10+
/// <param name="path">The path where the JSON files are located.</param>
11+
/// <returns>A list of commands.</returns>
12+
Task<List<Commands>> GetCommandsFromJsonFiles(string path);
13+
14+
/// <summary>
15+
/// Checks if an .example file exists in the specified path and creates a default config file if it doesn't exist.
16+
/// </summary>
17+
/// <param name="path">The path to check for the example file.</param>
818
void CheckForExampleFile(string path);
9-
bool IsValidJsonSyntax(string jsonString);
19+
20+
/// <summary>
21+
/// Checks if the JSON file has a valid syntax.
22+
/// </summary>
23+
/// <param name="path">The path to the JSON file.</param>
24+
/// <param name="json">The json string.</param>
25+
/// <returns>True if the JSON syntax is valid, false otherwise.</returns>
26+
bool IsValidJsonSyntax(string json, string path);
27+
28+
/// <summary>
29+
/// Validates the list of commands loaded from a JSON file.
30+
/// </summary>
31+
/// <param name="comms">The list of commands to validate.</param>
32+
/// <param name="path">The path of the JSON file.</param>
33+
/// <returns>True if all commands are valid, false otherwise.</returns>
1034
bool ValidateObject(List<Commands>? comms, string path);
35+
36+
/// <summary>
37+
/// Logs the details of a command.
38+
/// </summary>
39+
/// <param name="comms">The command to log.</param>
1140
void LogCommandDetails(Commands comms);
41+
42+
/// <summary>
43+
/// Validates the PrintTo property of the Commands object and checks if the required message properties are set based on the PrintTo value.
44+
/// </summary>
45+
/// <param name="comms">The Commands object to validate.</param>
46+
/// <returns>True if the PrintTo property is valid and the required message properties are set; otherwise, false.</returns>
1247
bool PrintToCheck(Commands comms);
48+
49+
/// <summary>
50+
/// Validates a dynamic message by checking if it is a string or an array.
51+
/// </summary>
52+
/// <param name="message">The dynamic message to validate.</param>
53+
/// <returns>True if the message is a string or an array, otherwise false.</returns>
1354
bool ValidateMessage(dynamic message);
1455
}

CustomCommands/Interfaces/IMessageManager.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ namespace CustomCommands.Interfaces;
55

66
public interface IMessageManager
77
{
8+
/// <summary>
9+
/// Sends a message based on the specified command and target receiver.
10+
/// </summary>
11+
/// <param name="player">The player who triggered the command.</param>
12+
/// <param name="cmd">The command containing the message and target receiver.</param>
813
void SendMessage(CCSPlayerController player, Commands cmd);
914
void PrintToCenterClient(CCSPlayerController player, Commands cmd);
1015
void PrintToAllCenter(Commands cmd);

CustomCommands/Interfaces/IPluginUtilities.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,49 @@ namespace CustomCommands.Interfaces;
55

66
public interface IPluginUtilities
77
{
8+
/// <summary>
9+
/// Adds the css_ prefix to each alias.
10+
/// This will help cs# tell this command belongs to the framework.
11+
/// </summary>
12+
/// <param name="input"></param>
13+
/// <returns></returns>
14+
string[] AddCSSTagsToAliases(List<string> input);
15+
16+
/// <summary>
17+
/// Splits a string by comma, semicolon, or whitespace characters.
18+
/// </summary>
19+
/// <param name="str">The string to be split.</param>
20+
/// <returns>An array of strings containing the split substrings.</returns>
821
string[] SplitStringByCommaOrSemicolon(string str);
22+
23+
/// <summary>
24+
/// Executes the server commands from the command object
25+
/// </summary>
26+
/// <param name="cmd"></param>
27+
/// <param name="player"></param>
928
void ExecuteServerCommands(Commands cmd, CCSPlayerController player);
29+
30+
/// <summary>
31+
/// Issue the specified command to the specified client (mimics that client typing the command at the console).
32+
/// Note: Only works for some commands, marked with the FCVAR_CLIENT_CAN_EXECUTE flag (not many).
33+
/// </summary>
34+
/// <param name="cmd"></param>
35+
/// <param name="player"></param>
36+
void ExecuteClientCommands(Commands cmd, CCSPlayerController player);
37+
38+
/// <summary>
39+
/// Issue the specified command directly from the server (mimics the server executing the command with the given player context).
40+
/// <remarks>Works with server commands like `kill`, `explode`, `noclip`, etc. </remarks>
41+
/// </summary>
42+
/// <param name="cmd"></param>
43+
/// <param name="player"></param>
44+
void ExecuteClientCommandsFromServer(Commands cmd, CCSPlayerController player);
45+
46+
/// <summary>
47+
/// Checks if the player has the required permissions to execute the command
48+
/// </summary>
49+
/// <param name="player"></param>
50+
/// <param name="permissions"></param>
51+
/// <returns></returns>
1052
bool RequiresPermissions(CCSPlayerController player, Permission permissions);
1153
}

CustomCommands/Interfaces/IRegisterCommands.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ namespace CustomCommands.Interfaces;
44

55
public interface IRegisterCommands
66
{
7+
/// <summary>
8+
/// Adds custom commands to the plugin.
9+
/// </summary>
10+
/// <param name="com">The command to add.</param>
711
void AddCommands(Commands cmd);
8-
List<Commands> CheckForDuplicateCommands(List<Commands> comms);
12+
13+
/// <summary>
14+
/// Checks for duplicate commands in the provided list and removes them.
15+
/// </summary>
16+
void CheckForDuplicateCommands();
17+
18+
/// <summary>
19+
/// Converts custom commands stored in the global plugin state by processing each command string,
20+
/// splitting it by commas or semicolons, and adjusting the command structure.
21+
///
22+
/// The method clones each command, assigns a new unique ID, and processes its arguments.
23+
/// Each split command is then added back to the global list with updated formatting.
24+
/// </summary>
25+
void ConvertingCommandsForRegister();
926
}

CustomCommands/Interfaces/IReplaceTagsFunctions.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,40 @@ namespace CustomCommands.Interfaces;
44

55
public interface IReplaceTagsFunctions
66
{
7-
string[] ReplaceTags(string[] input, CCSPlayerController player);
7+
/// <summary>
8+
/// Replaces tags in the input array with their corresponding values.
9+
/// </summary>
10+
/// <param name="input">The array of strings containing tags to be replaced.</param>
11+
/// <param name="player">The CCSPlayerController object used for tag replacement.</param>
12+
/// <returns>The array of strings with tags replaced.</returns>
13+
string[] ReplaceTags(dynamic input, CCSPlayerController player);
14+
15+
/// <summary>
16+
/// Replaces language tags in the input string with the corresponding localized value.
17+
/// Language tags are defined within curly braces, e.g. "{LANG=LocalizerTag}".
18+
/// If a language tag is found, it is replaced with the localized value from the CustomCommands plugin's Localizer.
19+
/// If the localized value is not found, a default message is returned.
20+
/// </summary>
21+
/// <param name="input">The input string to process.</param>
22+
/// <returns>The input string with language tags replaced with localized values.</returns>
823
string ReplaceLanguageTags(string input);
24+
25+
/// <summary>
26+
/// Replaces tags in the input string with corresponding values based on the provided player information.
27+
/// </summary>
28+
/// <param name="input">The input string containing tags to be replaced.</param>
29+
/// <param name="player">The CCSPlayerController object representing the player.</param>
30+
/// <param name="safety">A boolean value indicating whether to replace the {PLAYERNAME} tag. Default is true.</param>
31+
/// <returns>The modified string with replaced tags.</returns>
932
string ReplaceMessageTags(string input, CCSPlayerController player, bool safety = true);
1033
string ReplaceColorTags(string input);
11-
string[] WrappedLine(dynamic message);
34+
35+
/// <summary>
36+
/// 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.
37+
/// </summary>
38+
/// <param name="input">This should be a string[] or a string</param>
39+
/// <returns>An array of strings representing the lines of the input.</returns>
40+
List<string> WrappedLine(dynamic message);
41+
42+
string ReplaceRandomTags(string message);
1243
}

CustomCommands/Model/CommandsConfig.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
namespace CustomCommands.Model;
22

3-
public class Commands
3+
public class Commands : ICloneable
44
{
55
public Guid ID { get; set; } = Guid.NewGuid();
6+
public string? Argument { get; set; }
67
public string Title { get; set; } = "";
78
public string Description { get; set; } = "Description";
89
public string Command { get; set; } = "";
@@ -11,18 +12,48 @@ public class Commands
1112
public CenterElement CenterMessage { get; set; } = new();
1213
public Sender PrintTo { get; set; } = Sender.ClientChat;
1314
public List<string> ServerCommands { get; set; } = new();
14-
public Permission Permission { get; set; } = new();
15+
public List<string> ClientCommands { get; set; } = new();
16+
public List<string> ClientCommandsFromServer { get; set; } = new();
17+
public Permission? Permission { get; set; } = new();
18+
public bool IsRegisterable { get; set; } = true;
19+
20+
public object Clone()
21+
{
22+
return new Commands()
23+
{
24+
ID = ID,
25+
Argument = Argument,
26+
Title = Title,
27+
Description = Description,
28+
Command = Command,
29+
Cooldown = Cooldown,
30+
Message = Message,
31+
CenterMessage = CenterMessage,
32+
PrintTo = PrintTo,
33+
ServerCommands = new List<string>(ServerCommands),
34+
ClientCommands = new List<string>(ClientCommands),
35+
ClientCommandsFromServer = new List<string>(ClientCommandsFromServer),
36+
Permission = Permission?.Clone() as Permission,
37+
IsRegisterable = IsRegisterable
38+
};
39+
}
1540
}
1641
public class Cooldown
1742
{
1843
public int CooldownTime { get; set; } = 0;
1944
public bool IsGlobal { get; set; } = false;
2045
public string CooldownMessage { get; set; } = "";
2146
}
22-
public class Permission
47+
public class Permission : ICloneable
2348
{
2449
public bool RequiresAllPermissions { get; set; } = false;
2550
public List<string> PermissionList { get; set; } = new();
51+
52+
public object Clone()
53+
{
54+
return MemberwiseClone();
55+
}
56+
2657
}
2758
public class CenterElement
2859
{

0 commit comments

Comments
 (0)