feat(ui): notify on failed tell via RaptureLogModule hook
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Interface.ImGuiNotification;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||
using HellionChat._Helpers;
|
||||
using HellionChat.Resources;
|
||||
using HellionChat.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace HellionChat.Integrations;
|
||||
|
||||
// UI-2: a minimal, failed-tell-specific game hook. A locale-robust "tell
|
||||
// failed" signal is not reachable over the processed message stream (Message
|
||||
// carries no LogMessage row id, ChatCode 60 is too broad). This hooks the one
|
||||
// ShowLogMessageString overload and toasts on a pinned id set. It is NOT the
|
||||
// broad ad-block hook layer — that stays v1.5.6.
|
||||
internal sealed class FailedTellNotifier : IDisposable
|
||||
{
|
||||
private readonly ILogger<FailedTellNotifier> _logger;
|
||||
private readonly Hook<RaptureLogModule.Delegates.ShowLogMessageString>? _hook;
|
||||
|
||||
public unsafe FailedTellNotifier(ILogger<FailedTellNotifier> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
|
||||
// Creating/enabling a hook is safe off the framework thread (the
|
||||
// ctor runs during host startup on the framework thread,
|
||||
// eager-resolved via FailedTellNotifierInitHostedService).
|
||||
_hook = Plugin.GameInteropProvider
|
||||
.HookFromAddress<RaptureLogModule.Delegates.ShowLogMessageString>(
|
||||
RaptureLogModule.MemberFunctionPointers.ShowLogMessageString,
|
||||
ShowLogMessageStringDetour);
|
||||
_hook.Enable();
|
||||
}
|
||||
|
||||
private unsafe void ShowLogMessageStringDetour(
|
||||
RaptureLogModule* module, uint logMessageId, Utf8String* value)
|
||||
{
|
||||
try
|
||||
{
|
||||
// DISCOVERY (Task 2 Step 9): while the id set is empty, log every
|
||||
// call so a failed tell can be triggered in-game and its id read.
|
||||
// Remove this block once FailedTellLogMessageIds is pinned.
|
||||
_logger.LogInformation(
|
||||
"ShowLogMessageString id={Id} value={Value}",
|
||||
logMessageId,
|
||||
value is null ? "<null>" : value->ToString());
|
||||
|
||||
if (FailedTellMatcher.ShouldNotify(
|
||||
logMessageId, Plugin.Config.NotifyFailedTell,
|
||||
FailedTellMatcher.FailedTellLogMessageIds))
|
||||
{
|
||||
var recipient = value is null ? string.Empty : value->ToString();
|
||||
var content = string.IsNullOrEmpty(recipient)
|
||||
? HellionStrings.FailedTell_Notification_Generic
|
||||
: string.Format(HellionStrings.FailedTell_Notification_Named, recipient);
|
||||
WrapperUtil.AddNotification(content, NotificationType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "FailedTellNotifier detour threw");
|
||||
}
|
||||
|
||||
_hook!.Original(module, logMessageId, value);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_hook?.Disable();
|
||||
_hook?.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user