From 399c80d4058e8c089585f14ba7adf9aa1b6732c5 Mon Sep 17 00:00:00 2001 From: Zeffuro Date: Mon, 29 Dec 2025 10:27:14 +0100 Subject: [PATCH] Item linking, import/export fixed, stats --- AetherBags/Commands/CommandHandler.cs | 9 ++++++- AetherBags/Configuration/GeneralSettings.cs | 1 + AetherBags/Helpers/ImportExportResetHelper.cs | 8 +----- AetherBags/Inventory/InventoryState.cs | 26 +++++++++++++++++++ AetherBags/Inventory/InventoryStats.cs | 12 +++++++++ .../General/FunctionalConfigurationNode.cs | 13 ++++++++++ .../Nodes/Inventory/InventoryDragDropNode.cs | 11 +++++++- 7 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 AetherBags/Inventory/InventoryStats.cs diff --git a/AetherBags/Commands/CommandHandler.cs b/AetherBags/Commands/CommandHandler.cs index 7c97136..3d36d4e 100644 --- a/AetherBags/Commands/CommandHandler.cs +++ b/AetherBags/Commands/CommandHandler.cs @@ -1,5 +1,6 @@ using System; using AetherBags.Helpers; +using AetherBags.Inventory; using Dalamud.Game.Command; namespace AetherBags.Commands; @@ -74,7 +75,7 @@ public class CommandHandler : IDisposable break; case "import": - ImportExportResetHelper.TryImportConfigFromClipboard(System.Config); + ImportExportResetHelper.TryImportConfigFromClipboard(); System.AddonInventoryWindow.ManualInventoryRefresh(); break; @@ -83,6 +84,12 @@ public class CommandHandler : IDisposable System.AddonInventoryWindow.ManualInventoryRefresh(); break; + case "count": + case "stats": + var stats = InventoryState.GetInventoryStats(); + PrintChat($"{stats.UsedSlots}/{stats.TotalSlots} slots used ({stats.UsagePercent:F0}%) | {stats.TotalItems} unique items | {stats.CategoryCount} categories"); + break; + case "help": case "?": PrintHelp(); diff --git a/AetherBags/Configuration/GeneralSettings.cs b/AetherBags/Configuration/GeneralSettings.cs index 3215ba5..72296a8 100644 --- a/AetherBags/Configuration/GeneralSettings.cs +++ b/AetherBags/Configuration/GeneralSettings.cs @@ -14,6 +14,7 @@ public class GeneralSettings public bool OpenWithGameInventory { get; set; } = true; public bool HideGameInventory { get; set; } = false; public bool ShowCategoryItemCount { get; set; } = false; + public bool LinkItemEnabled { get; set; } = false; } public enum InventoryStackMode : byte diff --git a/AetherBags/Helpers/ImportExportResetHelper.cs b/AetherBags/Helpers/ImportExportResetHelper.cs index b667f58..1b7a2a2 100644 --- a/AetherBags/Helpers/ImportExportResetHelper.cs +++ b/AetherBags/Helpers/ImportExportResetHelper.cs @@ -8,11 +8,8 @@ using Dalamud.Interface.ImGuiNotification; namespace AetherBags.Helpers; public abstract class ImportExportResetHelper { - public static void TryImportConfigFromClipboard(SystemConfiguration currentOverlayConfig) + public static void TryImportConfigFromClipboard() { - if (!Services.KeyState[VirtualKey.SHIFT]) - return; - var clipboard = ImGui.GetClipboardText(); var notification = new Notification { Content = "Configuration imported from clipboard.", Type = NotificationType.Success }; @@ -66,9 +63,6 @@ public abstract class ImportExportResetHelper { public static void TryImportSortaKindaFromClipboard(bool replaceExisting) { - //if (!Services.KeyState[VirtualKey.SHIFT]) - // return; - var notification = new Notification { Content = "SortaKinda categories imported.", Type = NotificationType.Success }; if (!SortaKindaImportExport.TryImportFromClipboard(System.Config, replaceExisting, out var error)) diff --git a/AetherBags/Inventory/InventoryState.cs b/AetherBags/Inventory/InventoryState.cs index 1fc3982..0d354ca 100644 --- a/AetherBags/Inventory/InventoryState.cs +++ b/AetherBags/Inventory/InventoryState.cs @@ -97,6 +97,32 @@ public static unsafe class InventoryState invert); } + public static InventoryStats GetInventoryStats() + { + int totalItems = ItemInfoByKey.Count; + int totalQuantity = 0; + + foreach (var kvp in ItemInfoByKey) + { + totalQuantity += kvp.Value.ItemCount; + } + + uint emptySlots = InventoryManager.Instance()->GetEmptySlotsInBag(); + const int totalSlots = 140; + + var categories = GetInventoryItemCategories(string.Empty); + int categoryCount = categories.Count; + + return new InventoryStats + { + TotalItems = totalItems, + TotalQuantity = totalQuantity, + EmptySlots = (int)emptySlots, + TotalSlots = totalSlots, + CategoryCount = categoryCount, + }; + } + public static string GetEmptyItemSlotsString() => InventoryScanner.GetEmptyItemSlotsString(); diff --git a/AetherBags/Inventory/InventoryStats.cs b/AetherBags/Inventory/InventoryStats.cs new file mode 100644 index 0000000..4f9a997 --- /dev/null +++ b/AetherBags/Inventory/InventoryStats.cs @@ -0,0 +1,12 @@ +namespace AetherBags.Inventory; + +public readonly struct InventoryStats +{ + public int TotalItems { get; init; } + public int TotalQuantity { get; init; } + public int EmptySlots { get; init; } + public int TotalSlots { get; init; } + public int CategoryCount { get; init; } + public int UsedSlots => TotalSlots - EmptySlots; + public float UsagePercent => TotalSlots > 0 ? (float)UsedSlots / TotalSlots * 100f : 0f; +} \ No newline at end of file diff --git a/AetherBags/Nodes/Configuration/General/FunctionalConfigurationNode.cs b/AetherBags/Nodes/Configuration/General/FunctionalConfigurationNode.cs index 936548a..19fc24f 100644 --- a/AetherBags/Nodes/Configuration/General/FunctionalConfigurationNode.cs +++ b/AetherBags/Nodes/Configuration/General/FunctionalConfigurationNode.cs @@ -55,6 +55,19 @@ internal sealed class FunctionalConfigurationNode : TabbedVerticalListNode AddNode(_hideDefaultBagsCheckboxNode); SubtractTab(1); + var linkItemCheckBox = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Allow item linking with Shift+Click", + IsChecked = config.LinkItemEnabled, + OnClick = isChecked => + { + config.LinkItemEnabled = isChecked; + } + }; + AddNode(linkItemCheckBox); + _stackDropDown = new LabeledDropdownNode { Size = new Vector2(300, 20), diff --git a/AetherBags/Nodes/Inventory/InventoryDragDropNode.cs b/AetherBags/Nodes/Inventory/InventoryDragDropNode.cs index 29b042a..a2435fb 100644 --- a/AetherBags/Nodes/Inventory/InventoryDragDropNode.cs +++ b/AetherBags/Nodes/Inventory/InventoryDragDropNode.cs @@ -1,5 +1,6 @@ using System.Numerics; using AetherBags.Inventory; +using Dalamud.Game.ClientState.Keys; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Component.GUI; @@ -41,13 +42,21 @@ public class InventoryDragDropNode : DragDropFixedNode private unsafe void OnItemMouseDown(AtkEventListener* thisPtr, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData) { InventoryItem item = ItemInfo.Item; + if (Services.KeyState[VirtualKey.SHIFT] && atkEventData->IsLeftClick && System.Config.General.LinkItemEnabled) + { + AgentChatLog.Instance()->LinkItem(item.ItemId); + return; + } + if (!atkEventData->IsRightClick) return; AgentInventoryContext* context = AgentInventoryContext.Instance(); context->OpenForItemSlot(item.Container, item.Slot, 0, context->AddonId); } - private unsafe void OnItemClicked(AtkEventListener* thisPtr, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData) { + private unsafe void OnItemClicked(AtkEventListener* thisPtr, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData) + { + if (Services.KeyState[VirtualKey.SHIFT] && System.Config.General.LinkItemEnabled) return; InventoryItem item = ItemInfo.Item; if (!atkEventData->IsLeftClick) return; item.UseItem();