From 761d29a5c708ff33ccd57e615f0f938e11ad65f3 Mon Sep 17 00:00:00 2001 From: Tyfon <29051038+tyfon7@users.noreply.github.com> Date: Sat, 4 May 2024 12:58:12 -0700 Subject: [PATCH] Fix binding persisting into unbindable places, fix hoverstate not updating --- Patches/SwapPatch.cs | 75 ++++++++++++++++++++++++++++++++++++++++++-- UIFixes.csproj | 2 +- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/Patches/SwapPatch.cs b/Patches/SwapPatch.cs index 1c0b83d..2ccd687 100644 --- a/Patches/SwapPatch.cs +++ b/Patches/SwapPatch.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using UnityEngine.EventSystems; namespace UIFixes { @@ -26,7 +27,7 @@ namespace UIFixes private static PropertyInfo CanAcceptOperationSucceededProperty; private static PropertyInfo CanAcceptOperationErrorProperty; - private static Type SwapOperationType; // GStruct414 + private static Type SwapOperationType; // GStruct414 private static MethodInfo SwapOperationToCanAcceptOperationOperator; // Source container for the drag - we have to grab this early to check it @@ -36,10 +37,13 @@ namespace UIFixes // Whether we're being called from the "check every slot" loop private static bool InHighlight = false; - // The most recent CheckItemFilter result + // The most recent CheckItemFilter result - needed to differentiate "No room" from incompatible private static string LastCheckItemFilterId; private static bool LastCheckItemFilterResult; + // The most recent GridItemView that was hovered - needed to forcibly update hover state after swap + private static GridItemView LastHoveredGridItemView; + public static void Enable() { GridItemAddressType = PatchConstants.EftTypes.First(t => typeof(ItemAddress).IsAssignableFrom(t) && t.GetProperty("Grid") != null); // GClass2769 @@ -63,6 +67,8 @@ namespace UIFixes new GetHightLightColorPatch().Enable(); new SlotViewCanAcceptPatch().Enable(); new CheckItemFilterPatch().Enable(); + new SwapOperationRaiseEventsPatch().Enable(); + new GridItemViewOnPointerEnterPatch().Enable(); } private static bool InRaid() { @@ -297,6 +303,71 @@ namespace UIFixes } } + // Operations signal their completion status by raising events when they are disposed. + // The Move operation, for example, builds a list of moved items that are no longer valid for binding, and raises unbind events when it completes successfully + // Swap does not do that, because spaghetti, so do it here. + public class SwapOperationRaiseEventsPatch : ModulePatch + { + private static MethodInfo RaiseUnbindItemEvent; + private static Type RaiseUnbindItemEventArgs; // GEventArgs13 + + protected override MethodBase GetTargetMethod() + { + RaiseUnbindItemEvent = AccessTools.Method(typeof(InventoryControllerClass), "RaiseUnbindItemEvent"); + RaiseUnbindItemEventArgs = RaiseUnbindItemEvent.GetParameters()[0].ParameterType; + return AccessTools.Method(SwapOperationType.GenericTypeArguments[0], "RaiseEvents"); // GClass2787 + } + + [PatchPostfix] + private static void Postfix(TraderControllerClass controller, CommandStatus status, Item ___Item, Item ___Item1) + { + InventoryControllerClass inventoryController = controller as InventoryControllerClass; + if (status != CommandStatus.Succeed || inventoryController == null || ___Item == null || ___Item1 == null) + { + return; + } + + if (!inventoryController.IsAtBindablePlace(___Item)) + { + var result = inventoryController.UnbindItemDirect(___Item, false); + if (result.Succeeded) + { + result.Value.RaiseEvents(controller, CommandStatus.Begin); + result.Value.RaiseEvents(controller, CommandStatus.Succeed); + } + } + + if (!inventoryController.IsAtBindablePlace(___Item1)) + { + var result = inventoryController.UnbindItemDirect(___Item1, false); + if (result.Succeeded) + { + result.Value.RaiseEvents(controller, CommandStatus.Begin); + result.Value.RaiseEvents(controller, CommandStatus.Succeed); + } + } + + if (LastHoveredGridItemView != null) + { + LastHoveredGridItemView.OnPointerEnter(new PointerEventData(EventSystem.current)); + } + } + } + + public class GridItemViewOnPointerEnterPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(GridItemView), "OnPointerEnter"); + } + + [PatchPostfix] + private static void Postfix(GridItemView __instance) + { + LastHoveredGridItemView = __instance; + } + } + // Called when dragging an item onto an equipment slot // Handles any kind of ItemAddress as the target destination (aka where the dragged item came from) public class SlotViewCanAcceptPatch : ModulePatch diff --git a/UIFixes.csproj b/UIFixes.csproj index 2ee50e1..17dbf57 100644 --- a/UIFixes.csproj +++ b/UIFixes.csproj @@ -61,6 +61,6 @@ - +