/// <summary>
        /// Registers the specified command
        /// </summary>
        /// <param name="command"></param>
        /// <param name="plugin"></param>
        /// <param name="callback"></param>
        public void RegisterCommand(string command, Plugin plugin, CommandCallback callback)
        {
            // Convert command to lowercase and remove whitespace
            command = command.ToLowerInvariant().Trim();

            // Setup console command name
            string[] split    = command.Split('.');
            string   parent   = split.Length >= 2 ? split[0].Trim() : "global";
            string   name     = split.Length >= 2 ? string.Join(".", split.Skip(1).ToArray()) : split[0].Trim();
            string   fullName = $"{parent}.{name}";

            if (parent == "global")
            {
                command = name;
            }

            // Setup a new Covalence command
            RegisteredCommand newCommand = new RegisteredCommand(plugin, command, callback);

            // Check if the command can be overridden
            if (!CanOverrideCommand(command))
            {
                throw new CommandAlreadyExistsException(command);
            }

            // Check if command already exists in another Covalence plugin
            RegisteredCommand cmd;

            if (registeredCommands.TryGetValue(command, out cmd))
            {
                if (cmd.OriginalCallback != null)
                {
                    newCommand.OriginalCallback = cmd.OriginalCallback;
                }

                string previousPluginName = cmd.Source?.Name ?? "an unknown plugin";
                string newPluginName      = plugin?.Name ?? "An unknown plugin";
                string message            = $"{newPluginName} has replaced the '{command}' command previously registered by {previousPluginName}";
                Interface.Oxide.LogWarning(message);

                ConsoleSystem.Index.Server.Dict.Remove(fullName);
                if (parent == "global")
                {
                    ConsoleSystem.Index.Server.GlobalDict.Remove(name);
                }

                ConsoleSystem.Index.All = ConsoleSystem.Index.Server.Dict.Values.ToArray();
            }

            // Check if command already exists in a Rust plugin as a chat command
            Command.ChatCommand chatCommand;
            if (cmdlib.chatCommands.TryGetValue(command, out chatCommand))
            {
                string previousPluginName = chatCommand.Plugin?.Name ?? "an unknown plugin";
                string newPluginName      = plugin?.Name ?? "An unknown plugin";
                string message            = $"{newPluginName} has replaced the '{command}' chat command previously registered by {previousPluginName}";
                Interface.Oxide.LogWarning(message);

                cmdlib.chatCommands.Remove(command);
            }

            // Check if command already exists in a Rust plugin as a console command
            Command.ConsoleCommand consoleCommand;
            if (cmdlib.consoleCommands.TryGetValue(fullName, out consoleCommand))
            {
                if (consoleCommand.OriginalCallback != null)
                {
                    newCommand.OriginalCallback = consoleCommand.OriginalCallback;
                }

                string previousPluginName = consoleCommand.Callback.Plugin?.Name ?? "an unknown plugin";
                string newPluginName      = plugin?.Name ?? "An unknown plugin";
                string message            = $"{newPluginName} has replaced the '{fullName}' console command previously registered by {previousPluginName}";
                Interface.Oxide.LogWarning(message);

                ConsoleSystem.Index.Server.Dict.Remove(consoleCommand.RustCommand.FullName);
                if (parent == "global")
                {
                    ConsoleSystem.Index.Server.GlobalDict.Remove(consoleCommand.RustCommand.Name);
                }

                ConsoleSystem.Index.All = ConsoleSystem.Index.Server.Dict.Values.ToArray();
                cmdlib.consoleCommands.Remove(consoleCommand.RustCommand.FullName);
            }

            // Check if command is a vanilla Rust command
            ConsoleSystem.Command rustCommand;
            if (ConsoleSystem.Index.Server.Dict.TryGetValue(fullName, out rustCommand))
            {
                if (rustCommand.Variable)
                {
                    string newPluginName = plugin?.Name ?? "An unknown plugin";
                    Interface.Oxide.LogError($"{newPluginName} tried to register the {fullName} console variable as a command!");
                    return;
                }
                newCommand.OriginalCallback    = rustCommand.Call;
                newCommand.OriginalRustCommand = rustCommand;
            }

            // Create a new Rust console command
            newCommand.RustCommand = new ConsoleSystem.Command
            {
                Name        = name,
                Parent      = parent,
                FullName    = command,
                ServerUser  = true,
                ServerAdmin = true,
                Client      = true,
                ClientInfo  = false,
                Variable    = false,
                Call        = arg =>
                {
                    if (arg == null)
                    {
                        return;
                    }

                    BasePlayer player = arg.Player();
                    if (arg.Connection != null && player != null)
                    {
                        RustPlayer iplayer = player.IPlayer as RustPlayer;
                        if (iplayer != null)
                        {
                            iplayer.LastCommand = CommandType.Console;
                            callback(iplayer, command, ExtractArgs(arg));
                        }
                    }
                    else if (arg.Connection == null)
                    {
                        consolePlayer.LastCommand = CommandType.Console;
                        callback(consolePlayer, command, ExtractArgs(arg));
                    }
                }
            };

            // Register the command as a console command
            ConsoleSystem.Index.Server.Dict[fullName] = newCommand.RustCommand;
            if (parent == "global")
            {
                ConsoleSystem.Index.Server.GlobalDict[name] = newCommand.RustCommand;
            }

            ConsoleSystem.Index.All = ConsoleSystem.Index.Server.Dict.Values.ToArray();

            // Register the command as a chat command
            registeredCommands[command] = newCommand;
        }
        public void RegisterCommand(string command, Plugin plugin, CommandCallback callback)
        {
            RustCommandSystem.RegisteredCommand registeredCommand;
            Command.ChatCommand    chatCommand;
            Command.ConsoleCommand consoleCommand;
            ConsoleSystem.Command  command1;
            object name;
            object obj;
            object name1;
            object obj1;
            object name2;
            object obj2;
            object name3;
            string str = command;

            str = str.ToLowerInvariant().Trim();
            string[] strArray     = str.Split(new Char[] { '.' });
            string   str1         = ((int)strArray.Length >= 2 ? strArray[0].Trim() : "global");
            string   rustCommand  = ((int)strArray.Length >= 2 ? String.Join(".", strArray.Skip <string>(1).ToArray <string>()) : strArray[0].Trim());
            string   rustCommand1 = String.Concat(str1, ".", rustCommand);

            if (str1 == "global")
            {
                str = rustCommand;
            }
            RustCommandSystem.RegisteredCommand originalCallback = new RustCommandSystem.RegisteredCommand(plugin, str, callback);
            if (!this.CanOverrideCommand(str))
            {
                throw new CommandAlreadyExistsException(str);
            }
            if (this.registeredCommands.TryGetValue(str, out registeredCommand))
            {
                if (registeredCommand.OriginalCallback != null)
                {
                    originalCallback.OriginalCallback = registeredCommand.OriginalCallback;
                }
                Plugin source = registeredCommand.Source;
                if (source != null)
                {
                    obj2 = source.Name;
                }
                else
                {
                    obj2 = null;
                }
                if (obj2 == null)
                {
                    obj2 = "an unknown plugin";
                }
                string str2 = obj2;
                if (plugin != null)
                {
                    name3 = plugin.Name;
                }
                else
                {
                    name3 = null;
                }
                if (name3 == null)
                {
                    name3 = "An unknown plugin";
                }
                string str3 = name3;
                string str4 = String.Concat(new String[] { str3, " has replaced the '", str, "' command previously registered by ", str2 });
                Interface.Oxide.LogWarning(str4, Array.Empty <object>());
                ConsoleSystem.Index.Server.Dict.Remove(rustCommand1);
                if (str1 == "global")
                {
                    ConsoleSystem.Index.Server.GlobalDict.Remove(rustCommand);
                }
                ConsoleSystem.Index.All = ConsoleSystem.Index.Server.Dict.Values.ToArray <ConsoleSystem.Command>();
            }
            if (this.cmdlib.chatCommands.TryGetValue(str, out chatCommand))
            {
                Plugin plugin1 = chatCommand.Plugin;
                if (plugin1 != null)
                {
                    obj1 = plugin1.Name;
                }
                else
                {
                    obj1 = null;
                }
                if (obj1 == null)
                {
                    obj1 = "an unknown plugin";
                }
                string str5 = obj1;
                if (plugin != null)
                {
                    name2 = plugin.Name;
                }
                else
                {
                    name2 = null;
                }
                if (name2 == null)
                {
                    name2 = "An unknown plugin";
                }
                string str6 = name2;
                string str7 = String.Concat(new String[] { str6, " has replaced the '", str, "' chat command previously registered by ", str5 });
                Interface.Oxide.LogWarning(str7, Array.Empty <object>());
                this.cmdlib.chatCommands.Remove(str);
            }
            if (this.cmdlib.consoleCommands.TryGetValue(rustCommand1, out consoleCommand))
            {
                if (consoleCommand.OriginalCallback != null)
                {
                    originalCallback.OriginalCallback = consoleCommand.OriginalCallback;
                }
                Plugin plugin2 = consoleCommand.Callback.Plugin;
                if (plugin2 != null)
                {
                    obj = plugin2.Name;
                }
                else
                {
                    obj = null;
                }
                if (obj == null)
                {
                    obj = "an unknown plugin";
                }
                string str8 = obj;
                if (plugin != null)
                {
                    name1 = plugin.Name;
                }
                else
                {
                    name1 = null;
                }
                if (name1 == null)
                {
                    name1 = "An unknown plugin";
                }
                string str9  = name1;
                string str10 = String.Concat(new String[] { str9, " has replaced the '", rustCommand1, "' console command previously registered by ", str8 });
                Interface.Oxide.LogWarning(str10, Array.Empty <object>());
                ConsoleSystem.Index.Server.Dict.Remove(consoleCommand.RustCommand.FullName);
                if (str1 == "global")
                {
                    ConsoleSystem.Index.Server.GlobalDict.Remove(consoleCommand.RustCommand.Name);
                }
                ConsoleSystem.Index.All = ConsoleSystem.Index.Server.Dict.Values.ToArray <ConsoleSystem.Command>();
                this.cmdlib.consoleCommands.Remove(consoleCommand.RustCommand.FullName);
            }
            if (ConsoleSystem.Index.Server.Dict.TryGetValue(rustCommand1, out command1))
            {
                if (command1.Variable)
                {
                    if (plugin != null)
                    {
                        name = plugin.Name;
                    }
                    else
                    {
                        name = null;
                    }
                    if (name == null)
                    {
                        name = "An unknown plugin";
                    }
                    string str11 = name;
                    Interface.Oxide.LogError(String.Concat(str11, " tried to register the ", rustCommand1, " console variable as a command!"), Array.Empty <object>());
                    return;
                }
                originalCallback.OriginalCallback    = command1.Call;
                originalCallback.OriginalRustCommand = command1;
            }
            originalCallback.RustCommand = new ConsoleSystem.Command()
            {
                Name        = rustCommand,
                Parent      = str1,
                FullName    = str,
                ServerUser  = true,
                ServerAdmin = true,
                Client      = true,
                ClientInfo  = false,
                Variable    = false,
                Call        = (ConsoleSystem.Arg arg) => {
                    if (arg == null)
                    {
                        return;
                    }
                    BasePlayer basePlayer = arg.Player();
                    if (arg.Connection != null && basePlayer != null)
                    {
                        RustPlayer player = basePlayer.IPlayer as RustPlayer;
                        if (player != null)
                        {
                            player.LastCommand = CommandType.Console;
                            callback(player, str, RustCommandSystem.ExtractArgs(arg));
                            return;
                        }
                    }
                    else if (arg.Connection == null)
                    {
                        this.consolePlayer.LastCommand = CommandType.Console;
                        callback(this.consolePlayer, str, RustCommandSystem.ExtractArgs(arg));
                    }
                }
            };
            ConsoleSystem.Index.Server.Dict[rustCommand1] = originalCallback.RustCommand;
            if (str1 == "global")
            {
                ConsoleSystem.Index.Server.GlobalDict[rustCommand] = originalCallback.RustCommand;
            }
            ConsoleSystem.Index.All      = ConsoleSystem.Index.Server.Dict.Values.ToArray <ConsoleSystem.Command>();
            this.registeredCommands[str] = originalCallback;
        }