using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.Xna.Framework;
using StardewModdingAPI.Framework.StateTracking.FieldWatchers;
using StardewValley;
using StardewValley.Buildings;
using StardewValley.Locations;
using StardewValley.TerrainFeatures;
using Object = StardewValley.Object;
namespace StardewModdingAPI.Framework.StateTracking
{
/// Tracks changes to a location's data.
internal class LocationTracker : IWatcher
{
/*********
** Fields
*********/
/// The underlying watchers.
private readonly List Watchers = new List();
/*********
** Accessors
*********/
/// Whether the value changed since the last reset.
public bool IsChanged => this.Watchers.Any(p => p.IsChanged);
/// The tracked location.
public GameLocation Location { get; }
/// Tracks added or removed buildings.
public ICollectionWatcher BuildingsWatcher { get; }
/// Tracks added or removed debris.
public ICollectionWatcher DebrisWatcher { get; }
/// Tracks added or removed large terrain features.
public ICollectionWatcher LargeTerrainFeaturesWatcher { get; }
/// Tracks added or removed NPCs.
public ICollectionWatcher NpcsWatcher { get; }
/// Tracks added or removed objects.
public IDictionaryWatcher ObjectsWatcher { get; }
/// Tracks added or removed terrain features.
public IDictionaryWatcher TerrainFeaturesWatcher { get; }
/*********
** Public methods
*********/
/// Construct an instance.
/// The location to track.
public LocationTracker(GameLocation location)
{
this.Location = location;
// init watchers
this.BuildingsWatcher = location is BuildableGameLocation buildableLocation
? WatcherFactory.ForNetCollection(buildableLocation.buildings)
: (ICollectionWatcher)WatcherFactory.ForObservableCollection(new ObservableCollection());
this.DebrisWatcher = WatcherFactory.ForNetCollection(location.debris);
this.LargeTerrainFeaturesWatcher = WatcherFactory.ForNetCollection(location.largeTerrainFeatures);
this.NpcsWatcher = WatcherFactory.ForNetCollection(location.characters);
this.ObjectsWatcher = WatcherFactory.ForNetDictionary(location.netObjects);
this.TerrainFeaturesWatcher = WatcherFactory.ForNetDictionary(location.terrainFeatures);
this.Watchers.AddRange(new IWatcher[]
{
this.BuildingsWatcher,
this.DebrisWatcher,
this.LargeTerrainFeaturesWatcher,
this.NpcsWatcher,
this.ObjectsWatcher,
this.TerrainFeaturesWatcher
});
}
/// Stop watching the player fields and release all references.
public void Dispose()
{
foreach (IWatcher watcher in this.Watchers)
watcher.Dispose();
}
/// Update the current value if needed.
public void Update()
{
foreach (IWatcher watcher in this.Watchers)
watcher.Update();
}
/// Set the current value as the baseline.
public void Reset()
{
foreach (IWatcher watcher in this.Watchers)
watcher.Reset();
}
}
}