diff --git a/Dalamud/Game/Command/CommandInfo.cs b/Dalamud/Game/Command/CommandInfo.cs index 9b559599a..bc0250a66 100644 --- a/Dalamud/Game/Command/CommandInfo.cs +++ b/Dalamud/Game/Command/CommandInfo.cs @@ -15,7 +15,6 @@ public sealed class CommandInfo public CommandInfo(HandlerDelegate handler) { this.Handler = handler; - this.LoaderAssemblyName = Assembly.GetCallingAssembly()?.GetName()?.Name; } /// diff --git a/Dalamud/Game/Command/CommandManager.cs b/Dalamud/Game/Command/CommandManager.cs index 6a8651b41..218b89676 100644 --- a/Dalamud/Game/Command/CommandManager.cs +++ b/Dalamud/Game/Command/CommandManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -9,22 +8,21 @@ using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Logging.Internal; +using Dalamud.Plugin.Internal.Types; using Dalamud.Plugin.Services; -using Serilog; namespace Dalamud.Game.Command; /// /// This class manages registered in-game slash commands. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 internal sealed class CommandManager : IServiceType, IDisposable, ICommandManager { + private static readonly ModuleLog Log = new("Command"); + private readonly ConcurrentDictionary commandMap = new(); private readonly Regex commandRegexEn = new(@"^The command (?.+) does not exist\.$", RegexOptions.Compiled); private readonly Regex commandRegexJp = new(@"^そのコマンドはありません。: (?.+)$", RegexOptions.Compiled); @@ -84,7 +82,7 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage // => command: 0-12 (12 chars) // => argument: 13-17 (4 chars) // => content.IndexOf(' ') == 12 - command = content.Substring(0, separatorPosition); + command = content[..separatorPosition]; var argStart = separatorPosition + 1; argument = content[argStart..]; @@ -162,3 +160,93 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage } } } + +/// +/// Plugin-scoped version of a AddonLifecycle service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandManager +{ + private static readonly ModuleLog Log = new("Command"); + + [ServiceManager.ServiceDependency] + private readonly CommandManager commandManagerService = Service.Get(); + + private readonly List pluginRegisteredCommands = new(); + private readonly LocalPlugin pluginInfo; + + /// + /// Initializes a new instance of the class. + /// + /// Info for the plugin that requests this service. + public CommandManagerPluginScoped(LocalPlugin localPlugin) + { + this.pluginInfo = localPlugin; + } + + /// + public ReadOnlyDictionary Commands => this.commandManagerService.Commands; + + /// + public void Dispose() + { + foreach (var command in this.pluginRegisteredCommands) + { + this.commandManagerService.RemoveHandler(command); + } + + this.pluginRegisteredCommands.Clear(); + } + + /// + public bool ProcessCommand(string content) + => this.commandManagerService.ProcessCommand(content); + + /// + public void DispatchCommand(string command, string argument, CommandInfo info) + => this.commandManagerService.DispatchCommand(command, argument, info); + + /// + public bool AddHandler(string command, CommandInfo info) + { + if (!this.pluginRegisteredCommands.Contains(command)) + { + info.LoaderAssemblyName = this.pluginInfo.InternalName; + if (this.commandManagerService.AddHandler(command, info)) + { + this.pluginRegisteredCommands.Add(command); + return true; + } + } + else + { + Log.Error($"Command {command} is already registered."); + } + + return false; + } + + /// + public bool RemoveHandler(string command) + { + if (this.pluginRegisteredCommands.Contains(command)) + { + if (this.commandManagerService.RemoveHandler(command)) + { + this.pluginRegisteredCommands.Remove(command); + return true; + } + } + else + { + Log.Error($"Command {command} not found."); + } + + return false; + } +} diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index e5d3c147b..dcbdced28 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -15,7 +15,6 @@ using Dalamud.Game.Command; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; using Dalamud.Interface.Internal.Notifications; -using Dalamud.Interface.Style; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; @@ -2227,8 +2226,7 @@ internal class PluginInstallerWindow : Window, IDisposable { var commands = commandManager.Commands .Where(cInfo => - cInfo.Value != null && - cInfo.Value.ShowInHelp && + cInfo.Value is { ShowInHelp: true } && cInfo.Value.LoaderAssemblyName == plugin.Manifest.InternalName) .ToArray();