diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2020-01-01 18:52:24 -0500 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2020-01-01 18:52:24 -0500 |
commit | e64a1220e309e8fc83e20833b8849de1721ec469 (patch) | |
tree | c4913b48c869a4a8cea0ee6f969bb959bb1b3a63 /src | |
parent | 6766fcd0fd5f6982d1ffc91a46e0d4a5703315dc (diff) | |
download | SMAPI-e64a1220e309e8fc83e20833b8849de1721ec469.tar.gz SMAPI-e64a1220e309e8fc83e20833b8849de1721ec469.tar.bz2 SMAPI-e64a1220e309e8fc83e20833b8849de1721ec469.zip |
unify item diff logic for players & chests
Diffstat (limited to 'src')
-rw-r--r-- | src/SMAPI/Events/ChestInventoryChangedEventArgs.cs | 21 | ||||
-rw-r--r-- | src/SMAPI/Events/InventoryChangedEventArgs.cs | 34 | ||||
-rw-r--r-- | src/SMAPI/Events/ItemStackChange.cs | 20 | ||||
-rw-r--r-- | src/SMAPI/Framework/SGame.cs | 12 | ||||
-rw-r--r-- | src/SMAPI/Framework/SnapshotItemListDiff.cs | 66 | ||||
-rw-r--r-- | src/SMAPI/Framework/StateTracking/ChestTracker.cs | 26 | ||||
-rw-r--r-- | src/SMAPI/Framework/StateTracking/PlayerTracker.cs | 27 | ||||
-rw-r--r-- | src/SMAPI/Framework/StateTracking/Snapshots/LocationSnapshot.cs | 7 | ||||
-rw-r--r-- | src/SMAPI/Framework/StateTracking/Snapshots/PlayerSnapshot.cs | 15 |
9 files changed, 135 insertions, 93 deletions
diff --git a/src/SMAPI/Events/ChestInventoryChangedEventArgs.cs b/src/SMAPI/Events/ChestInventoryChangedEventArgs.cs index 7771cd7c..4b4c4210 100644 --- a/src/SMAPI/Events/ChestInventoryChangedEventArgs.cs +++ b/src/SMAPI/Events/ChestInventoryChangedEventArgs.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using StardewValley; using StardewValley.Objects; @@ -16,8 +17,14 @@ namespace StardewModdingAPI.Events /// <summary>The location containing the chest.</summary> public GameLocation Location { get; } - /// <summary>The inventory changes in the chest.</summary> - public ItemStackChange[] Changes { get; } + /// <summary>The added item stacks.</summary> + public IEnumerable<Item> Added { get; } + + /// <summary>The removed item stacks.</summary> + public IEnumerable<Item> Removed { get; } + + /// <summary>The item stacks whose size changed.</summary> + public IEnumerable<ItemStackSizeChange> QuantityChanged { get; } /********* @@ -26,12 +33,16 @@ namespace StardewModdingAPI.Events /// <summary>Construct an instance.</summary> /// <param name="chest">The chest whose inventory changed.</param> /// <param name="location">The location containing the chest.</param> - /// <param name="changes">The inventory changes in the chest.</param> - internal ChestInventoryChangedEventArgs(Chest chest, GameLocation location, ItemStackChange[] changes) + /// <param name="added">The added item stacks.</param> + /// <param name="removed">The removed item stacks.</param> + /// <param name="quantityChanged">The item stacks whose size changed.</param> + internal ChestInventoryChangedEventArgs(Chest chest, GameLocation location, Item[] added, Item[] removed, ItemStackSizeChange[] quantityChanged) { this.Location = location; this.Chest = chest; - this.Changes = changes; + this.Added = added; + this.Removed = removed; + this.QuantityChanged = quantityChanged; } } } diff --git a/src/SMAPI/Events/InventoryChangedEventArgs.cs b/src/SMAPI/Events/InventoryChangedEventArgs.cs index 874c2e48..40cd4128 100644 --- a/src/SMAPI/Events/InventoryChangedEventArgs.cs +++ b/src/SMAPI/Events/InventoryChangedEventArgs.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using StardewValley; namespace StardewModdingAPI.Events @@ -14,13 +13,13 @@ namespace StardewModdingAPI.Events /// <summary>The player whose inventory changed.</summary> public Farmer Player { get; } - /// <summary>The added items.</summary> + /// <summary>The added item stacks.</summary> public IEnumerable<Item> Added { get; } - /// <summary>The removed items.</summary> + /// <summary>The removed item stacks.</summary> public IEnumerable<Item> Removed { get; } - /// <summary>The items whose stack sizes changed, with the relative change.</summary> + /// <summary>The item stacks whose size changed.</summary> public IEnumerable<ItemStackSizeChange> QuantityChanged { get; } /// <summary>Whether the affected player is the local one.</summary> @@ -32,28 +31,15 @@ namespace StardewModdingAPI.Events *********/ /// <summary>Construct an instance.</summary> /// <param name="player">The player whose inventory changed.</param> - /// <param name="changedItems">The inventory changes.</param> - internal InventoryChangedEventArgs(Farmer player, ItemStackChange[] changedItems) + /// <param name="added">The added item stacks.</param> + /// <param name="removed">The removed item stacks.</param> + /// <param name="quantityChanged">The item stacks whose size changed.</param> + internal InventoryChangedEventArgs(Farmer player, Item[] added, Item[] removed, ItemStackSizeChange[] quantityChanged) { this.Player = player; - this.Added = changedItems - .Where(n => n.ChangeType == ChangeType.Added) - .Select(p => p.Item) - .ToArray(); - - this.Removed = changedItems - .Where(n => n.ChangeType == ChangeType.Removed) - .Select(p => p.Item) - .ToArray(); - - this.QuantityChanged = changedItems - .Where(n => n.ChangeType == ChangeType.StackChange) - .Select(change => new ItemStackSizeChange( - item: change.Item, - oldSize: change.Item.Stack - change.StackChange, - newSize: change.Item.Stack - )) - .ToArray(); + this.Added = added; + this.Removed = removed; + this.QuantityChanged = quantityChanged; } } } diff --git a/src/SMAPI/Events/ItemStackChange.cs b/src/SMAPI/Events/ItemStackChange.cs deleted file mode 100644 index cb5d2b88..00000000 --- a/src/SMAPI/Events/ItemStackChange.cs +++ /dev/null @@ -1,20 +0,0 @@ -using StardewValley; - -namespace StardewModdingAPI.Events -{ - /// <summary>Represents an inventory slot that changed.</summary> - public class ItemStackChange - { - /********* - ** Accessors - *********/ - /// <summary>The item in the slot.</summary> - public Item Item { get; set; } - - /// <summary>The amount by which the item's stack size changed.</summary> - public int StackChange { get; set; } - - /// <summary>How the inventory slot changed.</summary> - public ChangeType ChangeType { get; set; } - } -} diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index eccb6387..e2b22ba7 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -706,7 +706,10 @@ namespace StardewModdingAPI.Framework if (events.ChestInventoryChanged.HasListeners()) { foreach (var pair in locState.ChestItems) - events.ChestInventoryChanged.Raise(new ChestInventoryChangedEventArgs(pair.Key, location, pair.Value)); + { + SnapshotItemListDiff diff = pair.Value; + events.ChestInventoryChanged.Raise(new ChestInventoryChangedEventArgs(pair.Key, location, added: diff.Added, removed: diff.Removed, quantityChanged: diff.QuantityChanged)); + } } // terrain features changed @@ -747,12 +750,13 @@ namespace StardewModdingAPI.Framework } // raise player inventory changed - ItemStackChange[] changedItems = playerState.InventoryChanges.ToArray(); - if (changedItems.Any()) + if (playerState.Inventory.IsChanged) { + var inventory = playerState.Inventory; + if (this.Monitor.IsVerbose) this.Monitor.Log("Events: player inventory changed.", LogLevel.Trace); - events.InventoryChanged.Raise(new InventoryChangedEventArgs(player, changedItems)); + events.InventoryChanged.Raise(new InventoryChangedEventArgs(player, added: inventory.Added, removed: inventory.Removed, quantityChanged: inventory.QuantityChanged)); } } } diff --git a/src/SMAPI/Framework/SnapshotItemListDiff.cs b/src/SMAPI/Framework/SnapshotItemListDiff.cs new file mode 100644 index 00000000..e8ab1b1e --- /dev/null +++ b/src/SMAPI/Framework/SnapshotItemListDiff.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Linq; +using StardewModdingAPI.Events; +using StardewValley; + +namespace StardewModdingAPI.Framework +{ + /// <summary>A snapshot of a tracked item list.</summary> + internal class SnapshotItemListDiff + { + /********* + ** Accessors + *********/ + /// <summary>Whether the item list changed.</summary> + public bool IsChanged { get; } + + /// <summary>The removed values.</summary> + public Item[] Removed { get; } + + /// <summary>The added values.</summary> + public Item[] Added { get; } + + /// <summary>The items whose stack sizes changed.</summary> + public ItemStackSizeChange[] QuantityChanged { get; } + + + /********* + ** Public methods + *********/ + /// <summary>Update the snapshot.</summary> + /// <param name="added">The added values.</param> + /// <param name="removed">The removed values.</param> + /// <param name="sizesChanged">The items whose stack sizes changed.</param> + public SnapshotItemListDiff(Item[] added, Item[] removed, ItemStackSizeChange[] sizesChanged) + { + this.Removed = removed; + this.Added = added; + this.QuantityChanged = sizesChanged; + + this.IsChanged = removed.Length > 0 || added.Length > 0 || sizesChanged.Length > 0; + } + + /// <summary>Get a snapshot diff if anything changed in the given data.</summary> + /// <param name="added">The added item stacks.</param> + /// <param name="removed">The removed item stacks.</param> + /// <param name="stackSizes">The items with their previous stack sizes.</param> + /// <param name="changes">The inventory changes, or <c>null</c> if nothing changed.</param> + /// <returns>Returns whether anything changed.</returns> + public static bool TryGetChanges(ISet<Item> added, ISet<Item> removed, IDictionary<Item, int> stackSizes, out SnapshotItemListDiff changes) + { + KeyValuePair<Item, int>[] sizesChanged = stackSizes.Where(p => p.Key.Stack != p.Value).ToArray(); + if (sizesChanged.Any() || added.Any() || removed.Any()) + { + changes = new SnapshotItemListDiff( + added: added.ToArray(), + removed: removed.ToArray(), + sizesChanged: sizesChanged.Select(p => new ItemStackSizeChange(p.Key, p.Value, p.Key.Stack)).ToArray() + ); + return true; + } + + changes = null; + return false; + } + } +} 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(); } - /// <summary>Get the inventory changes since the last update.</summary> - public IEnumerable<ItemStackChange> GetInventoryChanges() + /// <summary>Get the inventory changes since the last update, if anything changed.</summary> + /// <param name="changes">The inventory changes, or <c>null</c> if nothing changed.</param> + /// <returns>Returns whether anything changed.</returns> + 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); } /// <summary>Release watchers and resources.</summary> 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; } - /// <summary>Get the inventory changes since the last update.</summary> - public IEnumerable<ItemStackChange> GetInventoryChanges() + /// <summary>Get the inventory changes since the last update, if anything changed.</summary> + /// <param name="changes">The inventory changes, or <c>null</c> if nothing changed.</param> + /// <returns>Returns whether anything changed.</returns> + public bool TryGetInventoryChanges(out SnapshotItemListDiff changes) { - IDictionary<Item, int> previous = this.PreviousInventory; IDictionary<Item, int> current = this.GetInventory(); - foreach (Item item in previous.Keys.Union(current.Keys)) + + ISet<Item> added = new HashSet<Item>(new ObjectReferenceComparer<Item>()); + ISet<Item> removed = new HashSet<Item>(new ObjectReferenceComparer<Item>()); + 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); } /// <summary>Release watchers and resources.</summary> 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<KeyValuePair<Vector2, TerrainFeature>> TerrainFeatures { get; } = new SnapshotListDiff<KeyValuePair<Vector2, TerrainFeature>>(); /// <summary>Tracks changed chest inventories.</summary> - public IDictionary<Chest, ItemStackChange[]> ChestItems { get; } = new Dictionary<Chest, ItemStackChange[]>(); + public IDictionary<Chest, SnapshotItemListDiff> ChestItems { get; } = new Dictionary<Chest, SnapshotItemListDiff>(); /********* @@ -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 @@ -11,6 +11,13 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots internal class PlayerSnapshot { /********* + ** Fields + *********/ + /// <summary>An empty item list diff.</summary> + private readonly SnapshotItemListDiff EmptyItemListDiff = new SnapshotItemListDiff(new Item[0], new Item[0], new ItemStackSizeChange[0]); + + + /********* ** Accessors *********/ /// <summary>The player being tracked.</summary> @@ -27,7 +34,7 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots .ToDictionary(skill => skill, skill => new SnapshotDiff<int>()); /// <summary>Get a list of inventory changes.</summary> - public IEnumerable<ItemStackChange> 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; + } } } |