Skip to content

Update 2.1.0 #57

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

Closed
wants to merge 11 commits into from
8 changes: 4 additions & 4 deletions CustomCommands/CustomCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

namespace CustomCommands;

[MinimumApiVersion(142)]
[MinimumApiVersion(213)]
public partial class CustomCommands : BasePlugin, IPluginConfig<CustomCommandsConfig>
{
public override string ModuleName => "CustomCommands";
public override string ModuleVersion => "2.0.3";
public override string ModuleVersion => "2.1.0";
public override string ModuleAuthor => "HerrMagic";
public override string ModuleDescription => "Create your own commands per config";

Expand Down Expand Up @@ -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);
}
}
}
4 changes: 2 additions & 2 deletions CustomCommands/CustomCommands.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
Expand All @@ -10,7 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.163">
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.213">
<PrivateAssets>none</PrivateAssets>
<ExcludeAssets>runtime</ExcludeAssets>
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
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
49 changes: 49 additions & 0 deletions CustomCommands/Interfaces/IPluginUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,56 @@ namespace CustomCommands.Interfaces;

public interface IPluginUtilities
{
/// <summary>
/// Splits the commands string into an array of strings.
/// </summary>
/// <param name="commands"></param>
/// <returns></returns>
string[] GettingCommandsFromString(string commands);

/// <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(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);
}
10 changes: 10 additions & 0 deletions CustomCommands/Interfaces/IRegisterCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ 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);

/// <summary>
/// Checks for duplicate commands in the provided list and removes them.
/// </summary>
/// <param name="comms">The list of commands to check for duplicates.</param>
/// <returns>A new list of commands without any duplicates.</returns>
List<Commands> CheckForDuplicateCommands(List<Commands> comms);
}
4 changes: 2 additions & 2 deletions CustomCommands/Interfaces/IReplaceTagsFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ namespace CustomCommands.Interfaces;

public interface IReplaceTagsFunctions
{
string[] ReplaceTags(string[] input, CCSPlayerController player);
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<string> WrappedLine(dynamic message);
}
2 changes: 2 additions & 0 deletions CustomCommands/Model/CommandsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public class Commands
public CenterElement CenterMessage { get; set; } = new();
public Sender PrintTo { get; set; } = Sender.ClientChat;
public List<string> ServerCommands { get; set; } = new();
public List<string> ClientCommands { get; set; } = new();
public List<string> ClientCommandsFromServer { get; set; } = new();
public Permission Permission { get; set; } = new();
}
public class Cooldown
Expand Down
21 changes: 13 additions & 8 deletions CustomCommands/Services/CooldownManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/// <summary>
Expand All @@ -33,17 +33,23 @@ public bool IsCommandOnCooldown(CCSPlayerController player, Commands cmd)
return false;
}

/// <summary>
/// Checks if a command is on cooldown based on a given condition.
/// </summary>
/// <param name="predicate">The condition to check for each cooldown timer.</param>
/// <param name="player">The player controller.</param>
/// <param name="cmd">The command.</param>
/// <returns>True if the command is on cooldown, false otherwise.</returns>
public bool IsCommandOnCooldownWithCondition(Func<CooldownTimer, bool> predicate, CCSPlayerController player, Commands cmd)
{
int 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 = "";
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
Expand Down Expand Up @@ -129,7 +135,6 @@ public void SetCooldown(CCSPlayerController player, Commands cmd)

var cooldownObject = JsonSerializer.Deserialize<Cooldown>(cmd.Cooldown.GetRawText());
AddToCooldownList(cooldownObject.IsGlobal, player.UserId ?? 0, cmd.ID, cooldownObject.CooldownTime);

break;

default:
Expand Down
7 changes: 4 additions & 3 deletions CustomCommands/Services/EventManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -32,6 +32,7 @@ public void RegisterListeners()
{
CustomCommands plugin = (PluginContext.Plugin as CustomCommands)!;

// Register the OnTick event for PrintToCenterHtml duration
plugin.RegisterListener<Listeners.OnTick>(() =>
{
// Client Print To Center
Expand Down
39 changes: 38 additions & 1 deletion CustomCommands/Services/LoadJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public LoadJson(ILogger<CustomCommands> Logger)
this.Logger = Logger;
}

/// <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>
public List<Commands> GetCommandsFromJsonFiles(string path)
{
var comms = new List<Commands>();
Expand Down Expand Up @@ -55,7 +60,12 @@ public List<Commands> GetCommandsFromJsonFiles(string path)
}
return comms;
}
// Check if the Command.json file exists. If not replace it with the example file


/// <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>
public void CheckForExampleFile(string path)
{
if (Directory.Exists(Path.Combine(path, "Commands")))
Expand All @@ -73,6 +83,12 @@ public void CheckForExampleFile(string path)
Logger.LogInformation("Created default config file.");
}
}

/// <summary>
/// Checks if the JSON file has a valid syntax.
/// </summary>
/// <param name="path">The path to the JSON file.</param>
/// <returns>True if the JSON syntax is valid, false otherwise.</returns>
public bool IsValidJsonSyntax(string path)
{
try
Expand All @@ -88,6 +104,13 @@ public bool IsValidJsonSyntax(string path)
return false;
}
}

/// <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>
public bool ValidateObject(List<Commands>? comms, string path)
{
if (comms == null)
Expand Down Expand Up @@ -131,6 +154,10 @@ public bool ValidateObject(List<Commands>? comms, string path)
return true;
}

/// <summary>
/// Logs the details of a command.
/// </summary>
/// <param name="comms">The command to log.</param>
public void LogCommandDetails(Commands comms)
{
Logger.LogInformation($"-- Title: {comms.Title}");
Expand All @@ -145,6 +172,11 @@ public void LogCommandDetails(Commands comms)
Logger.LogInformation("--------------------------------------------------");
}

/// <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>
public bool PrintToCheck(Commands comms)
{
if (comms.PrintTo == Sender.ClientChat || comms.PrintTo == Sender.AllChat)
Expand Down Expand Up @@ -175,6 +207,11 @@ public bool PrintToCheck(Commands comms)
return true;
}

/// <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>
public bool ValidateMessage(dynamic message)
{
if (message is JsonElement jsonElement)
Expand Down
17 changes: 10 additions & 7 deletions CustomCommands/Services/MessageManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public MessageManager(IPluginGlobals PluginGlobals, IReplaceTagsFunctions Replac
this.PluginContext = (PluginContext as PluginContext)!;
}

/// <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>
public void SendMessage(CCSPlayerController player, Commands cmd)
{
switch (cmd.PrintTo)
Expand Down Expand Up @@ -55,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
{
Expand All @@ -72,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, () =>
{
Expand All @@ -95,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)
{
Expand Down
15 changes: 15 additions & 0 deletions CustomCommands/Services/PluginGlobals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,24 @@
namespace CustomCommands.Services;
public class PluginGlobals : IPluginGlobals
{
/// <summary>
/// List of clients that have a message printed to their center.
/// </summary>
public List<CenterClientElement> centerClientOn { get; set; } = new();
/// <summary>
/// The message that is printed to all players' center.
/// </summary>
public CenterServerElement centerServerOn { get; set; } = new();
/// <summary>
/// The configuration for the plugin.
/// </summary>
public CustomCommandsConfig Config { get; set; } = new();
/// <summary>
/// List of cooldown timers for each player.
/// </summary>
public List<CooldownTimer> CooldownTimer { get; set; } = new();
/// <summary>
/// List of custom commands.
/// </summary>
public List<Commands> CustomCommands { get; set; } = new();
}
Loading
Loading