diff --git a/EXILED/Exiled.API/Features/Plugin.cs b/EXILED/Exiled.API/Features/Plugin.cs index 0c4b23fd2b..6153cbeee4 100644 --- a/EXILED/Exiled.API/Features/Plugin.cs +++ b/EXILED/Exiled.API/Features/Plugin.cs @@ -7,6 +7,8 @@ namespace Exiled.API.Features { + using System.Linq; + #pragma warning disable SA1402 using System; using System.Collections.Generic; @@ -97,6 +99,8 @@ public virtual void OnEnabled() /// public virtual void OnRegisteringCommands() { + Dictionary> toRegister = new(); + foreach (Type type in Assembly.GetTypes()) { if (type.GetInterface("ICommand") != typeof(ICommand)) @@ -105,28 +109,42 @@ public virtual void OnRegisteringCommands() if (!Attribute.IsDefined(type, typeof(CommandHandlerAttribute))) continue; - foreach (CustomAttributeData customAttributeData in type.CustomAttributes) + foreach (CustomAttributeData customAttributeData in type.GetCustomAttributesData()) { try { if (customAttributeData.AttributeType != typeof(CommandHandlerAttribute)) continue; - Type commandType = (Type)customAttributeData.ConstructorArguments?[0].Value; + Type commandHandlerType = (Type)customAttributeData.ConstructorArguments[0].Value; - if (!Commands.TryGetValue(commandType, out Dictionary typeCommands)) - continue; + ICommand command = GetCommand(type) ?? (ICommand)Activator.CreateInstance(type); - if (!typeCommands.TryGetValue(type, out ICommand command)) - command = (ICommand)Activator.CreateInstance(type); + if (typeof(ParentCommand).IsAssignableFrom(commandHandlerType)) + { + ParentCommand parentCommand = GetCommand(commandHandlerType) as ParentCommand; + + if (parentCommand == null) + { + if (!toRegister.TryGetValue(commandHandlerType, out List list)) + toRegister.Add(commandHandlerType, new() { command }); + else + list.Add(command); + + continue; + } + + parentCommand.RegisterCommand(command); + continue; + } try { - if (commandType == typeof(RemoteAdminCommandHandler)) + if (commandHandlerType == typeof(RemoteAdminCommandHandler)) CommandProcessor.RemoteAdminCommandHandler.RegisterCommand(command); - else if (commandType == typeof(GameConsoleCommandHandler)) + else if (commandHandlerType == typeof(GameConsoleCommandHandler)) GameCore.Console.singleton.ConsoleCommandHandler.RegisterCommand(command); - else if (commandType == typeof(ClientCommandHandler)) + else if (commandHandlerType == typeof(ClientCommandHandler)) QueryProcessor.DotCommandHandler.RegisterCommand(command); } catch (ArgumentException e) @@ -141,7 +159,7 @@ public virtual void OnRegisteringCommands() } } - Commands[commandType][type] = command; + Commands[commandHandlerType][type] = command; } catch (Exception exception) { @@ -149,6 +167,39 @@ public virtual void OnRegisteringCommands() } } } + + foreach (KeyValuePair> kvp in toRegister) + { + ParentCommand parentCommand = GetCommand(kvp.Key) as ParentCommand; + + foreach (ICommand command in kvp.Value) + parentCommand.RegisterCommand(command); + } + } + + /// + /// Gets a command by it's type. + /// + /// 's type. + /// 's type. Defines in which command handler command is registered. + /// A . May be if command is not registered. + public ICommand GetCommand(Type type, Type commandHandler = null) + { + if (type.GetInterface("ICommand") != typeof(ICommand)) + return null; + + if (commandHandler != null) + { + if (!Commands.TryGetValue(commandHandler, out Dictionary commands)) + return null; + + if (!commands.TryGetValue(type, out ICommand command)) + return null; + + return command; + } + + return Commands.Keys.Select(commandHandlerType => GetCommand(type, commandHandlerType)).FirstOrDefault(command => command != null); } /// diff --git a/EXILED/Exiled.Events/Commands/Config/EConfig.cs b/EXILED/Exiled.Events/Commands/Config/EConfig.cs index 120ed46619..6b6ead4b60 100644 --- a/EXILED/Exiled.Events/Commands/Config/EConfig.cs +++ b/EXILED/Exiled.Events/Commands/Config/EConfig.cs @@ -17,14 +17,6 @@ namespace Exiled.Events.Commands.Config [CommandHandler(typeof(GameConsoleCommandHandler))] public class EConfig : ParentCommand { - /// - /// Initializes a new instance of the class. - /// - public EConfig() - { - LoadGeneratedCommands(); - } - /// public override string Command { get; } = "econfig"; @@ -37,8 +29,6 @@ public EConfig() /// public override void LoadGeneratedCommands() { - RegisterCommand(Merge.Instance); - RegisterCommand(Split.Instance); } /// diff --git a/EXILED/Exiled.Events/Commands/Config/Merge.cs b/EXILED/Exiled.Events/Commands/Config/Merge.cs index dc90cad8ec..7bad3a00e4 100644 --- a/EXILED/Exiled.Events/Commands/Config/Merge.cs +++ b/EXILED/Exiled.Events/Commands/Config/Merge.cs @@ -20,6 +20,7 @@ namespace Exiled.Events.Commands.Config /// /// The config merge command. /// + [CommandHandler(typeof(EConfig))] public class Merge : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/Config/Split.cs b/EXILED/Exiled.Events/Commands/Config/Split.cs index ab2f1a577c..ad42f3024a 100644 --- a/EXILED/Exiled.Events/Commands/Config/Split.cs +++ b/EXILED/Exiled.Events/Commands/Config/Split.cs @@ -20,6 +20,7 @@ namespace Exiled.Events.Commands.Config /// /// The config split command. /// + [CommandHandler(typeof(EConfig))] public class Split : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/PluginManager/Disable.cs b/EXILED/Exiled.Events/Commands/PluginManager/Disable.cs index 998a81cdfb..81d3bdffd5 100644 --- a/EXILED/Exiled.Events/Commands/PluginManager/Disable.cs +++ b/EXILED/Exiled.Events/Commands/PluginManager/Disable.cs @@ -17,6 +17,7 @@ namespace Exiled.Events.Commands.PluginManager /// /// The command to disable a plugin. /// + [CommandHandler(typeof(PluginManager))] public sealed class Disable : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/PluginManager/Enable.cs b/EXILED/Exiled.Events/Commands/PluginManager/Enable.cs index 5c0201b647..4e400fe81c 100644 --- a/EXILED/Exiled.Events/Commands/PluginManager/Enable.cs +++ b/EXILED/Exiled.Events/Commands/PluginManager/Enable.cs @@ -21,6 +21,7 @@ namespace Exiled.Events.Commands.PluginManager /// /// The command to enable a plugin. /// + [CommandHandler(typeof(PluginManager))] public sealed class Enable : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/PluginManager/Patches.cs b/EXILED/Exiled.Events/Commands/PluginManager/Patches.cs index 9543e73aab..61d729f822 100644 --- a/EXILED/Exiled.Events/Commands/PluginManager/Patches.cs +++ b/EXILED/Exiled.Events/Commands/PluginManager/Patches.cs @@ -23,6 +23,7 @@ namespace Exiled.Events.Commands.PluginManager /// /// The command to show all the patches done by plugins. /// + [CommandHandler(typeof(PluginManager))] public sealed class Patches : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/PluginManager/PluginManager.cs b/EXILED/Exiled.Events/Commands/PluginManager/PluginManager.cs index ba778d5f43..2a4a550b40 100644 --- a/EXILED/Exiled.Events/Commands/PluginManager/PluginManager.cs +++ b/EXILED/Exiled.Events/Commands/PluginManager/PluginManager.cs @@ -18,14 +18,6 @@ namespace Exiled.Events.Commands.PluginManager [CommandHandler(typeof(GameConsoleCommandHandler))] public class PluginManager : ParentCommand { - /// - /// Initializes a new instance of the class. - /// - public PluginManager() - { - LoadGeneratedCommands(); - } - /// public override string Command { get; } = "pluginmanager"; @@ -38,10 +30,6 @@ public PluginManager() /// public override void LoadGeneratedCommands() { - RegisterCommand(Show.Instance); - RegisterCommand(Enable.Instance); - RegisterCommand(Disable.Instance); - RegisterCommand(Patches.Instance); } /// diff --git a/EXILED/Exiled.Events/Commands/PluginManager/Show.cs b/EXILED/Exiled.Events/Commands/PluginManager/Show.cs index b703d44fcd..cd73799329 100644 --- a/EXILED/Exiled.Events/Commands/PluginManager/Show.cs +++ b/EXILED/Exiled.Events/Commands/PluginManager/Show.cs @@ -24,6 +24,7 @@ namespace Exiled.Events.Commands.PluginManager /// /// The command to show all plugins. /// + [CommandHandler(typeof(PluginManager))] public sealed class Show : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/Reload/All.cs b/EXILED/Exiled.Events/Commands/Reload/All.cs index 124114e7e5..a46af1f5e2 100644 --- a/EXILED/Exiled.Events/Commands/Reload/All.cs +++ b/EXILED/Exiled.Events/Commands/Reload/All.cs @@ -14,6 +14,7 @@ namespace Exiled.Events.Commands.Reload /// /// The reload all command. /// + [CommandHandler(typeof(Reload))] public class All : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/Reload/Configs.cs b/EXILED/Exiled.Events/Commands/Reload/Configs.cs index 81ab11e792..2c6ed0a27c 100644 --- a/EXILED/Exiled.Events/Commands/Reload/Configs.cs +++ b/EXILED/Exiled.Events/Commands/Reload/Configs.cs @@ -20,6 +20,7 @@ namespace Exiled.Events.Commands.Reload /// /// The reload configs command. /// + [CommandHandler(typeof(Reload))] public class Configs : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/Reload/GamePlay.cs b/EXILED/Exiled.Events/Commands/Reload/GamePlay.cs index babd4c5bd2..02a02460a3 100644 --- a/EXILED/Exiled.Events/Commands/Reload/GamePlay.cs +++ b/EXILED/Exiled.Events/Commands/Reload/GamePlay.cs @@ -18,6 +18,7 @@ namespace Exiled.Events.Commands.Reload /// /// The reload gameplay command. /// + [CommandHandler(typeof(Reload))] public class GamePlay : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/Reload/Permissions.cs b/EXILED/Exiled.Events/Commands/Reload/Permissions.cs index 1f3943a82e..a0e9b9ec42 100644 --- a/EXILED/Exiled.Events/Commands/Reload/Permissions.cs +++ b/EXILED/Exiled.Events/Commands/Reload/Permissions.cs @@ -17,6 +17,7 @@ namespace Exiled.Events.Commands.Reload /// /// The reload permissions command. /// + [CommandHandler(typeof(Reload))] public class Permissions : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/Reload/Plugins.cs b/EXILED/Exiled.Events/Commands/Reload/Plugins.cs index 1a1c144722..f41d6027c0 100644 --- a/EXILED/Exiled.Events/Commands/Reload/Plugins.cs +++ b/EXILED/Exiled.Events/Commands/Reload/Plugins.cs @@ -19,6 +19,7 @@ namespace Exiled.Events.Commands.Reload /// /// The reload plugins command. /// + [CommandHandler(typeof(Reload))] public class Plugins : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/Reload/Reload.cs b/EXILED/Exiled.Events/Commands/Reload/Reload.cs index bf139a7fd0..b68927f63f 100644 --- a/EXILED/Exiled.Events/Commands/Reload/Reload.cs +++ b/EXILED/Exiled.Events/Commands/Reload/Reload.cs @@ -18,14 +18,6 @@ namespace Exiled.Events.Commands.Reload [CommandHandler(typeof(GameConsoleCommandHandler))] public class Reload : ParentCommand { - /// - /// Initializes a new instance of the class. - /// - public Reload() - { - LoadGeneratedCommands(); - } - /// public override string Command { get; } = "reload"; @@ -38,13 +30,6 @@ public Reload() /// public override void LoadGeneratedCommands() { - RegisterCommand(All.Instance); - RegisterCommand(Configs.Instance); - RegisterCommand(Translations.Instance); - RegisterCommand(Plugins.Instance); - RegisterCommand(GamePlay.Instance); - RegisterCommand(RemoteAdmin.Instance); - RegisterCommand(Permissions.Instance); } /// diff --git a/EXILED/Exiled.Events/Commands/Reload/RemoteAdmin.cs b/EXILED/Exiled.Events/Commands/Reload/RemoteAdmin.cs index 4777a7e4b0..7c21428b3e 100644 --- a/EXILED/Exiled.Events/Commands/Reload/RemoteAdmin.cs +++ b/EXILED/Exiled.Events/Commands/Reload/RemoteAdmin.cs @@ -18,6 +18,7 @@ namespace Exiled.Events.Commands.Reload /// /// The reload remoteadmin command. /// + [CommandHandler(typeof(Reload))] public class RemoteAdmin : ICommand { /// diff --git a/EXILED/Exiled.Events/Commands/Reload/Translations.cs b/EXILED/Exiled.Events/Commands/Reload/Translations.cs index 68d6f66986..621a7036bb 100644 --- a/EXILED/Exiled.Events/Commands/Reload/Translations.cs +++ b/EXILED/Exiled.Events/Commands/Reload/Translations.cs @@ -20,6 +20,7 @@ namespace Exiled.Events.Commands.Reload /// /// The reload translations command. /// + [CommandHandler(typeof(Reload))] public class Translations : ICommand { ///