diff --git a/Dalamud/Game/Inventory/GameInventory.cs b/Dalamud/Game/Inventory/GameInventory.cs index c2603f1bf..4ee66ffaf 100644 --- a/Dalamud/Game/Inventory/GameInventory.cs +++ b/Dalamud/Game/Inventory/GameInventory.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; -using System.Runtime.InteropServices; +using Dalamud.Configuration.Internal; +using Dalamud.Game.Inventory.InventoryChangeArgsTypes; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Logging.Internal; @@ -8,7 +9,9 @@ using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game; -namespace Dalamud.Game.GameInventory; +using Serilog.Events; + +namespace Dalamud.Game.Inventory; /// /// This class provides events for the players in-game inventory. @@ -19,10 +22,17 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory { private static readonly ModuleLog Log = new("GameInventory"); - private readonly List changelog = new(); + private readonly List allEvents = new(); + private readonly List addedEvents = new(); + private readonly List removedEvents = new(); + private readonly List changedEvents = new(); + private readonly List movedEvents = new(); [ServiceManager.ServiceDependency] private readonly Framework framework = Service.Get(); + + [ServiceManager.ServiceDependency] + private readonly DalamudConfiguration dalamudConfiguration = Service.Get(); private readonly GameInventoryType[] inventoryTypes; private readonly GameInventoryItem[]?[] inventoryItems; @@ -39,6 +49,9 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory /// public event IGameInventory.InventoryChangelogDelegate? InventoryChanged; + /// + public event IGameInventory.InventoryChangelogDelegate? InventoryChangedRaw; + /// public event IGameInventory.InventoryChangedDelegate? ItemAdded; @@ -72,6 +85,32 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory return new ReadOnlySpan(inventory->Items, (int)inventory->Size); } + + private static void InvokeSafely( + IGameInventory.InventoryChangelogDelegate? cb, + IReadOnlyCollection data) + { + try + { + cb?.Invoke(data); + } + catch (Exception e) + { + Log.Error(e, "Exception during batch callback"); + } + } + + private static void InvokeSafely(IGameInventory.InventoryChangedDelegate? cb, InventoryEventArgs arg) + { + try + { + cb?.Invoke(arg.Type, arg); + } + catch (Exception e) + { + Log.Error(e, "Exception during {argType} callback", arg.Type); + } + } private void OnFrameworkUpdate(IFramework framework1) { @@ -90,208 +129,146 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory if (oldItem.IsEmpty) { - if (newItem.IsEmpty) - continue; - - this.changelog.Add(new InventoryItemAddedArgs + if (!newItem.IsEmpty) { - Item = newItem, - Inventory = newItem.ContainerType, - Slot = newItem.InventorySlot, - }); + this.addedEvents.Add(new(newItem)); + oldItem = newItem; + } } else { if (newItem.IsEmpty) { - this.changelog.Add(new InventoryItemRemovedArgs - { - Item = oldItem, - Inventory = oldItem.ContainerType, - Slot = oldItem.InventorySlot, - }); + this.removedEvents.Add(new(oldItem)); + oldItem = newItem; } else if (!oldItem.Equals(newItem)) { - this.changelog.Add(new InventoryItemChangedArgs - { - OldItemState = oldItem, - Item = newItem, - Inventory = newItem.ContainerType, - Slot = newItem.InventorySlot, - }); - } - else - { - continue; + this.changedEvents.Add(new(oldItem, newItem)); + oldItem = newItem; } } - - Log.Verbose($"[{this.changelog.Count - 1}] {this.changelog[^1]}"); - oldItem = newItem; } } // Was there any change? If not, stop further processing. - if (this.changelog.Count == 0) + // Note that... + // * this.movedEvents is not checked; it will be populated after this check. + // * this.allEvents is not checked; it is a temporary list to be used after this check. + if (this.addedEvents.Count == 0 && this.removedEvents.Count == 0 && this.changedEvents.Count == 0) return; try { - // From this point, the size of changelog shall not change. - var span = CollectionsMarshal.AsSpan(this.changelog); + // Broadcast InventoryChangedRaw, if necessary. + if (this.InventoryChangedRaw is not null) + { + this.allEvents.Clear(); + this.allEvents.EnsureCapacity( + this.addedEvents.Count + + this.removedEvents.Count + + this.changedEvents.Count); + this.allEvents.AddRange(this.addedEvents); + this.allEvents.AddRange(this.removedEvents); + this.allEvents.AddRange(this.changedEvents); + InvokeSafely(this.InventoryChangedRaw, this.allEvents); + } - // Ensure that changelog is in order of Added, Removed, and then Changed. - span.Sort((a, b) => a.Type.CompareTo(b.Type)); + // Resolve changelog for item moved, from 1 added + 1 removed event. + for (var iAdded = this.addedEvents.Count - 1; iAdded >= 0; --iAdded) + { + var added = this.addedEvents[iAdded]; + for (var iRemoved = this.removedEvents.Count - 1; iRemoved >= 0; --iRemoved) + { + var removed = this.removedEvents[iRemoved]; + if (added.Item.ItemId != removed.Item.ItemId) + continue; + + this.movedEvents.Add(new(removed, added)); + + // Remove the reinterpreted entries. + this.addedEvents.RemoveAt(iAdded); + this.removedEvents.RemoveAt(iRemoved); + break; + } + } + + // Resolve changelog for item moved, from 2 changed events. + for (var i = this.changedEvents.Count - 1; i >= 0; --i) + { + var e1 = this.changedEvents[i]; + for (var j = i - 1; j >= 0; --j) + { + var e2 = this.changedEvents[j]; + if (e1.Item.ItemId != e2.Item.ItemId || e1.Item.ItemId != e2.Item.ItemId) + continue; + + // move happened, and e2 has an item + if (!e2.Item.IsEmpty) + this.movedEvents.Add(new(e1, e2)); + + // move happened, and e1 has an item + if (!e1.Item.IsEmpty) + this.movedEvents.Add(new(e2, e1)); + + // Remove the reinterpreted entries. Note that i > j. + this.changedEvents.RemoveAt(i); + this.changedEvents.RemoveAt(j); + break; + } + } + + // Log only if it matters. + if (this.dalamudConfiguration.LogLevel >= LogEventLevel.Verbose) + { + foreach (var x in this.addedEvents) + Log.Verbose($"{x}"); - var removedFrom = 0; - while (removedFrom < span.Length && span[removedFrom].Type != GameInventoryEvent.Removed) - removedFrom++; + foreach (var x in this.removedEvents) + Log.Verbose($"{x}"); - var changedFrom = removedFrom; - while (changedFrom < span.Length && span[changedFrom].Type != GameInventoryEvent.Changed) - changedFrom++; - - var addedSpan = span[..removedFrom]; - var removedSpan = span[removedFrom..changedFrom]; - var changedSpan = span[changedFrom..]; - - // Resolve changelog for item moved, from 1 added + 1 removed - foreach (ref var added in addedSpan) - { - foreach (ref var removed in removedSpan) - { - if (added.Item.ItemId == removed.Item.ItemId) - { - Log.Verbose($"Move: reinterpreting {removed} + {added}"); - added = new InventoryItemMovedArgs - { - Item = removed.Item, - SourceInventory = removed.Item.ContainerType, - SourceSlot = removed.Item.InventorySlot, - TargetInventory = added.Item.ContainerType, - TargetSlot = added.Item.InventorySlot, - }; - removed = default; - break; - } - } + foreach (var x in this.changedEvents) + Log.Verbose($"{x}"); + + foreach (var x in this.movedEvents) + Log.Verbose($"{x} (({x.SourceEvent}) + ({x.TargetEvent}))"); } - // Resolve changelog for item moved, from 2 changes - for (var i = 0; i < changedSpan.Length; i++) + // Broadcast InventoryChanged, if necessary. + if (this.InventoryChanged is not null) { - if (span[i].Type is GameInventoryEvent.Empty) - continue; - - ref var e1 = ref changedSpan[i]; - for (var j = i + 1; j < changedSpan.Length; j++) - { - ref var e2 = ref changedSpan[j]; - if (e1.Item.ItemId == e2.Item.ItemId && e1.Item.ItemId == e2.Item.ItemId) - { - if (e1.Item.IsEmpty) - { - // e1 got moved to e2 - Log.Verbose($"Move: reinterpreting {e1} + {e2}"); - e1 = new InventoryItemMovedArgs - { - Item = e2.Item, - SourceInventory = e1.Item.ContainerType, - SourceSlot = e1.Item.InventorySlot, - TargetInventory = e2.Item.ContainerType, - TargetSlot = e2.Item.InventorySlot, - }; - e2 = default; - } - else if (e2.Item.IsEmpty) - { - // e2 got moved to e1 - Log.Verbose($"Move: reinterpreting {e2} + {e1}"); - e1 = new InventoryItemMovedArgs - { - Item = e1.Item, - SourceInventory = e2.Item.ContainerType, - SourceSlot = e2.Item.InventorySlot, - TargetInventory = e1.Item.ContainerType, - TargetSlot = e1.Item.InventorySlot, - }; - e2 = default; - } - else - { - // e1 and e2 got swapped - Log.Verbose($"Move(Swap): reinterpreting {e1} + {e2}"); - var newEvent1 = new InventoryItemMovedArgs - { - Item = e2.Item, - SourceInventory = e1.Item.ContainerType, - SourceSlot = e1.Item.InventorySlot, - TargetInventory = e2.Item.ContainerType, - TargetSlot = e2.Item.InventorySlot, - }; - - var newEvent2 = new InventoryItemMovedArgs - { - Item = e1.Item, - SourceInventory = e2.Item.ContainerType, - SourceSlot = e2.Item.InventorySlot, - TargetInventory = e1.Item.ContainerType, - TargetSlot = e1.Item.InventorySlot, - }; - - (e1, e2) = (newEvent1, newEvent2); - } - } - } + this.allEvents.Clear(); + this.allEvents.EnsureCapacity( + this.addedEvents.Count + + this.removedEvents.Count + + this.changedEvents.Count + + this.movedEvents.Count); + this.allEvents.AddRange(this.addedEvents); + this.allEvents.AddRange(this.removedEvents); + this.allEvents.AddRange(this.changedEvents); + this.allEvents.AddRange(this.movedEvents); + InvokeSafely(this.InventoryChanged, this.allEvents); } - // Filter out the emptied out entries. - // We do not care about the order of items in the changelog anymore. - for (var i = 0; i < span.Length;) - { - if (span[i] is null || span[i].Type is GameInventoryEvent.Empty) - { - span[i] = span[^1]; - span = span[..^1]; - } - else - { - i++; - } - } - - // Actually broadcast the changes to subscribers. - if (!span.IsEmpty) - { - this.InventoryChanged?.Invoke(span); - - foreach (var change in span) - { - switch (change) - { - case InventoryItemAddedArgs: - this.ItemAdded?.Invoke(GameInventoryEvent.Added, change); - break; - - case InventoryItemRemovedArgs: - this.ItemRemoved?.Invoke(GameInventoryEvent.Removed, change); - break; - - case InventoryItemMovedArgs: - this.ItemMoved?.Invoke(GameInventoryEvent.Moved, change); - break; - - case InventoryItemChangedArgs: - this.ItemChanged?.Invoke(GameInventoryEvent.Changed, change); - break; - } - } - } + // Broadcast the rest. + foreach (var x in this.addedEvents) + InvokeSafely(this.ItemAdded, x); + + foreach (var x in this.removedEvents) + InvokeSafely(this.ItemRemoved, x); + + foreach (var x in this.changedEvents) + InvokeSafely(this.ItemChanged, x); + + foreach (var x in this.movedEvents) + InvokeSafely(this.ItemMoved, x); } finally { - this.changelog.Clear(); + this.addedEvents.Clear(); + this.removedEvents.Clear(); + this.changedEvents.Clear(); + this.movedEvents.Clear(); } } } @@ -316,6 +293,7 @@ internal class GameInventoryPluginScoped : IDisposable, IServiceType, IGameInven public GameInventoryPluginScoped() { this.gameInventoryService.InventoryChanged += this.OnInventoryChangedForward; + this.gameInventoryService.InventoryChangedRaw += this.OnInventoryChangedRawForward; this.gameInventoryService.ItemAdded += this.OnInventoryItemAddedForward; this.gameInventoryService.ItemRemoved += this.OnInventoryItemRemovedForward; this.gameInventoryService.ItemMoved += this.OnInventoryItemMovedForward; @@ -325,6 +303,9 @@ internal class GameInventoryPluginScoped : IDisposable, IServiceType, IGameInven /// public event IGameInventory.InventoryChangelogDelegate? InventoryChanged; + /// + public event IGameInventory.InventoryChangelogDelegate? InventoryChangedRaw; + /// public event IGameInventory.InventoryChangedDelegate? ItemAdded; @@ -341,20 +322,25 @@ internal class GameInventoryPluginScoped : IDisposable, IServiceType, IGameInven public void Dispose() { this.gameInventoryService.InventoryChanged -= this.OnInventoryChangedForward; + this.gameInventoryService.InventoryChangedRaw -= this.OnInventoryChangedRawForward; this.gameInventoryService.ItemAdded -= this.OnInventoryItemAddedForward; this.gameInventoryService.ItemRemoved -= this.OnInventoryItemRemovedForward; this.gameInventoryService.ItemMoved -= this.OnInventoryItemMovedForward; this.gameInventoryService.ItemChanged -= this.OnInventoryItemChangedForward; this.InventoryChanged = null; + this.InventoryChangedRaw = null; this.ItemAdded = null; this.ItemRemoved = null; this.ItemMoved = null; this.ItemChanged = null; } - private void OnInventoryChangedForward(ReadOnlySpan events) + private void OnInventoryChangedForward(IReadOnlyCollection events) => this.InventoryChanged?.Invoke(events); + + private void OnInventoryChangedRawForward(IReadOnlyCollection events) + => this.InventoryChangedRaw?.Invoke(events); private void OnInventoryItemAddedForward(GameInventoryEvent type, InventoryEventArgs data) => this.ItemAdded?.Invoke(type, data); diff --git a/Dalamud/Game/Inventory/GameInventoryEvent.cs b/Dalamud/Game/Inventory/GameInventoryEvent.cs index 805306671..c23d79f30 100644 --- a/Dalamud/Game/Inventory/GameInventoryEvent.cs +++ b/Dalamud/Game/Inventory/GameInventoryEvent.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.GameInventory; +namespace Dalamud.Game.Inventory; /// /// Class representing a item's changelog state. diff --git a/Dalamud/Game/Inventory/GameInventoryItem.cs b/Dalamud/Game/Inventory/GameInventoryItem.cs index 794785e5c..9073073cb 100644 --- a/Dalamud/Game/Inventory/GameInventoryItem.cs +++ b/Dalamud/Game/Inventory/GameInventoryItem.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; using FFXIVClientStructs.FFXIV.Client.Game; -namespace Dalamud.Game.GameInventory; +namespace Dalamud.Game.Inventory; /// /// Dalamud wrapper around a ClientStructs InventoryItem. diff --git a/Dalamud/Game/Inventory/GameInventoryType.cs b/Dalamud/Game/Inventory/GameInventoryType.cs index 0eeeebe20..c982fa80f 100644 --- a/Dalamud/Game/Inventory/GameInventoryType.cs +++ b/Dalamud/Game/Inventory/GameInventoryType.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.GameInventory; +namespace Dalamud.Game.Inventory; /// /// Enum representing various player inventories. diff --git a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryEventArgs.cs b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryEventArgs.cs index a427dc840..070d8a8db 100644 --- a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryEventArgs.cs +++ b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryEventArgs.cs @@ -1,29 +1,35 @@ -namespace Dalamud.Game.GameInventory; +using System.Diagnostics.CodeAnalysis; + +namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes; /// /// Abstract base class representing inventory changed events. /// +[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1206:Declaration keywords should follow order", Justification = "It literally says , , and then . required is not an access modifier.")] public abstract class InventoryEventArgs { + /// + /// Initializes a new instance of the class. + /// + /// Type of the event. + /// Item about the event. + protected InventoryEventArgs(GameInventoryEvent type, in GameInventoryItem item) + { + this.Type = type; + this.Item = item; + } + /// /// Gets the type of event for these args. /// - public abstract GameInventoryEvent Type { get; } + public GameInventoryEvent Type { get; } /// /// Gets the item associated with this event. /// This is a copy of the item data. /// - required public GameInventoryItem Item { get; init; } + public GameInventoryItem Item { get; } /// - public override string ToString() => this.Type switch - { - GameInventoryEvent.Empty => $"<{this.Type}>", - GameInventoryEvent.Added => $"<{this.Type}> ({this.Item})", - GameInventoryEvent.Removed => $"<{this.Type}> ({this.Item})", - GameInventoryEvent.Changed => $"<{this.Type}> ({this.Item})", - GameInventoryEvent.Moved when this is InventoryItemMovedArgs args => $"<{this.Type}> (Item #{this.Item.ItemId}) from (slot {args.SourceSlot} in {args.SourceInventory}) to (slot {args.TargetSlot} in {args.TargetInventory})", - _ => $" {this.Item}", - }; + public override string ToString() => $"<{this.Type}> ({this.Item})"; } diff --git a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemAddedArgs.cs b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemAddedArgs.cs index 8d3e99823..f68b23106 100644 --- a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemAddedArgs.cs +++ b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemAddedArgs.cs @@ -1,20 +1,26 @@ -namespace Dalamud.Game.GameInventory; +namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes; /// /// Represents the data associated with an item being added to an inventory. /// public class InventoryItemAddedArgs : InventoryEventArgs { - /// - public override GameInventoryEvent Type => GameInventoryEvent.Added; - + /// + /// Initializes a new instance of the class. + /// + /// The item. + internal InventoryItemAddedArgs(in GameInventoryItem item) + : base(GameInventoryEvent.Added, item) + { + } + /// /// Gets the inventory this item was added to. /// - required public GameInventoryType Inventory { get; init; } - + public GameInventoryType Inventory => this.Item.ContainerType; + /// /// Gets the slot this item was added to. /// - required public uint Slot { get; init; } + public uint Slot => this.Item.InventorySlot; } diff --git a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemChangedArgs.cs b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemChangedArgs.cs index 1e2632722..1c47d3b83 100644 --- a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemChangedArgs.cs +++ b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemChangedArgs.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.GameInventory; +namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes; /// /// Represents the data associated with an items properties being changed. @@ -6,21 +6,29 @@ /// public class InventoryItemChangedArgs : InventoryEventArgs { - /// - public override GameInventoryEvent Type => GameInventoryEvent.Changed; - + /// + /// Initializes a new instance of the class. + /// + /// The item before change. + /// The item after change. + internal InventoryItemChangedArgs(in GameInventoryItem oldItem, in GameInventoryItem newItem) + : base(GameInventoryEvent.Changed, newItem) + { + this.OldItemState = oldItem; + } + /// /// Gets the inventory this item is in. /// - required public GameInventoryType Inventory { get; init; } - + public GameInventoryType Inventory => this.Item.ContainerType; + /// /// Gets the inventory slot this item is in. /// - required public uint Slot { get; init; } - + public uint Slot => this.Item.InventorySlot; + /// /// Gets the state of the item from before it was changed. /// - required public GameInventoryItem OldItemState { get; init; } + public GameInventoryItem OldItemState { get; init; } } diff --git a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemMovedArgs.cs b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemMovedArgs.cs index 655f43445..2f1113b02 100644 --- a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemMovedArgs.cs +++ b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemMovedArgs.cs @@ -1,30 +1,56 @@ -namespace Dalamud.Game.GameInventory; +using System.Diagnostics.CodeAnalysis; + +namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes; /// /// Represents the data associated with an item being moved from one inventory and added to another. /// +[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1206:Declaration keywords should follow order", Justification = "It literally says , , and then . required is not an access modifier.")] public class InventoryItemMovedArgs : InventoryEventArgs { - /// - public override GameInventoryEvent Type => GameInventoryEvent.Moved; - + /// + /// Initializes a new instance of the class. + /// + /// The item at before slot. + /// The item at after slot. + internal InventoryItemMovedArgs(InventoryEventArgs sourceEvent, InventoryEventArgs targetEvent) + : base(GameInventoryEvent.Moved, targetEvent.Item) + { + this.SourceEvent = sourceEvent; + this.TargetEvent = targetEvent; + } + /// /// Gets the inventory this item was moved from. /// - required public GameInventoryType SourceInventory { get; init; } - + public GameInventoryType SourceInventory => this.SourceEvent.Item.ContainerType; + /// /// Gets the inventory this item was moved to. /// - required public GameInventoryType TargetInventory { get; init; } + public GameInventoryType TargetInventory => this.Item.ContainerType; /// /// Gets the slot this item was moved from. /// - required public uint SourceSlot { get; init; } - + public uint SourceSlot => this.SourceEvent.Item.InventorySlot; + /// /// Gets the slot this item was moved to. /// - required public uint TargetSlot { get; init; } + public uint TargetSlot => this.Item.InventorySlot; + + /// + /// Gets the associated source event. + /// + internal InventoryEventArgs SourceEvent { get; } + + /// + /// Gets the associated target event. + /// + internal InventoryEventArgs TargetEvent { get; } + + /// + public override string ToString() => + $"<{this.Type}> (Item #{this.Item.ItemId}) from (slot {this.SourceSlot} in {this.SourceInventory}) to (slot {this.TargetSlot} in {this.TargetInventory})"; } diff --git a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemRemovedArgs.cs b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemRemovedArgs.cs index 2d4db2384..bd982d702 100644 --- a/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemRemovedArgs.cs +++ b/Dalamud/Game/Inventory/InventoryChangeArgsTypes/InventoryItemRemovedArgs.cs @@ -1,20 +1,26 @@ -namespace Dalamud.Game.GameInventory; +namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes; /// /// Represents the data associated with an item being removed from an inventory. /// public class InventoryItemRemovedArgs : InventoryEventArgs { - /// - public override GameInventoryEvent Type => GameInventoryEvent.Removed; - + /// + /// Initializes a new instance of the class. + /// + /// The item. + internal InventoryItemRemovedArgs(in GameInventoryItem item) + : base(GameInventoryEvent.Removed, item) + { + } + /// /// Gets the inventory this item was removed from. /// - required public GameInventoryType Inventory { get; init; } + public GameInventoryType Inventory => this.Item.ContainerType; /// /// Gets the slot this item was removed from. /// - required public uint Slot { get; init; } + public uint Slot => this.Item.InventorySlot; } diff --git a/Dalamud/Plugin/Services/IGameInventory.cs b/Dalamud/Plugin/Services/IGameInventory.cs index 40b4bd84f..979e2d6a6 100644 --- a/Dalamud/Plugin/Services/IGameInventory.cs +++ b/Dalamud/Plugin/Services/IGameInventory.cs @@ -1,4 +1,7 @@ -using Dalamud.Game.GameInventory; +using System.Collections.Generic; + +using Dalamud.Game.Inventory; +using Dalamud.Game.Inventory.InventoryChangeArgsTypes; namespace Dalamud.Plugin.Services; @@ -12,7 +15,7 @@ public interface IGameInventory /// This delegate sends the entire set of changes recorded. /// /// The events. - public delegate void InventoryChangelogDelegate(ReadOnlySpan events); + public delegate void InventoryChangelogDelegate(IReadOnlyCollection events); /// /// Delegate function to be called for each change to inventories. @@ -26,24 +29,37 @@ public interface IGameInventory /// Event that is fired when the inventory has been changed. /// public event InventoryChangelogDelegate InventoryChanged; + + /// + /// Event that is fired when the inventory has been changed, without trying to interpret two inventory slot changes + /// as a move event as appropriate.
+ /// In other words, does not fire in this event. + ///
+ public event InventoryChangelogDelegate InventoryChangedRaw; /// - /// Event that is fired when an item is added to an inventory. + /// Event that is fired when an item is added to an inventory.
+ /// If an accompanying item remove event happens, then will be called instead.
+ /// Use if you do not want such reinterpretation. ///
public event InventoryChangedDelegate ItemAdded; /// - /// Event that is fired when an item is removed from an inventory. + /// Event that is fired when an item is removed from an inventory.
+ /// If an accompanying item add event happens, then will be called instead.
+ /// Use if you do not want such reinterpretation. ///
public event InventoryChangedDelegate ItemRemoved; + /// + /// Event that is fired when an items properties are changed.
+ /// If an accompanying item change event happens, then will be called instead.
+ /// Use if you do not want such reinterpretation. + ///
+ public event InventoryChangedDelegate ItemChanged; + /// /// Event that is fired when an item is moved from one inventory into another. /// public event InventoryChangedDelegate ItemMoved; - - /// - /// Event that is fired when an items properties are changed. - /// - public event InventoryChangedDelegate ItemChanged; }