diff --git a/Patches/SortPatches.cs b/Patches/SortPatches.cs index 34b16f9..d9ed424 100644 --- a/Patches/SortPatches.cs +++ b/Patches/SortPatches.cs @@ -1,8 +1,14 @@ -using System.Reflection; +using Comfort.Common; +using Diz.LanguageExtensions; +using EFT.InventoryLogic; using EFT.UI; using EFT.UI.DragAndDrop; using HarmonyLib; using SPT.Reflection.Patching; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; using UnityEngine; namespace UIFixes; @@ -13,6 +19,7 @@ public static class SortPatches { new SortPatch().Enable(); new ShiftClickPatch().Enable(); + new StackFirstPatch().Enable(); } public class SortPatch : ModulePatch @@ -54,4 +61,83 @@ public static class SortPatches return false; } } + + public class StackFirstPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(GridSortPanel), nameof(GridSortPanel.method_1)); + } + + // Normally this method just calls method_2 and eats the exceptions + // This sidesteps method_2 and calls my Sort, to do stacking + [PatchPrefix] + public static bool Prefix(GridSortPanel __instance, LootItemClass ___lootItemClass, InventoryControllerClass ___inventoryControllerClass) + { + Sort(__instance, ___lootItemClass, ___inventoryControllerClass).HandleExceptions(); + return false; + } + + private static async Task Sort(GridSortPanel instance, LootItemClass lootItem, InventoryControllerClass inventoryController) + { + instance.method_3(true); + + Error error = await StackAll(lootItem, inventoryController); + + if (error == null) + { + GStruct414 sortOperation = InteractionsHandlerClass.Sort(lootItem, inventoryController, false); + if (sortOperation.Succeeded) + { + IResult result = await inventoryController.TryRunNetworkTransaction(sortOperation); + sortOperation.Value.RaiseEvents(inventoryController, result.Succeed ? CommandStatus.Succeed : CommandStatus.Failed); + } + else + { + error = sortOperation.Error; + } + } + + if (error is InventoryError inventoryError) + { + NotificationManagerClass.DisplayWarningNotification(inventoryError.GetLocalizedDescription()); + } + + instance.method_3(false); + } + + private static async Task StackAll(LootItemClass lootItem, InventoryControllerClass inventoryController) + { + Error error = null; + List> transferOrMergeOperations = []; + var mergeableItems = lootItem.Grids.SelectMany(g => g.Items) + .OfType() + .Where(i => i.StackObjectsCount < i.StackMaxSize) + .ToArray(); + + foreach (Item item in mergeableItems) + { + // Check the item hasn't been merged to full or away yet + if (item.StackObjectsCount == 0 || item.StackObjectsCount == item.StackMaxSize) + { + continue; + } + + if (InteractionsHandlerClass.smethod_0(lootItem.Grids, item, out GClass2751 targetItem, 1)) + { + var operation = InteractionsHandlerClass.TransferOrMerge(item, targetItem, inventoryController, true); + if (operation.Succeeded) + { + await inventoryController.TryRunNetworkTransaction(operation); + } + else + { + error = operation.Error; + } + } + } + + return error; + } + } } \ No newline at end of file