1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Xna.Framework;
using StardewModdingAPI.Framework.Input;
using StardewModdingAPI.Framework.StateTracking;
using StardewModdingAPI.Framework.StateTracking.FieldWatchers;
using StardewValley;
using StardewValley.Locations;
using StardewValley.Menus;
namespace StardewModdingAPI.Framework
{
/// <summary>Monitors the entire game state for changes, virally spreading watchers into any new entities that get created.</summary>
internal class WatcherCore
{
/*********
** Fields
*********/
/// <summary>The underlying watchers for convenience. These are accessible individually as separate properties.</summary>
private readonly List<IWatcher> Watchers = new();
/*********
** Accessors
*********/
/// <summary>Tracks changes to the window size.</summary>
public readonly IValueWatcher<Point> WindowSizeWatcher;
/// <summary>Tracks changes to the current player.</summary>
public PlayerTracker? CurrentPlayerTracker;
/// <summary>Tracks changes to the time of day (in 24-hour military format).</summary>
public readonly IValueWatcher<int> TimeWatcher;
/// <summary>Tracks changes to the save ID.</summary>
public readonly IValueWatcher<ulong> SaveIdWatcher;
/// <summary>Tracks changes to the game's locations.</summary>
public readonly WorldLocationsTracker LocationsWatcher;
/// <summary>Tracks changes to <see cref="Game1.activeClickableMenu"/>.</summary>
public readonly IValueWatcher<IClickableMenu> ActiveMenuWatcher;
/// <summary>Tracks changes to the cursor position.</summary>
public readonly IValueWatcher<ICursorPosition> CursorWatcher;
/// <summary>Tracks changes to the mouse wheel scroll.</summary>
public readonly IValueWatcher<int> MouseWheelScrollWatcher;
/// <summary>Tracks changes to the content locale.</summary>
public readonly IValueWatcher<LocalizedContentManager.LanguageCode> LocaleWatcher;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="inputState">Manages input visible to the game.</param>
/// <param name="gameLocations">The observable list of game locations.</param>
public WatcherCore(SInputState inputState, ObservableCollection<GameLocation> gameLocations)
{
// init watchers
this.CursorWatcher = WatcherFactory.ForEquatable(() => inputState.CursorPosition);
this.MouseWheelScrollWatcher = WatcherFactory.ForEquatable(() => inputState.MouseState.ScrollWheelValue);
this.SaveIdWatcher = WatcherFactory.ForEquatable(() => Game1.hasLoadedGame ? Game1.uniqueIDForThisGame : 0);
this.WindowSizeWatcher = WatcherFactory.ForEquatable(() => new Point(Game1.viewport.Width, Game1.viewport.Height));
this.TimeWatcher = WatcherFactory.ForEquatable(() => Game1.timeOfDay);
this.ActiveMenuWatcher = WatcherFactory.ForReference(() => Game1.activeClickableMenu);
this.LocationsWatcher = new WorldLocationsTracker(gameLocations, MineShaft.activeMines, VolcanoDungeon.activeLevels);
this.LocaleWatcher = WatcherFactory.ForGenericEquality(() => LocalizedContentManager.CurrentLanguageCode);
this.Watchers.AddRange(new IWatcher[]
{
this.CursorWatcher,
this.MouseWheelScrollWatcher,
this.SaveIdWatcher,
this.WindowSizeWatcher,
this.TimeWatcher,
this.ActiveMenuWatcher,
this.LocationsWatcher,
this.LocaleWatcher
});
}
/// <summary>Update the watchers and adjust for added or removed entities.</summary>
public void Update()
{
// reset player
if (Context.IsWorldReady)
{
if (this.CurrentPlayerTracker == null || this.CurrentPlayerTracker.Player != Game1.player)
{
this.CurrentPlayerTracker?.Dispose();
this.CurrentPlayerTracker = new PlayerTracker(Game1.player);
}
}
else
{
if (this.CurrentPlayerTracker != null)
{
this.CurrentPlayerTracker.Dispose();
this.CurrentPlayerTracker = null;
}
}
// update values
foreach (IWatcher watcher in this.Watchers)
watcher.Update();
this.CurrentPlayerTracker?.Update();
this.LocationsWatcher.Update();
}
/// <summary>Reset the current values as the baseline.</summary>
public void Reset()
{
foreach (IWatcher watcher in this.Watchers)
watcher.Reset();
this.CurrentPlayerTracker?.Reset();
this.LocationsWatcher.Reset();
}
}
}
|