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
{
///