refactor(commands): cache slash-command wrappers in private fields

TearDownCommands attached the same instance via re-Register with identical
args, which was functionally a no-op but masked a latent bug if Description
or ShowInHelp ever diverged between Setup and Teardown. Hold the wrapper
instances as nullable fields so Teardown can detach the live registration
directly. Mirrors the cached-wrapper pattern in ChatLogWindow.
This commit is contained in:
2026-05-15 20:18:41 +02:00
parent 7c9b90c767
commit fbbbeebade
+50 -26
View File
@@ -123,6 +123,15 @@ public sealed class Plugin : IAsyncDalamudPlugin
// isolation. Wired immediately after Dalamud injects Log. // isolation. Wired immediately after Dalamud injects Log.
internal static IPluginLogProxy LogProxy { get; private set; } = null!; internal static IPluginLogProxy LogProxy { get; private set; } = null!;
// Wrapper cached so TearDown can detach the live instance instead of
// re-registering with identical args (v1.4.9 ISSUE-1 cleanup).
private CommandWrapper? _hellionSettingsCmd;
private CommandWrapper? _hellionViewCmd;
private CommandWrapper? _hellionDebuggerCmd;
#if DEBUG
private CommandWrapper? _hellionSeStringCmd;
#endif
// Idempotency guard — Dalamud may fire DisposeAsync twice in a reload race. // Idempotency guard — Dalamud may fire DisposeAsync twice in a reload race.
private int _disposeStarted; private int _disposeStarted;
@@ -699,21 +708,25 @@ public sealed class Plugin : IAsyncDalamudPlugin
{ {
// ChatLogWindow.cs:128 already registers /hellion (ToggleChat). The // ChatLogWindow.cs:128 already registers /hellion (ToggleChat). The
// description-arg here keeps the Dalamud help list populated. // description-arg here keeps the Dalamud help list populated.
Commands.Register("/hellion", "Perform various actions with Hellion Chat.").Execute += _hellionSettingsCmd = Commands.Register(
OnHellionSettingsCommand; "/hellion",
Commands "Perform various actions with Hellion Chat."
.Register( );
"/hellionView", _hellionSettingsCmd.Execute += OnHellionSettingsCommand;
"Get access to your message history, with simple filter options.",
true _hellionViewCmd = Commands.Register(
) "/hellionView",
.Execute += OnHellionViewCommand; "Get access to your message history, with simple filter options.",
Commands.Register("/hellionDebugger", showInHelp: false).Execute += true
OnHellionDebuggerCommand; );
_hellionViewCmd.Execute += OnHellionViewCommand;
_hellionDebuggerCmd = Commands.Register("/hellionDebugger", showInHelp: false);
_hellionDebuggerCmd.Execute += OnHellionDebuggerCommand;
#if DEBUG #if DEBUG
// SeStringDebugger.cs lives under #if DEBUG too; keep this out of release builds. // SeStringDebugger.cs lives under #if DEBUG too; keep this out of release builds.
Commands.Register("/hellionSeString", showInHelp: false).Execute += _hellionSeStringCmd = Commands.Register("/hellionSeString", showInHelp: false);
OnHellionSeStringCommand; _hellionSeStringCmd.Execute += OnHellionSeStringCommand;
#endif #endif
// Plugin-Manager "Settings" button. Was in Settings.cs:67 pre-v1.4.9. // Plugin-Manager "Settings" button. Was in Settings.cs:67 pre-v1.4.9.
@@ -729,20 +742,31 @@ public sealed class Plugin : IAsyncDalamudPlugin
Interface.UiBuilder.OpenMainUi -= OnOpenMainUi; Interface.UiBuilder.OpenMainUi -= OnOpenMainUi;
Interface.UiBuilder.OpenConfigUi -= OnOpenConfigUi; Interface.UiBuilder.OpenConfigUi -= OnOpenConfigUi;
Commands.Register("/hellion", "Perform various actions with Hellion Chat.").Execute -= // Null-tolerant detaches: TearDownCommands can run from the LoadAsync
OnHellionSettingsCommand; // failure path (Plugin.cs CaptureFailure) before SetupCommands finished.
Commands if (_hellionSettingsCmd is not null)
.Register( {
"/hellionView", _hellionSettingsCmd.Execute -= OnHellionSettingsCommand;
"Get access to your message history, with simple filter options.", _hellionSettingsCmd = null;
true }
)
.Execute -= OnHellionViewCommand; if (_hellionViewCmd is not null)
Commands.Register("/hellionDebugger", showInHelp: false).Execute -= {
OnHellionDebuggerCommand; _hellionViewCmd.Execute -= OnHellionViewCommand;
_hellionViewCmd = null;
}
if (_hellionDebuggerCmd is not null)
{
_hellionDebuggerCmd.Execute -= OnHellionDebuggerCommand;
_hellionDebuggerCmd = null;
}
#if DEBUG #if DEBUG
Commands.Register("/hellionSeString", showInHelp: false).Execute -= if (_hellionSeStringCmd is not null)
OnHellionSeStringCommand; {
_hellionSeStringCmd.Execute -= OnHellionSeStringCommand;
_hellionSeStringCmd = null;
}
#endif #endif
} }