From 33c7a0392cc9f39f885f50774e980a0bf3643fd6 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 17 Aug 2021 23:25:09 -0400 Subject: remove libgdiplus workaround on macOS This is no longer needed after the .NET 5 migration. --- src/SMAPI/Framework/ContentManagers/ModContentManager.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/SMAPI/Framework/ContentManagers') diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs index d24ffb81..bf0b54b9 100644 --- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs @@ -7,7 +7,6 @@ using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI.Framework.Exceptions; using StardewModdingAPI.Framework.Reflection; -using StardewModdingAPI.Internal; using StardewModdingAPI.Toolkit.Serialization; using StardewModdingAPI.Toolkit.Utilities; using StardewValley; @@ -177,8 +176,6 @@ namespace StardewModdingAPI.Framework.ContentManagers } catch (Exception ex) when (!(ex is SContentLoadException)) { - if (ex.GetInnermostException() is DllNotFoundException dllEx && dllEx.Message == "libgdiplus.dylib") - throw GetContentError("couldn't find libgdiplus, which is needed to load mod images. Make sure Mono is installed and you're running the game through the normal launcher."); throw new SContentLoadException($"The content manager failed loading content asset '{assetName}' from {this.Name}.", ex); } -- cgit From 25384ce6bc1b05cb5150915ab40effe7749f683b Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 15 Sep 2021 00:27:17 -0400 Subject: update for custom languages --- src/SMAPI/Framework/ContentCoordinator.cs | 41 ++++++++++++++++++++++ .../ContentManagers/BaseContentManager.cs | 17 +-------- .../ContentManagers/GameContentManager.cs | 2 +- src/SMAPI/Framework/SCore.cs | 4 +-- 4 files changed, 45 insertions(+), 19 deletions(-) (limited to 'src/SMAPI/Framework/ContentManagers') diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index d0e759c2..b6f1669a 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -64,6 +64,9 @@ namespace StardewModdingAPI.Framework /// An unmodified content manager which doesn't intercept assets, used to compare asset data. private readonly LocalizedContentManager VanillaContentManager; + /// The language enum values indexed by locale code. + private Lazy> LocaleCodes; + /********* ** Accessors @@ -133,6 +136,7 @@ namespace StardewModdingAPI.Framework this.ContentManagers.Add(contentManagerForAssetPropagation); this.VanillaContentManager = new LocalizedContentManager(serviceProvider, rootDirectory); this.CoreAssets = new CoreAssetPropagator(this.MainContentManager, contentManagerForAssetPropagation, this.Monitor, reflection, aggressiveMemoryOptimizations); + this.LocaleCodes = new Lazy>(this.GetLocaleCodes); } /// Get a new content manager which handles reading files from the game content folder with support for interception. @@ -195,6 +199,10 @@ namespace StardewModdingAPI.Framework /// Perform any cleanup needed when the locale changes. public void OnLocaleChanged() { + // rebuild locale cache (which may change due to custom mod languages) + this.LocaleCodes = new Lazy>(this.GetLocaleCodes); + + // reload affected content this.ContentManagerLock.InReadLock(() => { foreach (IContentManager contentManager in this.ContentManagers) @@ -408,6 +416,25 @@ namespace StardewModdingAPI.Framework return tilesheets ?? new TilesheetReference[0]; } + /// Get the language enum which corresponds to a locale code (e.g. given fr-FR). + /// The locale code to search. This must exactly match the language; no fallback is performed. + /// The matched language enum, if any. + /// Returns whether a valid language was found. + public bool TryGetLanguageEnum(string locale, out LocalizedContentManager.LanguageCode language) + { + return this.LocaleCodes.Value.TryGetValue(locale, out language); + } + + /// Get the locale code which corresponds to a language enum (e.g. fr-FR given ). + /// The language enum to search. + public string GetLocaleCode(LocalizedContentManager.LanguageCode language) + { + if (language == LocalizedContentManager.LanguageCode.mod && LocalizedContentManager.CurrentModLanguage == null) + return null; + + return Game1.content.LanguageCodeString(language); + } + /// Dispose held resources. public void Dispose() { @@ -457,5 +484,19 @@ namespace StardewModdingAPI.Framework return false; } } + + /// Get the language enums (like ) indexed by locale code (like ja-JP). + private IDictionary GetLocaleCodes() + { + IDictionary map = new Dictionary(); + foreach (LocalizedContentManager.LanguageCode code in Enum.GetValues(typeof(LocalizedContentManager.LanguageCode))) + { + string locale = this.GetLocaleCode(code); + if (locale != null) + map[locale] = code; + } + + return map; + } } } diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs index 7244a534..5645c0fa 100644 --- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs @@ -38,9 +38,6 @@ namespace StardewModdingAPI.Framework.ContentManagers /// A callback to invoke when the content manager is being disposed. private readonly Action OnDisposing; - /// The language enum values indexed by locale code. - protected IDictionary LanguageCodes { get; } - /// A list of disposable assets. private readonly List> Disposables = new List>(); @@ -92,7 +89,6 @@ namespace StardewModdingAPI.Framework.ContentManagers this.AggressiveMemoryOptimizations = aggressiveMemoryOptimizations; // get asset data - this.LanguageCodes = this.GetKeyLocales().ToDictionary(p => p.Value, p => p.Key, StringComparer.OrdinalIgnoreCase); this.BaseDisposableReferences = reflection.GetField>(this, "disposableAssets").GetValue(); } @@ -292,7 +288,7 @@ namespace StardewModdingAPI.Framework.ContentManagers if (lastSepIndex >= 0) { string suffix = cacheKey.Substring(lastSepIndex + 1, cacheKey.Length - lastSepIndex - 1); - if (this.LanguageCodes.ContainsKey(suffix)) + if (this.Coordinator.TryGetLanguageEnum(suffix, out _)) { assetName = cacheKey.Substring(0, lastSepIndex); localeCode = cacheKey.Substring(lastSepIndex + 1, cacheKey.Length - lastSepIndex - 1); @@ -311,17 +307,6 @@ namespace StardewModdingAPI.Framework.ContentManagers /// The language to check. protected abstract bool IsNormalizedKeyLoaded(string normalizedAssetName, LanguageCode language); - /// Get the locale codes (like ja-JP) used in asset keys. - private IDictionary GetKeyLocales() - { - // create locale => code map - IDictionary map = new Dictionary(); - foreach (LanguageCode code in Enum.GetValues(typeof(LanguageCode))) - map[code] = this.GetLocale(code); - - return map; - } - /// Get the asset name from a cache key. /// The input cache key. private string GetAssetName(string cacheKey) diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs index 38bcf153..7a49dd36 100644 --- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs @@ -249,7 +249,7 @@ namespace StardewModdingAPI.Framework.ContentManagers // extract language code int splitIndex = rawAsset.LastIndexOf('.'); - if (splitIndex != -1 && this.LanguageCodes.TryGetValue(rawAsset.Substring(splitIndex + 1), out language)) + if (splitIndex != -1 && this.Coordinator.TryGetLanguageEnum(rawAsset.Substring(splitIndex + 1), out language)) { assetName = rawAsset.Substring(0, splitIndex); return true; diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 947284a8..a0467daa 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -751,7 +751,7 @@ namespace StardewModdingAPI.Framework ** Locale changed events *********/ if (state.Locale.IsChanged) - this.Monitor.Log($"Context: locale set to {state.Locale.New}."); + this.Monitor.Log($"Context: locale set to {state.Locale.New} ({this.ContentCore.GetLocaleCode(state.Locale.New)})."); /********* ** Load / return-to-title events @@ -761,7 +761,7 @@ namespace StardewModdingAPI.Framework else if (Context.IsWorldReady && Context.LoadStage != LoadStage.Ready) { // print context - string context = $"Context: loaded save '{Constants.SaveFolderName}', starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}, locale set to {this.ContentCore.Language}."; + string context = $"Context: loaded save '{Constants.SaveFolderName}', starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}, locale set to {this.ContentCore.GetLocale()}."; if (Context.IsMultiplayer) { int onlineCount = Game1.getOnlineFarmers().Count(); -- cgit From d1d09ae1df63826dd453aa0347d668f420754ed7 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 25 Nov 2021 23:01:14 -0500 Subject: add support for loading BmFont files for custom languages --- docs/release-notes.md | 1 + src/SMAPI/Framework/ContentManagers/ModContentManager.cs | 11 ++++++++++- src/SMAPI/SMAPI.csproj | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/ContentManagers') diff --git a/docs/release-notes.md b/docs/release-notes.md index 69eab3ec..d60156d5 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -5,6 +5,7 @@ * For players: * Updated for Stardew Valley 1.5.5. * Updated compatibility list. + * Added support for loading BmFont `.fnt` files for [custom languages](https://stardewvalleywiki.com/Modding:Custom_languages) through the [content API](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Content). * Added `set_farm_type` [console command](https://stardewvalleywiki.com/Modding:Console_commands#Console_commands) to change the current farm type. * Fixed installer window closing immediately if the installer crashed. diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs index bf0b54b9..beb90a5d 100644 --- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs @@ -2,6 +2,7 @@ using System; using System.Globalization; using System.IO; using System.Linq; +using BmFont; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; @@ -129,6 +130,14 @@ namespace StardewModdingAPI.Framework.ContentManagers } break; + // unpacked Bitmap font + case ".fnt": + { + string source = File.ReadAllText(file.FullName); + asset = (T)(object)new XmlSource(source); + } + break; + // unpacked data case ".json": { @@ -171,7 +180,7 @@ namespace StardewModdingAPI.Framework.ContentManagers break; default: - throw GetContentError($"unknown file extension '{file.Extension}'; must be one of '.json', '.png', '.tbin', or '.xnb'."); + throw GetContentError($"unknown file extension '{file.Extension}'; must be one of '.fnt', '.json', '.png', '.tbin', or '.xnb'."); } } catch (Exception ex) when (!(ex is SContentLoadException)) diff --git a/src/SMAPI/SMAPI.csproj b/src/SMAPI/SMAPI.csproj index 4f9aa9b1..b99028da 100644 --- a/src/SMAPI/SMAPI.csproj +++ b/src/SMAPI/SMAPI.csproj @@ -31,6 +31,7 @@ + -- cgit