using System.Collections.Generic; using System.Linq; using StardewModdingAPI.Events; using StardewValley; using StardewValley.Objects; using ChangeType = StardewModdingAPI.Events.ChangeType; namespace StardewModdingAPI.Framework.StateTracking { /// Tracks changes to a chest's items. internal class ChestTracker { /********* ** Fields *********/ /// The chest's inventory as of the last reset. private IDictionary PreviousInventory; /// The chest's inventory change as of the last update. private IDictionary CurrentInventory; /********* ** Accessors *********/ /// The chest being tracked. public Chest Chest { get; } /********* ** Public methods *********/ /// Construct an instance. /// The chest being tracked. public ChestTracker(Chest chest) { this.Chest = chest; this.PreviousInventory = this.GetInventory(); } /// Update the current values if needed. public void Update() { this.CurrentInventory = this.GetInventory(); } /// Reset all trackers so their current values are the baseline. public void Reset() { if (this.CurrentInventory != null) this.PreviousInventory = this.CurrentInventory; } /// Get the inventory changes since the last update. public IEnumerable GetInventoryChanges() { IDictionary previous = this.PreviousInventory; IDictionary current = this.GetInventory(); foreach (Item item in previous.Keys.Union(current.Keys)) { if (!previous.TryGetValue(item, out int prevStack)) yield return new ItemStackChange { Item = item, StackChange = item.Stack, ChangeType = ChangeType.Added }; else if (!current.TryGetValue(item, out int newStack)) yield return new ItemStackChange { Item = item, StackChange = -item.Stack, ChangeType = ChangeType.Removed }; else if (prevStack != newStack) yield return new ItemStackChange { Item = item, StackChange = newStack - prevStack, ChangeType = ChangeType.StackChange }; } } /********* ** Private methods *********/ /// Get the player's current inventory. private IDictionary GetInventory() { return this.Chest.items .Where(n => n != null) .Distinct() .ToDictionary(n => n, n => n.Stack); } } }