Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.0.0 #63

Merged
merged 29 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9e06e2d
Adding Comments
HerrMagiic Feb 9, 2024
17d9652
fixed a bug that commands are not tagged as cs# commands
NilsSchucka Feb 13, 2024
0961fe2
fixed newline not working in language tags
NilsSchucka Feb 13, 2024
357f608
fixed newline not working in LANG tag
NilsSchucka Feb 13, 2024
10ddfd5
Adding config option to disable css_ befor the cmd
HerrMagiic Feb 15, 2024
9d0708f
Adding Execute Client COmmands
HerrMagiic Feb 16, 2024
23736c5
Merge branch 'dev' of https://github.com/HerrMagiic/CSS-CreateCustomC…
HerrMagiic Feb 16, 2024
1e80010
Updating Examples to markdown with more explanation
HerrMagiic Feb 16, 2024
a64b781
update to dotnet 8
HerrMagiic Apr 21, 2024
4b0c62e
update css to 213 and normal v to 2.1.0
HerrMagiic Apr 21, 2024
f230997
Merge pull request #56 from HerrMagiic/dotnet8
HerrMagiic Apr 21, 2024
b337fa2
Merge pull request #60 from HerrMagiic/main
HerrMagiic Apr 25, 2024
96e0b9a
fixed WrappedLine accepting normal Array
HerrMagiic May 26, 2024
83dcb5f
fixed wrong Tag showing in Cooldown Examples
HerrMagiic May 26, 2024
805cf58
update ServerCommand Kick example
HerrMagiic May 26, 2024
87f760e
Fixed CenterMessage not working
HerrMagiic May 26, 2024
02d8e16
args still not working
HerrMagiic May 26, 2024
12258fb
adding unicode support
NilsSchucka Jun 4, 2024
2673a93
Merge branch 'dev' of https://github.com/HerrMagiic/CSS-CreateCustomC…
NilsSchucka Jun 4, 2024
d077c68
change version to v2.2.0
HerrMagiic Jun 28, 2024
879328c
Merge branch 'dev' of https://github.com/HerrMagiic/CSS-CreateCustomC…
HerrMagiic Oct 5, 2024
139e34a
set some vars to var. added clone function to object
HerrMagiic Oct 5, 2024
9f02b60
fixing argument problems
HerrMagiic Oct 5, 2024
78bed95
fixing args not working
HerrMagiic Oct 6, 2024
dade59a
small impovements
HerrMagiic Oct 6, 2024
6ca65f5
adding random tag #66
HerrMagiic Oct 6, 2024
6a4a09e
renaming name of workflow
HerrMagiic Oct 6, 2024
ac24f16
adding color tags to prefix #62
HerrMagiic Oct 6, 2024
b2d6492
change version
HerrMagiic Oct 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: .NET 7 Build and Release
name: .NET 8 Build and Release

on:
pull_request:
Expand Down
39 changes: 22 additions & 17 deletions CustomCommands/CustomCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ namespace CustomCommands;
public partial class CustomCommands : BasePlugin, IPluginConfig<CustomCommandsConfig>
{
public override string ModuleName => "CustomCommands";
public override string ModuleVersion => "2.1.0";
public override string ModuleVersion => "3.0.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;
private readonly IReplaceTagsFunctions _replaceTagsFunctions;

public CustomCommands(IRegisterCommands RegisterCommands, ILogger<CustomCommands> Logger,
IPluginGlobals PluginGlobals, ILoadJson LoadJson, IEventManager EventManager)
IPluginGlobals PluginGlobals, ILoadJson LoadJson, IEventManager EventManager, IReplaceTagsFunctions ReplaceTagsFunctions)
{
this.Logger = Logger;
this.RegisterCommands = RegisterCommands;
this.PluginGlobals = PluginGlobals;
this.LoadJson = LoadJson;
this.EventManager = EventManager;
_registerCommands = RegisterCommands;
_pluginGlobals = PluginGlobals;
_loadJson = LoadJson;
_eventManager = EventManager;
_replaceTagsFunctions = ReplaceTagsFunctions;
}

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

PluginGlobals.Config = Config;
_pluginGlobals.Config = Config;
Config.Prefix = _replaceTagsFunctions.ReplaceColorTags(Config.Prefix);

var comms = LoadJson.GetCommandsFromJsonFiles(ModuleDirectory);
var comms = Task.Run(async () => await _loadJson.GetCommandsFromJsonFiles(ModuleDirectory)).Result;

