From e64a1220e309e8fc83e20833b8849de1721ec469 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 1 Jan 2020 18:52:24 -0500 Subject: unify item diff logic for players & chests --- src/SMAPI/Framework/StateTracking/ChestTracker.cs | 26 ++++----------------- src/SMAPI/Framework/StateTracking/PlayerTracker.cs | 27 ++++++++++++---------- .../StateTracking/Snapshots/LocationSnapshot.cs | 7 ++---- .../StateTracking/Snapshots/PlayerSnapshot.cs | 15 ++++++++++-- 4 files changed, 35 insertions(+), 40 deletions(-) (limited to 'src/SMAPI/Framework/StateTracking') diff --git a/src/SMAPI/Framework/StateTracking/ChestTracker.cs b/src/SMAPI/Framework/StateTracking/ChestTracker.cs index 3ce70c17..65f58ee7 100644 --- a/src/SMAPI/Framework/StateTracking/ChestTracker.cs +++ b/src/SMAPI/Framework/StateTracking/ChestTracker.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using StardewModdingAPI.Events; using StardewModdingAPI.Framework.StateTracking.Comparers; using StardewModdingAPI.Framework.StateTracking.FieldWatchers; using StardewValley; using StardewValley.Objects; -using ChangeType = StardewModdingAPI.Events.ChangeType; namespace StardewModdingAPI.Framework.StateTracking { @@ -83,26 +81,12 @@ namespace StardewModdingAPI.Framework.StateTracking this.Removed.Clear(); } - /// Get the inventory changes since the last update. - public IEnumerable GetInventoryChanges() + /// Get the inventory changes since the last update, if anything changed. + /// The inventory changes, or null if nothing changed. + /// Returns whether anything changed. + public bool TryGetInventoryChanges(out SnapshotItemListDiff changes) { - // removed - foreach (Item item in this.Removed) - yield return new ItemStackChange { Item = item, StackChange = -item.Stack, ChangeType = ChangeType.Removed }; - - // added - foreach (Item item in this.Added) - yield return new ItemStackChange { Item = item, StackChange = item.Stack, ChangeType = ChangeType.Added }; - - // stack size changed - foreach (var entry in this.StackSizes) - { - Item item = entry.Key; - int prevStack = entry.Value; - - if (item.Stack != prevStack) - yield return new ItemStackChange { Item = item, StackChange = item.Stack - prevStack, ChangeType = ChangeType.StackChange }; - } + return SnapshotItemListDiff.TryGetChanges(added: this.Added, removed: this.Removed, stackSizes: this.StackSizes, out changes); } /// Release watchers and resources. diff --git a/src/SMAPI/Framework/StateTracking/PlayerTracker.cs b/src/SMAPI/Framework/StateTracking/PlayerTracker.cs index d25f3345..cf49a7c1 100644 --- a/src/SMAPI/Framework/StateTracking/PlayerTracker.cs +++ b/src/SMAPI/Framework/StateTracking/PlayerTracker.cs @@ -2,10 +2,9 @@ using System; using System.Collections.Generic; using System.Linq; using StardewModdingAPI.Enums; -using StardewModdingAPI.Events; +using StardewModdingAPI.Framework.StateTracking.Comparers; using StardewModdingAPI.Framework.StateTracking.FieldWatchers; using StardewValley; -using ChangeType = StardewModdingAPI.Events.ChangeType; namespace StardewModdingAPI.Framework.StateTracking { @@ -99,20 +98,24 @@ namespace StardewModdingAPI.Framework.StateTracking return this.Player.currentLocation ?? this.LastValidLocation; } - /// Get the inventory changes since the last update. - public IEnumerable GetInventoryChanges() + /// Get the inventory changes since the last update, if anything changed. + /// The inventory changes, or null if nothing changed. + /// Returns whether anything changed. + public bool TryGetInventoryChanges(out SnapshotItemListDiff changes) { - IDictionary previous = this.PreviousInventory; IDictionary current = this.GetInventory(); - foreach (Item item in previous.Keys.Union(current.Keys)) + + ISet added = new HashSet(new ObjectReferenceComparer()); + ISet removed = new HashSet(new ObjectReferenceComparer()); + foreach (Item item in this.PreviousInventory.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 }; + if (!this.PreviousInventory.ContainsKey(item)) + added.Add(item); + else if (!current.ContainsKey(item)) + removed.Add(item); } + + return SnapshotItemListDiff.TryGetChanges(added: added, removed: removed, stackSizes: this.PreviousInventory, out changes); } /// Release watchers and resources. diff --git a/src/SMAPI/Framework/StateTracking/Snapshots/LocationSnapshot.cs b/src/SMAPI/Framework/StateTracking/Snapshots/LocationSnapshot.cs index edfba736..6ae52fd0 100644 --- a/src/SMAPI/Framework/StateTracking/Snapshots/LocationSnapshot.cs +++ b/src/SMAPI/Framework/StateTracking/Snapshots/LocationSnapshot.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using System.Linq; using Microsoft.Xna.Framework; -using StardewModdingAPI.Events; using StardewValley; using StardewValley.Buildings; using StardewValley.Objects; @@ -37,7 +35,7 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots public SnapshotListDiff> TerrainFeatures { get; } = new SnapshotListDiff>(); /// Tracks changed chest inventories. - public IDictionary ChestItems { get; } = new Dictionary(); + public IDictionary ChestItems { get; } = new Dictionary(); /********* @@ -66,8 +64,7 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots this.ChestItems.Clear(); foreach (ChestTracker tracker in watcher.ChestWatchers.Values) { - ItemStackChange[] changes = tracker.GetInventoryChanges().ToArray(); - if (changes.Length > 0) + if (tracker.TryGetInventoryChanges(out SnapshotItemListDiff changes)) this.ChestItems[tracker.Chest] = changes; } } diff --git a/src/SMAPI/Framework/StateTracking/Snapshots/PlayerSnapshot.cs b/src/SMAPI/Framework/StateTracking/Snapshots/PlayerSnapshot.cs index 7bcd9f82..f0fb9485 100644 --- a/src/SMAPI/Framework/StateTracking/Snapshots/PlayerSnapshot.cs +++ b/src/SMAPI/Framework/StateTracking/Snapshots/PlayerSnapshot.cs @@ -10,6 +10,13 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots /// A frozen snapshot of a tracked player. internal class PlayerSnapshot { + /********* + ** Fields + *********/ + /// An empty item list diff. + private readonly SnapshotItemListDiff EmptyItemListDiff = new SnapshotItemListDiff(new Item[0], new Item[0], new ItemStackSizeChange[0]); + + /********* ** Accessors *********/ @@ -27,7 +34,7 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots .ToDictionary(skill => skill, skill => new SnapshotDiff()); /// Get a list of inventory changes. - public IEnumerable InventoryChanges { get; private set; } + public SnapshotItemListDiff Inventory { get; private set; } /********* @@ -47,7 +54,11 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots this.Location.Update(watcher.LocationWatcher); foreach (var pair in this.Skills) pair.Value.Update(watcher.SkillWatchers[pair.Key]); - this.InventoryChanges = watcher.GetInventoryChanges().ToArray(); + + this.Inventory = watcher.TryGetInventoryChanges(out SnapshotItemListDiff itemChanges) + ? itemChanges + : this.EmptyItemListDiff; + } } } -- cgit