From aa450a71995cee42eabca65232494b450224fc1d Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sun, 17 Nov 2024 00:08:23 +0100 Subject: [PATCH] Revert ItemHover/ItemOut hook removal (#2093) * Revert ItemHover/ItemOut hook removal * Update delegates for HandleItemHover hooks * Fix HandleItemHoverDetour spam * Update GameGui signature comments * Use int in HandleItemOutDetour like the game does * Hook AgentItemDetail vfuncs * Add missing hook Dispose calls --------- Co-authored-by: KazWolfe --- Dalamud/Game/Gui/GameGui.cs | 74 ++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs index 54f4253cd..aecbb7201 100644 --- a/Dalamud/Game/Gui/GameGui.cs +++ b/Dalamud/Game/Gui/GameGui.cs @@ -32,12 +32,11 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui { private static readonly ModuleLog Log = new("GameGui"); - [ServiceManager.ServiceDependency] - private readonly Framework framework = Service.Get(); - private readonly GameGuiAddressResolver address; private readonly Hook setGlobalBgmHook; + private readonly Hook handleItemHoverHook; + private readonly Hook handleItemOutHook; private readonly Hook handleActionHoverHook; private readonly Hook handleActionOutHook; private readonly Hook handleImmHook; @@ -57,6 +56,9 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui this.setGlobalBgmHook = Hook.FromAddress(this.address.SetGlobalBgm, this.HandleSetGlobalBgmDetour); + this.handleItemHoverHook = Hook.FromAddress((nint)AgentItemDetail.StaticVirtualTablePointer->Update, this.HandleItemHoverDetour); + this.handleItemOutHook = Hook.FromAddress((nint)AgentItemDetail.StaticVirtualTablePointer->ReceiveEvent, this.HandleItemOutDetour); + this.handleActionHoverHook = Hook.FromAddress(AgentActionDetail.Addresses.HandleActionHover.Value, this.HandleActionHoverDetour); this.handleActionOutHook = Hook.FromAddress((nint)AgentActionDetail.StaticVirtualTablePointer->ReceiveEvent, this.HandleActionOutDetour); @@ -67,13 +69,13 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui this.utf8StringFromSequenceHook = Hook.FromAddress(Utf8String.Addresses.Ctor_FromSequence.Value, this.Utf8StringFromSequenceDetour); this.setGlobalBgmHook.Enable(); + this.handleItemHoverHook.Enable(); + this.handleItemOutHook.Enable(); this.handleImmHook.Enable(); this.setUiVisibilityHook.Enable(); this.handleActionHoverHook.Enable(); this.handleActionOutHook.Enable(); this.utf8StringFromSequenceHook.Enable(); - - this.framework.Update += this.FrameworkUpdate; } // Hooked delegates @@ -252,9 +254,9 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui /// void IInternalDisposableService.DisposeService() { - this.framework.Update -= this.FrameworkUpdate; - this.setGlobalBgmHook.Dispose(); + this.handleItemHoverHook.Dispose(); + this.handleItemOutHook.Dispose(); this.handleImmHook.Dispose(); this.setUiVisibilityHook.Dispose(); this.handleActionHoverHook.Dispose(); @@ -300,6 +302,46 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui return retVal; } + private void HandleItemHoverDetour(AgentItemDetail* thisPtr, uint frameCount) + { + this.handleItemHoverHook.Original(thisPtr, frameCount); + + if (!thisPtr->IsAgentActive()) + return; + + var itemId = (ulong)thisPtr->ItemId; + if (this.HoveredItem == itemId) + return; + + this.HoveredItem = itemId; + this.HoveredItemChanged?.InvokeSafely(this, itemId); + + Log.Verbose($"HoveredItem changed: {itemId}"); + } + + private AtkValue* HandleItemOutDetour(AgentItemDetail* thisPtr, AtkValue* returnValue, AtkValue* values, uint valueCount, ulong eventKind) + { + var ret = this.handleItemOutHook.Original(thisPtr, returnValue, values, valueCount, eventKind); + + if (values != null && valueCount == 1 && values->Int == -1) + { + this.HoveredItem = 0; + + try + { + this.HoveredItemChanged?.Invoke(this, 0); + } + catch (Exception e) + { + Log.Error(e, "Could not dispatch HoveredItemChanged event."); + } + + Log.Verbose("HoveredItem changed: 0"); + } + + return ret; + } + private void HandleActionHoverDetour(AgentActionDetail* hoverState, ActionKind actionKind, uint actionId, int a4, byte a5) { this.handleActionHoverHook.Original(hoverState, actionKind, actionId, a4, a5); @@ -371,24 +413,6 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui return thisPtr; // this function shouldn't need to return but the original asm moves this into rax before returning so be safe? } - - private unsafe void FrameworkUpdate(IFramework framework) - { - var agentItemDetail = AgentItemDetail.Instance(); - if (agentItemDetail != null) - { - var itemId = agentItemDetail->ItemId; - - if (this.HoveredItem != itemId) - { - Log.Verbose($"HoveredItem changed: {itemId}"); - - this.HoveredItem = itemId; - - this.HoveredItemChanged?.InvokeSafely(this, itemId); - } - } - } } ///