if (comms == null)
{
Logger.LogError("No commands found please create a config file");
return;
}

EventManager.RegisterListeners();
_eventManager.RegisterListeners();

if (comms != null)
{
PluginGlobals.CustomCommands = comms;
_pluginGlobals.CustomCommands = comms;

_registerCommands.CheckForDuplicateCommands();
_registerCommands.ConvertingCommandsForRegister();

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 _pluginGlobals.CustomCommands)
_registerCommands.AddCommands(cmd);
}
}
}
5 changes: 5 additions & 0 deletions CustomCommands/CustomCommandsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}
1 change: 1 addition & 0 deletions CustomCommands/CustomCommandsServiceCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class CustomCommandsServiceCollection : IPluginServiceCollection<CustomCo
{
public void ConfigureServices(IServiceCollection services)
{
// Scans the interface in the CustomCommands.Interfaces namespace and adds the classes that implement the interface to the service collection automatically
services.Scan(scan => scan
.FromAssemblyOf<IRegisterCommands>()
.AddClasses()
Expand Down
45 changes: 43 additions & 2 deletions CustomCommands/Interfaces/ILoadJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,52 @@ namespace CustomCommands.Interfaces;

public interface ILoadJson
{
List<Commands> GetCommandsFromJsonFiles(string path);
/// <summary>
/// Retrieves a list of commands from JSON files located in the specified path.
/// </summary>
/// <param name="path">The path where the JSON files are located.</param>
/// <returns>A list of commands.</returns>
Task<List<Commands>> GetCommandsFromJsonFiles(string path);

/// <summary>
/// Checks if an .example file exists in the specified path and creates a default config file if it doesn't exist.
/// </summary>
/// <param name="path">The path to check for the example file.</param>
void CheckForExampleFile(string path);
bool IsValidJsonSyntax(string jsonString);

/// <summary>
/// Checks if the JSON file has a valid syntax.
/// </summary>
/// <param name="path">The path to the JSON file.</param>
/// <param name="json">The json string.</param>
/// <returns>True if the JSON syntax is valid, false otherwise.</returns>
bool IsValidJsonSyntax(string json, string path);

/// <summary>
/// Validates the list of commands loaded from a JSON file.
/// </summary>
/// <param name="comms">The list of commands to validate.</param>
/// <param name="path">The path of the JSON file.</param>
/// <returns>True if all commands are valid, false otherwise.</returns>
bool ValidateObject(List<Commands>? comms, string path);

/// <summary>
/// Logs the details of a command.
/// </summary>
/// <param name="comms">The command to log.</param>
void LogCommandDetails(Commands comms);

/// <summary>
/// Validates the PrintTo property of the Commands object and checks if the required message properties are set based on the PrintTo value.
/// </summary>
/// <param name="comms">The Commands object to validate.</param>
/// <returns>True if the PrintTo property is valid and the required message properties are set; otherwise, false.</returns>
bool PrintToCheck(Commands comms);

/// <summary>
/// Validates a dynamic message by checking if it is a string or an array.
/// </summary>
/// <param name="message">The dynamic message to validate.</param>
/// <returns>True if the message is a string or an array, otherwise false.</returns>
bool ValidateMessage(dynamic message);
}
5 changes: 5 additions & 0 deletions CustomCommands/Interfaces/IMessageManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace CustomCommands.Interfaces;

public interface IMessageManager
{
/// <summary>
/// Sends a message based on the specified command and target receiver.
/// </summary>
/// <param name="player">The player who triggered the command.</param>
/// <param name="cmd">The command containing the message and target receiver.</param>
void SendMessage(CCSPlayerController player, Commands cmd);
void PrintToCenterClient(CCSPlayerController player, Commands cmd);
void PrintToAllCenter(Commands cmd);
Expand Down
42 changes: 42 additions & 0 deletions CustomCommands/Interfaces/IPluginUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,49 @@ namespace CustomCommands.Interfaces;

public interface IPluginUtilities
{
/// <summary>
/// Adds the css_ prefix to each alias.
/// This will help cs# tell this command belongs to the framework.
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
string[] AddCSSTagsToAliases(List<string> input);

/// <summary>
/// Splits a string by comma, semicolon, or whitespace characters.
/// </summary>
/// <param name="str">The string to be split.</param>
/// <returns>An array of strings containing the split substrings.</returns>
string[] SplitStringByCommaOrSemicolon(string str);

/// <summary>
/// Executes the server commands from the command object
/// </summary>
/// <param name="cmd"></param>
/// <param name="player"></param>
void ExecuteServerCommands(Commands cmd, CCSPlayerController player);

/// <summary>
/// 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).
/// </summary>
/// <param name="cmd"></param>
/// <param name="player"></param>
void ExecuteClientCommands(Commands cmd, CCSPlayerController player);

/// <summary>
/// Issue the specified command directly from the server (mimics the server executing the command with the given player context).
/// <remarks>Works with server commands like `kill`, `explode`, `noclip`, etc. </remarks>
/// </summary>
/// <param name="cmd"></param>
/// <param name="player"></param>
void ExecuteClientCommandsFromServer(Commands cmd, CCSPlayerController player);

/// <summary>
/// Checks if the player has the required permissions to execute the command
/// </summary>
/// <param name="player"></param>
/// <param name="permissions"></param>
/// <returns></returns>
bool RequiresPermissions(CCSPlayerController player, Permission permissions);
}
19 changes: 18 additions & 1 deletion CustomCommands/Interfaces/IRegisterCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ namespace CustomCommands.Interfaces;

public interface IRegisterCommands
{
/// <summary>
/// Adds custom commands to the plugin.
/// </summary>
/// <param name="com">The command to add.</param>
void AddCommands(Commands cmd);
List<Commands> CheckForDuplicateCommands(List<Commands> comms);

/// <summary>
/// Checks for duplicate commands in the provided list and removes them.
/// </summary>
void CheckForDuplicateCommands();

/// <summary>
/// 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.
/// </summary>
void ConvertingCommandsForRegister();
}
35 changes: 33 additions & 2 deletions CustomCommands/Interfaces/IReplaceTagsFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,40 @@ namespace CustomCommands.Interfaces;

public interface IReplaceTagsFunctions
{
string[] ReplaceTags(string[] input, CCSPlayerController player);
/// <summary>
/// Replaces tags in the input array with their corresponding values.
/// </summary>
/// <param name="input">The array of strings containing tags to be replaced.</param>
/// <param name="player">The CCSPlayerController object used for tag replacement.</param>
/// <returns>The array of strings with tags replaced.</returns>
string[] ReplaceTags(dynamic input, CCSPlayerController player);

/// <summary>
/// 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.
/// </summary>
/// <param name="input">The input string to process.</param>
/// <returns>The input string with language tags replaced with localized values.</returns>
string ReplaceLanguageTags(string input);

/// <summary>
/// Replaces tags in the input string with corresponding values based on the provided player information.
/// </summary>
/// <param name="input">The input string containing tags to be replaced.</param>
/// <param name="player">The CCSPlayerController object representing the player.</param>
/// <param name="safety">A boolean value indicating whether to replace the {PLAYERNAME} tag. Default is true.</param>
/// <returns>The modified string with replaced tags.</returns>
string ReplaceMessageTags(string input, CCSPlayerController player, bool safety = true);
string ReplaceColorTags(string input);
string[] WrappedLine(dynamic message);

/// <summary>
/// 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.
/// </summary>
/// <param name="input">This should be a string[] or a string</param>
/// <returns>An array of strings representing the lines of the input.</returns>
List<string> WrappedLine(dynamic message);

string ReplaceRandomTags(string message);
}
37 changes: 34 additions & 3 deletions CustomCommands/Model/CommandsConfig.cs
Original file line number Diff line number Diff line change
@@ -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; } = "";
Expand All @@ -11,18 +12,48 @@ public class Commands
public CenterElement CenterMessage { get; set; } = new();
public Sender PrintTo { get; set; } = Sender.ClientChat;
public List<string> ServerCommands { get; set; } = new();
public Permission Permission { get; set; } = new();
public List<string> ClientCommands { get; set; } = new();
public List<string> ClientCommandsFromServer { get; set; } = new();
public Permission? Permission { get; set; } = new();
public bool IsRegisterable { get; set; } = true;

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<string>(ServerCommands),
ClientCommands = new List<string>(ClientCommands),
ClientCommandsFromServer = new List<string>(ClientCommandsFromServer),
Permission = Permission?.Clone() as Permission,
IsRegisterable = IsRegisterable
};
}
}
public class Cooldown
{
public int CooldownTime { get; set; } = 0;
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<string> PermissionList { get; set; } = new();

public object Clone()
{
return MemberwiseClone();
}

}
public class CenterElement
{
Expand Down
Loading
Loading