|
15 | 15 | using StardewModdingAPI.Internal;
|
16 | 16 | using StardewModdingAPI.Metadata;
|
17 | 17 | using StardewModdingAPI.Toolkit.Serialization;
|
18 |
| -using StardewModdingAPI.Toolkit.Utilities; |
19 | 18 | using StardewModdingAPI.Toolkit.Utilities.PathLookups;
|
| 19 | +using StardewModdingAPI.Utilities; |
20 | 20 | using StardewValley;
|
21 | 21 | using StardewValley.GameData;
|
22 | 22 | using xTile;
|
@@ -110,6 +110,10 @@ internal class ContentCoordinator : IDisposable
|
110 | 110 | /// <summary>The absolute path to the <see cref="ContentManager.RootDirectory"/>.</summary>
|
111 | 111 | public string FullRootDirectory { get; }
|
112 | 112 |
|
| 113 | + /// <summary>A lookup which tracks whether each given asset name has a localized form.</summary> |
| 114 | + /// <remarks>This is a per-screen equivalent to the base game's <see cref="LocalizedContentManager.localizedAssetNames"/> field, since mods may provide different assets per-screen.</remarks> |
| 115 | + public PerScreen<Dictionary<string, string>> LocalizedAssetNames { get; } = new(() => new()); |
| 116 | + |
113 | 117 |
|
114 | 118 | /*********
|
115 | 119 | ** Public methods
|
@@ -245,6 +249,9 @@ public void OnLocaleChanged()
|
245 | 249 | {
|
246 | 250 | this.VanillaContentManager.Unload();
|
247 | 251 | });
|
| 252 | + |
| 253 | + // forget localized flags (to match the logic in Game1.TranslateFields, which is called on language change) |
| 254 | + this.LocalizedAssetNames.Value.Clear(); |
248 | 255 | }
|
249 | 256 |
|
250 | 257 | /// <summary>Clean up when the player is returning to the title screen.</summary>
|
@@ -275,6 +282,10 @@ public void OnReturningToTitleScreen()
|
275 | 282 | // their changes, the assets won't be found in the cache so no changes will be propagated.
|
276 | 283 | if (LocalizedContentManager.CurrentLanguageCode != LocalizedContentManager.LanguageCode.en)
|
277 | 284 | this.InvalidateCache((contentManager, _, _) => contentManager is GameContentManager);
|
| 285 | + |
| 286 | + // clear the localized assets lookup (to match the logic in Game1.CleanupReturningToTitle) |
| 287 | + foreach ((_, Dictionary<string, string> localizedAssets) in this.LocalizedAssetNames.GetActiveValues()) |
| 288 | + localizedAssets.Clear(); |
278 | 289 | }
|
279 | 290 |
|
280 | 291 | /// <summary>Parse a raw asset name.</summary>
|
@@ -411,12 +422,15 @@ public IEnumerable<IAssetName> InvalidateCache(Func<IContentManager, string, Typ
|
411 | 422 | // A mod might provide a localized variant of a normally non-localized asset (like
|
412 | 423 | // `Maps/MovieTheater.fr-FR`). When the asset is invalidated, we need to recheck
|
413 | 424 | // whether the asset is localized in case it stops providing it.
|
414 |
| - foreach (IAssetName assetName in invalidatedAssets.Keys) |
415 | 425 | {
|
416 |
| - LocalizedContentManager.localizedAssetNames.Remove(assetName.Name); |
| 426 | + Dictionary<string, string> localizedAssetNames = this.LocalizedAssetNames.Value; |
| 427 | + foreach (IAssetName assetName in invalidatedAssets.Keys) |
| 428 | + { |
| 429 | + localizedAssetNames.Remove(assetName.Name); |
417 | 430 |
|
418 |
| - if (LocalizedContentManager.localizedAssetNames.TryGetValue(assetName.BaseName, out string? targetForBaseKey) && targetForBaseKey == assetName.Name) |
419 |
| - LocalizedContentManager.localizedAssetNames.Remove(assetName.BaseName); |
| 431 | + if (localizedAssetNames.TryGetValue(assetName.BaseName, out string? targetForBaseKey) && targetForBaseKey == assetName.Name) |
| 432 | + localizedAssetNames.Remove(assetName.BaseName); |
| 433 | + } |
420 | 434 | }
|
421 | 435 |
|
422 | 436 | // special case: maps may be loaded through a temporary content manager that's removed while the map is still in use.
|
|
0 commit comments