diff --git a/build/common.targets b/build/common.targets index f2b05acfc..892084caf 100644 --- a/build/common.targets +++ b/build/common.targets @@ -7,7 +7,7 @@ repo. It imports the other MSBuild files as needed. - 4.1.4 + 4.1.5 SMAPI latest $(AssemblySearchPaths);{GAC} diff --git a/docs/release-notes.md b/docs/release-notes.md index e50b98c18..b117d2274 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,6 +1,16 @@ ← [README](README.md) # Release notes +## 4.1.5 +Released 07 November 2024 for Stardew Valley 1.6.10 or later. + +* For players: + * Updated mod compatibility list. + * Fixed translation issues in some mods with SMAPI 4.1._x_. + +* For mod authors: + * Fixed `translation.UsePlaceholder(false)` also disabling custom fallback text in recent builds, not just the "no translation" placeholder. + ## 4.1.4 Released 05 November 2024 for Stardew Valley 1.6.10 or later. diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index f180e6388..25872837b 100644 --- a/src/SMAPI.Mods.ConsoleCommands/manifest.json +++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json @@ -1,9 +1,9 @@ { "Name": "Console Commands", "Author": "SMAPI", - "Version": "4.1.4", + "Version": "4.1.5", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "4.1.4" + "MinimumApiVersion": "4.1.5" } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index d13f07350..d11d2ecf2 100644 --- a/src/SMAPI.Mods.SaveBackup/manifest.json +++ b/src/SMAPI.Mods.SaveBackup/manifest.json @@ -1,9 +1,9 @@ { "Name": "Save Backup", "Author": "SMAPI", - "Version": "4.1.4", + "Version": "4.1.5", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueID": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "4.1.4" + "MinimumApiVersion": "4.1.5" } diff --git a/src/SMAPI.Web/wwwroot/SMAPI.metadata.json b/src/SMAPI.Web/wwwroot/SMAPI.metadata.json index 5df40feba..35ff87994 100644 --- a/src/SMAPI.Web/wwwroot/SMAPI.metadata.json +++ b/src/SMAPI.Web/wwwroot/SMAPI.metadata.json @@ -74,10 +74,6 @@ "ID": "Entoarox.EntoaroxFramework", "Default | UpdateKey": "Nexus:2269" }, - "JSON Assets": { - "ID": "spacechase0.JsonAssets", - "Default | UpdateKey": "Nexus:1720" - }, "Mail Framework": { "ID": "DIGUS.MailFrameworkMod", "Default | UpdateKey": "Nexus:1536" @@ -98,10 +94,6 @@ "ID": "Omegasis.StardustCore", "Default | UpdateKey": "Nexus:2341" }, - "TMXL Map Toolkit": { - "ID": "Platonymous.TMXLoader", - "Default | UpdateKey": "Nexus:1820" - }, /********* ** Obsolete @@ -148,6 +140,44 @@ "~ | StatusReasonPhrase": "split-screen mode was added in Stardew Valley 1.5. You can delete this mod." }, + /********* + ** Broke in SDV 1.6.9 + *********/ + "Catalogue Indicator": { + "ID": "com.anthonyhilyard.CatalogueIndicator", + "~1.0.0 | Status": "AssumeBroken", + "~1.0.0 | StatusReasonDetails": "ItemStockInformation references crash at runtime" + }, + "Heart Event Helper": { + "ID": "bungus.HeartEventHelper", + "~1.0.6 | Status": "AssumeBroken", + "~1.0.6 | StatusReasonDetails": "breaks question dialogues (e.g. Lewis' start-festival-event question)" + }, + "Json Assets": { + "ID": "spacechase0.JsonAssets", + "~1.1.18 | Status": "AssumeBroken", + "~1.1.18 | StatusReasonDetails": "ItemStockInformation references crash at runtime", + + "Default | UpdateKey": "Nexus:1720" + }, + "Shop Tile Framework": { + "ID": "Cherry.ShopTileFramework", + "~1.0.10-alpha-20240227 | Status": "AssumeBroken", + "~1.0.10-alpha-20240227 | StatusReasonDetails": "ItemStockInformation references crash at runtime" + }, + "Swim (FlyingTNT)": { + "ID": "FlyingTNT.Swim", + "~1.6.4 | Status": "AssumeBroken", + "~1.6.4 | StatusReasonDetails": "Harmony patches fail at runtime" + }, + "TMXL Map Toolkit": { + "ID": "Platonymous.TMXLoader", + "~1.24.3-alpha.20240226 | Status": "AssumeBroken", + "~1.24.3-alpha.20240226 | StatusReasonDetails": "Harmony patches fail at runtime", + + "Default | UpdateKey": "Nexus:1820" + }, + /********* ** Broke in SDV 1.6 *********/ diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index 69e7c9037..5e8d42599 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -49,7 +49,7 @@ internal static class EarlyConstants internal static int? LogScreenId { get; set; } /// SMAPI's current raw semantic version. - internal static string RawApiVersion = "4.1.4"; + internal static string RawApiVersion = "4.1.5"; } /// Contains SMAPI's constants and assumptions. diff --git a/src/SMAPI/Translation.cs b/src/SMAPI/Translation.cs index 6d1dc4147..478b91c9a 100644 --- a/src/SMAPI/Translation.cs +++ b/src/SMAPI/Translation.cs @@ -27,10 +27,10 @@ public class Translation /// The underlying translation text. private readonly string? Text; - /// The value to return if the translations is undefined. - private string? Placeholder { get; init; } + /// The custom value to return if the translations is undefined. + private string? CustomDefault { get; init; } - /// Whether to use if the translation is null or empty. + /// Whether to show a placeholder if the and are both is null or empty. private bool ShouldUsePlaceholder { get; init; } /// Whether to process gender-switch blocks in translation text, if any. @@ -65,7 +65,6 @@ internal Translation(string locale, string key, string? text) this.Locale = locale; this.Key = key; this.Text = text; - this.Placeholder = string.Format(Translation.PlaceholderText, key); this.ShouldUsePlaceholder = true; this.ShouldApplyGenderSwitchBlocks = true; } @@ -75,28 +74,27 @@ internal Translation(string locale, string key, string? text) internal Translation(Translation other) : this(other.Locale, other.Key, other.Text) { - this.Placeholder = other.Placeholder; + this.CustomDefault = other.CustomDefault; this.ShouldUsePlaceholder = other.ShouldUsePlaceholder; this.ShouldApplyGenderSwitchBlocks = other.ShouldApplyGenderSwitchBlocks; this.TokenValues = other.TokenValues; this.ForceGender = other.ForceGender; } - /// Replace the text if it's null or empty. If you set a null or empty value, the translation will show the fallback "no translation" placeholder (see if you want to disable that). + /// The custom text to use if the text is null or empty. If set to null or empty value, defaults to a fallback "no translation" placeholder unless you disable that via . /// The default value. /// Returns a new instance if this would change the result, else the current instance. public Translation Default(string? @default) { - if (this.HasValue()) - return this; + if (string.IsNullOrEmpty(@default)) + @default = null; - string placeholder = string.IsNullOrEmpty(@default) - ? string.Format(Translation.PlaceholderText, this.Key) - : @default; + if (this.HasValue() || @default == this.CustomDefault) + return this; return new Translation(this) { - Placeholder = placeholder + CustomDefault = @default }; } @@ -160,18 +158,22 @@ public bool HasValue() } /// Get the translation text. Calling this method isn't strictly necessary, since you can assign a value directly to a string. - /// Limitation with nullable reference types: if there's no text and you disabled the fallback via , this will return null but the return value will still be marked non-nullable. + /// Limitation with nullable reference types: if there's no text, no , and you disabled the fallback via , this will return null but the return value will still be marked non-nullable. public override string ToString() { if (!this.Cached) { - string? rawText = this.FormatText( - this.ShouldUsePlaceholder && !this.HasValue() - ? this.Placeholder - : this.Text - ); + string? rawText; + if (this.HasValue()) + rawText = this.Text; + else if (this.CustomDefault != null) + rawText = this.CustomDefault; + else if (this.ShouldUsePlaceholder) + rawText = string.Format(Translation.PlaceholderText, this.Key); + else + rawText = null; - this.CachedResult = rawText; + this.CachedResult = this.FormatText(rawText); this.Cached = true; }