Merge branch 'develop' into stable
This commit is contained in:
commit
48bb1581a6
|
@ -4,7 +4,7 @@
|
|||
|
||||
<!--set properties -->
|
||||
<PropertyGroup>
|
||||
<Version>3.8.0</Version>
|
||||
<Version>3.8.1</Version>
|
||||
<Product>SMAPI</Product>
|
||||
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
|
|
@ -7,8 +7,22 @@
|
|||
* Migrated to Harmony 2.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info).
|
||||
-->
|
||||
|
||||
## 3.8.1
|
||||
Released 26 December 2020 for Stardew Valley 1.5.1 or later.
|
||||
|
||||
* For players:
|
||||
* Fixed broken community center bundles for non-English saves created in Stardew Valley 1.5. Affected saves will be fixed automatically on load.
|
||||
|
||||
* For modders:
|
||||
* World events are now raised for volcano dungeon levels.
|
||||
* Added `apply_save_fix` command to reapply a save migration in exceptional cases. This should be used very carefully. Type `help apply_save_fix` for details.
|
||||
* **Deprecation notice:** the `Helper.ConsoleCommands.Trigger` method is now deprecated and should no longer be used. See [integration APIs](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Integrations) for better mod integration options. It will eventually be removed in SMAPI 4.0.
|
||||
|
||||
For the web UI:
|
||||
* Fixed edge cases in SMAPI log parsing.
|
||||
|
||||
## 3.8
|
||||
Released 21 December 2020 for Stardew Valley 1.5 or later.
|
||||
Released 21 December 2020 for Stardew Valley 1.5 or later. See [release highlights](https://www.patreon.com/posts/45294737).
|
||||
|
||||
* For players:
|
||||
* Updated for Stardew Valley 1.5, including split-screen support.
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using StardewValley;
|
||||
|
||||
namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other
|
||||
{
|
||||
/// <summary>A command which runs one of the game's save migrations.</summary>
|
||||
internal class ApplySaveFixCommand : TrainerCommand
|
||||
{
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
public ApplySaveFixCommand()
|
||||
: base("apply_save_fix", "Apply one of the game's save migrations to the currently loaded save. WARNING: This may corrupt or make permanent changes to your save. DO NOT USE THIS unless you're absolutely sure.\n\nUsage: apply_save_fix list\nList all valid save IDs.\n\nUsage: apply_save_fix <fix ID>\nApply the named save fix.") { }
|
||||
|
||||
/// <summary>Handle the command.</summary>
|
||||
/// <param name="monitor">Writes messages to the console and log file.</param>
|
||||
/// <param name="command">The command name.</param>
|
||||
/// <param name="args">The command arguments.</param>
|
||||
public override void Handle(IMonitor monitor, string command, ArgumentParser args)
|
||||
{
|
||||
// get fix ID
|
||||
if (!args.TryGet(0, "fix_id", out string rawFixId, required: false))
|
||||
{
|
||||
monitor.Log("Invalid usage. Type 'help apply_save_fix' for details.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
rawFixId = rawFixId.Trim();
|
||||
|
||||
|
||||
// list mode
|
||||
if (rawFixId == "list")
|
||||
{
|
||||
monitor.Log("Valid save fix IDs:\n - " + string.Join("\n - ", this.GetSaveIds()), LogLevel.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
// validate fix ID
|
||||
if (!Enum.TryParse(rawFixId, ignoreCase: true, out SaveGame.SaveFixes fixId))
|
||||
{
|
||||
monitor.Log($"Invalid save ID '{rawFixId}'. Type 'help apply_save_fix' for details.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
// apply
|
||||
monitor.Log("THIS MAY CAUSE PERMANENT CHANGES TO YOUR SAVE FILE. If you're not sure, exit your game without saving to avoid issues.", LogLevel.Warn);
|
||||
monitor.Log($"Trying to apply save fix ID: '{fixId}'.", LogLevel.Warn);
|
||||
try
|
||||
{
|
||||
Game1.applySaveFix(fixId);
|
||||
monitor.Log("Save fix applied.", LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
monitor.Log("Applying save fix failed. The save may be in an invalid state; you should exit your game now without saving to avoid issues.", LogLevel.Error);
|
||||
monitor.Log($"Technical details: {ex}", LogLevel.Debug);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>Get the valid save fix IDs.</summary>
|
||||
private IEnumerable<string> GetSaveIds()
|
||||
{
|
||||
foreach (SaveGame.SaveFixes id in Enum.GetValues(typeof(SaveGame.SaveFixes)))
|
||||
{
|
||||
if (id == SaveGame.SaveFixes.MAX)
|
||||
continue;
|
||||
|
||||
yield return id.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Name": "Console Commands",
|
||||
"Author": "SMAPI",
|
||||
"Version": "3.8.0",
|
||||
"Version": "3.8.1",
|
||||
"Description": "Adds SMAPI console commands that let you manipulate the game.",
|
||||
"UniqueID": "SMAPI.ConsoleCommands",
|
||||
"EntryDll": "ConsoleCommands.dll",
|
||||
"MinimumApiVersion": "3.8.0"
|
||||
"MinimumApiVersion": "3.8.1"
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Name": "Save Backup",
|
||||
"Author": "SMAPI",
|
||||
"Version": "3.8.0",
|
||||
"Version": "3.8.1",
|
||||
"Description": "Automatically backs up all your saves once per day into its folder.",
|
||||
"UniqueID": "SMAPI.SaveBackup",
|
||||
"EntryDll": "SaveBackup.dll",
|
||||
"MinimumApiVersion": "3.8.0"
|
||||
"MinimumApiVersion": "3.8.1"
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace StardewModdingAPI.Web.Framework.LogParsing
|
|||
private readonly Regex ModUpdateListStartPattern = new Regex(@"^You can update \d+ mods?:$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
/// <summary>A regex pattern matching an entry in SMAPI's mod update list.</summary>
|
||||
private readonly Regex ModUpdateListEntryPattern = new Regex(@"^ (?<name>.+?) (?<version>[^\s]+): (?<link>.+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private readonly Regex ModUpdateListEntryPattern = new Regex(@"^ (?<name>.+) (?<version>[^\s]+): (?<link>.+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
/// <summary>A regex pattern matching SMAPI's update line.</summary>
|
||||
private readonly Regex SmapiUpdatePattern = new Regex(@"^You can update SMAPI to (?<version>[^\s]+): (?<link>.+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
@ -109,12 +109,9 @@ namespace StardewModdingAPI.Web.Framework.LogParsing
|
|||
if (message.Mod == "SMAPI")
|
||||
{
|
||||
// update flags
|
||||
if (inModList && !this.ModListEntryPattern.IsMatch(message.Text))
|
||||
inModList = false;
|
||||
if (inContentPackList && !this.ContentPackListEntryPattern.IsMatch(message.Text))
|
||||
inContentPackList = false;
|
||||
if (inModUpdateList && !this.ModUpdateListEntryPattern.IsMatch(message.Text))
|
||||
inModUpdateList = false;
|
||||
inModList = inModList && message.Level == LogLevel.Info && this.ModListEntryPattern.IsMatch(message.Text);
|
||||
inContentPackList = inContentPackList && message.Level == LogLevel.Info && this.ContentPackListEntryPattern.IsMatch(message.Text);
|
||||
inModUpdateList = inModUpdateList && message.Level == LogLevel.Alert && this.ModUpdateListEntryPattern.IsMatch(message.Text);
|
||||
|
||||
// mod list
|
||||
if (!inModList && message.Level == LogLevel.Info && this.ModListStartPattern.IsMatch(message.Text))
|
||||
|
|
|
@ -54,10 +54,10 @@ namespace StardewModdingAPI
|
|||
** Public
|
||||
****/
|
||||
/// <summary>SMAPI's current semantic version.</summary>
|
||||
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.8.0");
|
||||
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.8.1");
|
||||
|
||||
/// <summary>The minimum supported version of Stardew Valley.</summary>
|
||||
public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.5.0");
|
||||
public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.5.1");
|
||||
|
||||
/// <summary>The maximum supported version of Stardew Valley.</summary>
|
||||
public static ISemanticVersion MaximumGameVersion { get; } = null;
|
||||
|
|
|
@ -278,7 +278,7 @@ namespace StardewModdingAPI.Framework
|
|||
return this.ContentManagerLock.InReadLock(() =>
|
||||
{
|
||||
List<object> values = new List<object>();
|
||||
foreach (IContentManager content in this.ContentManagers.Where(p => !p.IsNamespaced && p.IsLoaded(assetName)))
|
||||
foreach (IContentManager content in this.ContentManagers.Where(p => !p.IsNamespaced && p.IsLoaded(assetName, p.Language)))
|
||||
{
|
||||
object value = content.Load<object>(assetName, this.Language, useCache: true);
|
||||
values.Add(value);
|
||||
|
|
|
@ -169,10 +169,11 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
|
||||
/// <summary>Get whether the content manager has already loaded and cached the given asset.</summary>
|
||||
/// <param name="assetName">The asset path relative to the loader root directory, not including the <c>.xnb</c> extension.</param>
|
||||
public bool IsLoaded(string assetName)
|
||||
/// <param name="language">The language.</param>
|
||||
public bool IsLoaded(string assetName, LanguageCode language)
|
||||
{
|
||||
assetName = this.Cache.NormalizeKey(assetName);
|
||||
return this.IsNormalizedKeyLoaded(assetName);
|
||||
return this.IsNormalizedKeyLoaded(assetName, language);
|
||||
}
|
||||
|
||||
/// <summary>Get the cached asset keys.</summary>
|
||||
|
@ -315,7 +316,8 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
|
||||
/// <summary>Get whether an asset has already been loaded.</summary>
|
||||
/// <param name="normalizedAssetName">The normalized asset name.</param>
|
||||
protected abstract bool IsNormalizedKeyLoaded(string normalizedAssetName);
|
||||
/// <param name="language">The language to check.</param>
|
||||
protected abstract bool IsNormalizedKeyLoaded(string normalizedAssetName, LanguageCode language);
|
||||
|
||||
/// <summary>Get the locale codes (like <c>ja-JP</c>) used in asset keys.</summary>
|
||||
private IDictionary<LanguageCode, string> GetKeyLocales()
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
return this.Load<T>(newAssetName, newLanguage, useCache);
|
||||
|
||||
// get from cache
|
||||
if (useCache && this.IsLoaded(assetName))
|
||||
if (useCache && this.IsLoaded(assetName, language))
|
||||
return this.RawLoad<T>(assetName, language, useCache: true);
|
||||
|
||||
// get managed asset
|
||||
|
@ -151,11 +151,12 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
*********/
|
||||
/// <summary>Get whether an asset has already been loaded.</summary>
|
||||
/// <param name="normalizedAssetName">The normalized asset name.</param>
|
||||
protected override bool IsNormalizedKeyLoaded(string normalizedAssetName)
|
||||
/// <param name="language">The language to check.</param>
|
||||
protected override bool IsNormalizedKeyLoaded(string normalizedAssetName, LanguageCode language)
|
||||
{
|
||||
string cachedKey = null;
|
||||
bool localized =
|
||||
this.Language != LocalizedContentManager.LanguageCode.en
|
||||
language != LocalizedContentManager.LanguageCode.en
|
||||
&& !this.Coordinator.IsManagedAssetKey(normalizedAssetName)
|
||||
&& this.LocalizedAssetNames.TryGetValue(normalizedAssetName, out cachedKey);
|
||||
|
||||
|
@ -214,7 +215,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
private T RawLoad<T>(string assetName, LanguageCode language, bool useCache)
|
||||
{
|
||||
// use cached key
|
||||
if (this.LocalizedAssetNames.TryGetValue(assetName, out string cachedKey))
|
||||
if (language == this.Language && this.LocalizedAssetNames.TryGetValue(assetName, out string cachedKey))
|
||||
return base.RawLoad<T>(cachedKey, useCache);
|
||||
|
||||
// try translated key
|
||||
|
|
|
@ -58,7 +58,8 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
|
||||
/// <summary>Get whether the content manager has already loaded and cached the given asset.</summary>
|
||||
/// <param name="assetName">The asset path relative to the loader root directory, not including the <c>.xnb</c> extension.</param>
|
||||
bool IsLoaded(string assetName);
|
||||
/// <param name="language">The language.</param>
|
||||
bool IsLoaded(string assetName, LocalizedContentManager.LanguageCode language);
|
||||
|
||||
/// <summary>Get the cached asset keys.</summary>
|
||||
IEnumerable<string> GetAssetKeys();
|
||||
|
|
|
@ -211,7 +211,8 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
*********/
|
||||
/// <summary>Get whether an asset has already been loaded.</summary>
|
||||
/// <param name="normalizedAssetName">The normalized asset name.</param>
|
||||
protected override bool IsNormalizedKeyLoaded(string normalizedAssetName)
|
||||
/// <param name="language">The language to check.</param>
|
||||
protected override bool IsNormalizedKeyLoaded(string normalizedAssetName, LanguageCode language)
|
||||
{
|
||||
return this.Cache.ContainsKey(normalizedAssetName);
|
||||
}
|
||||
|
|
|
@ -35,19 +35,17 @@ namespace StardewModdingAPI.Framework
|
|||
this.ModRegistry = modRegistry;
|
||||
}
|
||||
|
||||
/// <summary>Log a deprecation warning for the old-style events.</summary>
|
||||
public void WarnForOldEvents()
|
||||
/// <summary>Get the source name for a mod from its unique ID.</summary>
|
||||
public string GetSourceNameFromStack()
|
||||
{
|
||||
this.Warn("legacy events", "2.9", DeprecationLevel.PendingRemoval);
|
||||
return this.ModRegistry.GetFromStack()?.DisplayName;
|
||||
}
|
||||
|
||||
/// <summary>Log a deprecation warning.</summary>
|
||||
/// <param name="nounPhrase">A noun phrase describing what is deprecated.</param>
|
||||
/// <param name="version">The SMAPI version which deprecated it.</param>
|
||||
/// <param name="severity">How deprecated the code is.</param>
|
||||
public void Warn(string nounPhrase, string version, DeprecationLevel severity)
|
||||
/// <summary>Get the source name for a mod from its unique ID.</summary>
|
||||
/// <param name="modId">The mod's unique ID.</param>
|
||||
public string GetSourceName(string modId)
|
||||
{
|
||||
this.Warn(this.ModRegistry.GetFromStack()?.DisplayName, nounPhrase, version, severity);
|
||||
return this.ModRegistry.Get(modId)?.DisplayName;
|
||||
}
|
||||
|
||||
/// <summary>Log a deprecation warning.</summary>
|
||||
|
@ -58,7 +56,7 @@ namespace StardewModdingAPI.Framework
|
|||
public void Warn(string source, string nounPhrase, string version, DeprecationLevel severity)
|
||||
{
|
||||
// ignore if already warned
|
||||
if (!this.MarkWarned(source ?? "<unknown>", nounPhrase, version))
|
||||
if (!this.MarkWarned(source ?? this.GetSourceNameFromStack() ?? "<unknown>", nounPhrase, version))
|
||||
return;
|
||||
|
||||
// queue warning
|
||||
|
@ -111,21 +109,16 @@ namespace StardewModdingAPI.Framework
|
|||
this.QueuedWarnings.Clear();
|
||||
}
|
||||
|
||||
/// <summary>Mark a deprecation warning as already logged.</summary>
|
||||
/// <param name="nounPhrase">A noun phrase describing what is deprecated (e.g. "the Extensions.AsInt32 method").</param>
|
||||
/// <param name="version">The SMAPI version which deprecated it.</param>
|
||||
/// <returns>Returns whether the deprecation was successfully marked as warned. Returns <c>false</c> if it was already marked.</returns>
|
||||
public bool MarkWarned(string nounPhrase, string version)
|
||||
{
|
||||
return this.MarkWarned(this.ModRegistry.GetFromStack()?.DisplayName, nounPhrase, version);
|
||||
}
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>Mark a deprecation warning as already logged.</summary>
|
||||
/// <param name="source">The friendly name of the assembly which used the deprecated code.</param>
|
||||
/// <param name="nounPhrase">A noun phrase describing what is deprecated (e.g. "the Extensions.AsInt32 method").</param>
|
||||
/// <param name="version">The SMAPI version which deprecated it.</param>
|
||||
/// <returns>Returns whether the deprecation was successfully marked as warned. Returns <c>false</c> if it was already marked.</returns>
|
||||
public bool MarkWarned(string source, string nounPhrase, string version)
|
||||
private bool MarkWarned(string source, string nounPhrase, string version)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(source))
|
||||
throw new InvalidOperationException("The deprecation source cannot be empty.");
|
||||
|
|
|
@ -36,8 +36,16 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Obsolete]
|
||||
public bool Trigger(string name, string[] arguments)
|
||||
{
|
||||
SCore.DeprecationManager.Warn(
|
||||
source: SCore.DeprecationManager.GetSourceName(this.ModID),
|
||||
nounPhrase: $"{nameof(IModHelper)}.{nameof(IModHelper.ConsoleCommands)}.{nameof(ICommandHelper.Trigger)}",
|
||||
version: "3.8.1",
|
||||
severity: DeprecationLevel.Notice
|
||||
);
|
||||
|
||||
return this.CommandManager.Trigger(name, arguments);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -765,6 +765,9 @@ namespace StardewModdingAPI.Framework
|
|||
|
||||
this.Monitor.Log(context);
|
||||
|
||||
// apply save fixes
|
||||
this.ApplySaveFixes();
|
||||
|
||||
// raise events
|
||||
this.OnLoadStageChanged(LoadStage.Ready);
|
||||
events.SaveLoaded.RaiseEmpty();
|
||||
|
@ -1054,6 +1057,40 @@ namespace StardewModdingAPI.Framework
|
|||
this.EventManager.ReturnedToTitle.RaiseEmpty();
|
||||
}
|
||||
|
||||
/// <summary>Apply fixes to the save after it's loaded.</summary>
|
||||
private void ApplySaveFixes()
|
||||
{
|
||||
// get last SMAPI version used with this save
|
||||
const string migrationKey = "Pathoschild.SMAPI/api-version";
|
||||
if (!Game1.CustomData.TryGetValue(migrationKey, out string rawVersion) || !SemanticVersion.TryParse(rawVersion, out ISemanticVersion lastVersion))
|
||||
lastVersion = new SemanticVersion(3, 8, 0);
|
||||
|
||||
// fix bundle corruption in SMAPI 3.8.0
|
||||
// For non-English players who created a new save in SMAPI 3.8.0, bundle data was
|
||||
// incorrectly translated which caused the code to crash whenever the game tried to
|
||||
// read it.
|
||||
if (lastVersion.IsOlderThan(new SemanticVersion(3, 8, 1)) && Game1.netWorldState?.Value?.BundleData != null)
|
||||
{
|
||||
var oldData = new Dictionary<string, string>(Game1.netWorldState.Value.BundleData);
|
||||
|
||||
try
|
||||
{
|
||||
Game1.applySaveFix(SaveGame.SaveFixes.FixBotchedBundleData);
|
||||
bool changed = Game1.netWorldState.Value.BundleData.Any(p => oldData.TryGetValue(p.Key, out string oldValue) && oldValue != p.Value);
|
||||
if (changed)
|
||||
this.Monitor.Log("Found broken community center bundles and fixed them automatically.", LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Monitor.Log("Failed to verify community center data.", LogLevel.Error); // should never happen
|
||||
this.Monitor.Log($"Technical details: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
// update last run
|
||||
Game1.CustomData[migrationKey] = Constants.ApiVersion.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Raised after custom content is removed from the save data to avoid a crash.</summary>
|
||||
internal void OnSaveContentRemoved()
|
||||
{
|
||||
|
|
|
@ -21,6 +21,9 @@ namespace StardewModdingAPI.Framework.StateTracking
|
|||
/// <summary>Tracks changes to the list of active mine locations.</summary>
|
||||
private readonly ICollectionWatcher<MineShaft> MineLocationListWatcher;
|
||||
|
||||
/// <summary>Tracks changes to the list of active volcano locations.</summary>
|
||||
private readonly ICollectionWatcher<GameLocation> VolcanoLocationListWatcher;
|
||||
|
||||
/// <summary>A lookup of the tracked locations.</summary>
|
||||
private IDictionary<GameLocation, LocationTracker> LocationDict { get; } = new Dictionary<GameLocation, LocationTracker>(new ObjectReferenceComparer<GameLocation>());
|
||||
|
||||
|
@ -53,10 +56,12 @@ namespace StardewModdingAPI.Framework.StateTracking
|
|||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="locations">The game's list of locations.</param>
|
||||
/// <param name="activeMineLocations">The game's list of active mine locations.</param>
|
||||
public WorldLocationsTracker(ObservableCollection<GameLocation> locations, IList<MineShaft> activeMineLocations)
|
||||
/// <param name="activeVolcanoLocations">The game's list of active volcano locations.</param>
|
||||
public WorldLocationsTracker(ObservableCollection<GameLocation> locations, IList<MineShaft> activeMineLocations, IList<VolcanoDungeon> activeVolcanoLocations)
|
||||
{
|
||||
this.LocationListWatcher = WatcherFactory.ForObservableCollection(locations);
|
||||
this.MineLocationListWatcher = WatcherFactory.ForReferenceList(activeMineLocations);
|
||||
this.VolcanoLocationListWatcher = WatcherFactory.ForReferenceList(activeVolcanoLocations);
|
||||
}
|
||||
|
||||
/// <summary>Update the current value if needed.</summary>
|
||||
|
@ -65,6 +70,7 @@ namespace StardewModdingAPI.Framework.StateTracking
|
|||
// update watchers
|
||||
this.LocationListWatcher.Update();
|
||||
this.MineLocationListWatcher.Update();
|
||||
this.VolcanoLocationListWatcher.Update();
|
||||
foreach (LocationTracker watcher in this.Locations)
|
||||
watcher.Update();
|
||||
|
||||
|
@ -79,6 +85,11 @@ namespace StardewModdingAPI.Framework.StateTracking
|
|||
this.Remove(this.MineLocationListWatcher.Removed);
|
||||
this.Add(this.MineLocationListWatcher.Added);
|
||||
}
|
||||
if (this.VolcanoLocationListWatcher.IsChanged)
|
||||
{
|
||||
this.Remove(this.VolcanoLocationListWatcher.Removed);
|
||||
this.Add(this.VolcanoLocationListWatcher.Added);
|
||||
}
|
||||
|
||||
// detect building changed
|
||||
foreach (LocationTracker watcher in this.Locations.Where(p => p.BuildingsWatcher.IsChanged).ToArray())
|
||||
|
@ -107,6 +118,7 @@ namespace StardewModdingAPI.Framework.StateTracking
|
|||
this.Added.Clear();
|
||||
this.LocationListWatcher.Reset();
|
||||
this.MineLocationListWatcher.Reset();
|
||||
this.VolcanoLocationListWatcher.Reset();
|
||||
}
|
||||
|
||||
/// <summary>Set the current value as the baseline.</summary>
|
||||
|
@ -243,6 +255,7 @@ namespace StardewModdingAPI.Framework.StateTracking
|
|||
{
|
||||
yield return this.LocationListWatcher;
|
||||
yield return this.MineLocationListWatcher;
|
||||
yield return this.VolcanoLocationListWatcher;
|
||||
foreach (LocationTracker watcher in this.Locations)
|
||||
yield return watcher;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace StardewModdingAPI.Framework
|
|||
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);
|
||||
this.LocationsWatcher = new WorldLocationsTracker(gameLocations, MineShaft.activeMines, VolcanoDungeon.activeLevels);
|
||||
this.LocaleWatcher = WatcherFactory.ForGenericEquality(() => LocalizedContentManager.CurrentLanguageCode);
|
||||
this.Watchers.AddRange(new IWatcher[]
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue