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
/// The location containing the chest.
public GameLocation Location { get; }
- /// The inventory changes in the chest.
- public ItemStackChange[] Changes { get; }
+ /// The added item stacks.
+ public IEnumerable- Added { get; }
+
+ /// The removed item stacks.
+ public IEnumerable
- Removed { get; }
+
+ /// The item stacks whose size changed.
+ public IEnumerable QuantityChanged { get; }
/*********
@@ -26,12 +33,16 @@ namespace StardewModdingAPI.Events
/// Construct an instance.
/// The chest whose inventory changed.
/// The location containing the chest.
- /// The inventory changes in the chest.
- internal ChestInventoryChangedEventArgs(Chest chest, GameLocation location, ItemStackChange[] changes)
+ /// The added item stacks.
+ /// The removed item stacks.
+ /// The item stacks whose size changed.
+ 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
/// The player whose inventory changed.
public Farmer Player { get; }
- /// The added items.
+ /// The added item stacks.
public IEnumerable
- Added { get; }
- /// The removed items.
+ /// The removed item stacks.
public IEnumerable
- Removed { get; }
- /// The items whose stack sizes changed, with the relative change.
+ /// The item stacks whose size changed.
public IEnumerable QuantityChanged { get; }
/// Whether the affected player is the local one.
@@ -32,28 +31,15 @@ namespace StardewModdingAPI.Events
*********/
/// Construct an instance.
/// The player whose inventory changed.
- /// The inventory changes.
- internal InventoryChangedEventArgs(Farmer player, ItemStackChange[] changedItems)
+ /// The added item stacks.
+ /// The removed item stacks.
+ /// The item stacks whose size changed.
+ 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
-{
- /// Represents an inventory slot that changed.
- public class ItemStackChange
- {
- /*********
- ** Accessors
- *********/
- /// The item in the slot.
- public Item Item { get; set; }
-
- /// The amount by which the item's stack size changed.
- public int StackChange { get; set; }
-
- /// How the inventory slot changed.
- 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
+{
+ /// A snapshot of a tracked item list.
+ internal class SnapshotItemListDiff
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// Whether the item list changed.
+ public bool IsChanged { get; }
+
+ /// The removed values.
+ public Item[] Removed { get; }
+
+ /// The added values.
+ public Item[] Added { get; }
+
+ /// The items whose stack sizes changed.
+ public ItemStackSizeChange[] QuantityChanged { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// Update the snapshot.
+ /// The added values.
+ /// The removed values.
+ /// The items whose stack sizes changed.
+ 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;
+ }
+
+ /// Get a snapshot diff if anything changed in the given data.
+ /// The added item stacks.
+ /// The removed item stacks.
+ /// The items with their previous stack sizes.
+ /// The inventory changes, or null if nothing changed.
+ /// Returns whether anything changed.
+ public static bool TryGetChanges(ISet
- added, ISet
- removed, IDictionary
- stackSizes, out SnapshotItemListDiff changes)
+ {
+ KeyValuePair
- [] 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();
}
- /// 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;
+
}
}
}