diff --git a/src/SMAPI/Framework/StateTracking/ChestTracker.cs b/src/SMAPI/Framework/StateTracking/ChestTracker.cs
new file mode 100644
index 00000000..4440bf4b
--- /dev/null
+++ b/src/SMAPI/Framework/StateTracking/ChestTracker.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using StardewModdingAPI.Enums;
+using StardewModdingAPI.Events;
+using StardewModdingAPI.Framework.StateTracking.FieldWatchers;
+using StardewValley;
+using ChangeType = StardewModdingAPI.Events.ChangeType;
+using Chest = StardewValley.Objects.Chest;
+
+namespace StardewModdingAPI.Framework.StateTracking
+{
+ 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
+ *********/
+ public ChestTracker(Chest chest)
+ {
+ this.Chest = chest;
+ this.PreviousInventory = this.GetInventory();
+ }
+
+ public void Update()
+ {
+ this.CurrentInventory = this.GetInventory();
+ }
+
+
+ public void Reset()
+ {
+ this.PreviousInventory = this.CurrentInventory;
+ }
+
+ public IEnumerable GetInventoryChanges()
+ {
+ IDictionary
- previous = this.PreviousInventory;
+ Console.WriteLine(previous.Count);
+ IDictionary
- current = this.GetInventory();
+ Console.WriteLine(current.Count);
+ 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
+ *********/
+
+ private IDictionary
- GetInventory()
+ {
+ return this.Chest.items
+ .Where(n => n != null)
+ .Distinct()
+ .ToDictionary(n => n, n => n.Stack);
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/StateTracking/Snapshots/WorldLocationsSnapshot.cs b/src/SMAPI/Framework/StateTracking/Snapshots/WorldLocationsSnapshot.cs
index 73ed2d8f..ed8001d6 100644
--- a/src/SMAPI/Framework/StateTracking/Snapshots/WorldLocationsSnapshot.cs
+++ b/src/SMAPI/Framework/StateTracking/Snapshots/WorldLocationsSnapshot.cs
@@ -43,7 +43,7 @@ namespace StardewModdingAPI.Framework.StateTracking.Snapshots
foreach (LocationTracker locationWatcher in watcher.Locations)
{
if (!this.LocationsDict.TryGetValue(locationWatcher.Location, out LocationSnapshot snapshot))
- this.LocationsDict[locationWatcher.Location] = snapshot = new LocationSnapshot(locationWatcher.Location);
+ this.LocationsDict[locationWatcher.Location] = snapshot = new LocationSnapshot(locationWatcher);
snapshot.Update(locationWatcher);
}