diff --git a/build/common.targets b/build/common.targets index 82a3ef7f2..aec6e8791 100644 --- a/build/common.targets +++ b/build/common.targets @@ -7,7 +7,7 @@ repo. It imports the other MSBuild files as needed. - 3.18.5 + 3.18.6 SMAPI latest $(AssemblySearchPaths);{GAC} diff --git a/docs/release-notes.md b/docs/release-notes.md index 34cbf74d1..3cc2239db 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -7,6 +7,19 @@ _If needed, you can update to SMAPI 3.16.0 first and then install the latest version._ --> +## 3.18.6 +Released 05 October 2023 for Stardew Valley 1.5.6 or later. + +* For players: + * Fixed SpriteMaster compatibility in SMAPI 3.18.5+ with temporary workaround. + * Fixed `player_add` and `list_items` console commands not including Pickled Ginger, and returning Honey instead of Wild Honey _(in Console Commands)_. + +* For mod authors: + * Added asset propagation for `LooseSprites/chatBox` and `LooseSprites/emojis`. + +* For the web UI: + * Fixed uploaded log/JSON file expiry alway shown as renewed. + ## 3.18.5 Released 26 August 2023 for Stardew Valley 1.5.6 or later. @@ -77,7 +90,7 @@ Released 09 January 2023 for Stardew Valley 1.5.6 or later. * For players: * Fixed empty save backups for some macOS players. - * Fixed `player_add` console command not handling custom slingshots correctly (thanks too DaLion!). + * Fixed `player_add` console command not handling custom slingshots correctly (thanks to DaLion!). * For mod authors: * Added `DelegatingModHooks` utility for mods which need to override SMAPI's mod hooks directly. diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs index c46195773..52bf149ec 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs @@ -171,21 +171,31 @@ public IEnumerable GetAll(ItemType[]? itemTypes = null, bool inc else if (ShouldGet(ItemType.Object)) { // spawn main item - SObject? item = null; - yield return this.TryCreate(ItemType.Object, id, p => + SearchableItem? mainItem = this.TryCreate(ItemType.Object, id, p => { - return item = (p.ID == 812 // roe - ? new ColoredObject(p.ID, 1, Color.White) - : new SObject(p.ID, 1) - ); + // roe + if (p.ID == 812) + return new ColoredObject(p.ID, 1, Color.White); + + // Wild Honey + if (p.ID == 340) + { + return new SObject(Vector2.Zero, 340, "Wild Honey", false, true, false, false) + { + Name = "Wild Honey", + preservedParentSheetIndex = { -1 } + }; + } + + // else plain item + return new SObject(p.ID, 1); }); - if (item == null) - continue; + yield return mainItem; // flavored items - if (includeVariants) + if (includeVariants && mainItem?.Item != null) { - foreach (SearchableItem? variant in this.GetFlavoredObjectVariants(item)) + foreach (SearchableItem? variant in this.GetFlavoredObjectVariants((SObject)mainItem.Item)) yield return variant; } } @@ -356,6 +366,18 @@ select item } break; } + + // ginger => pickled ginger + if (id == 829 && item.Category != SObject.VegetableCategory) + { + yield return this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + id, _ => new SObject(342, 1) + { + Name = $"Pickled {item.Name}", + Price = 50 + item.Price * 2, + preserve = { SObject.PreserveType.Pickle }, + preservedParentSheetIndex = { id } + }); + } } /// Get optimized lookups to match items which produce roe in a fish pond. diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index 4ed5ea2e6..a97124e50 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": "3.18.5", + "Version": "3.18.6", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "3.18.5" + "MinimumApiVersion": "3.18.6" } diff --git a/src/SMAPI.Mods.ErrorHandler/manifest.json b/src/SMAPI.Mods.ErrorHandler/manifest.json index 1ff8b190b..fb268fa03 100644 --- a/src/SMAPI.Mods.ErrorHandler/manifest.json +++ b/src/SMAPI.Mods.ErrorHandler/manifest.json @@ -1,9 +1,9 @@ { "Name": "Error Handler", "Author": "SMAPI", - "Version": "3.18.5", + "Version": "3.18.6", "Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.", "UniqueID": "SMAPI.ErrorHandler", "EntryDll": "ErrorHandler.dll", - "MinimumApiVersion": "3.18.5" + "MinimumApiVersion": "3.18.6" } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index 84c2a9c90..94a1ce79c 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": "3.18.5", + "Version": "3.18.6", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueID": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "3.18.5" + "MinimumApiVersion": "3.18.6" } diff --git a/src/SMAPI.Web/Framework/Storage/StorageProvider.cs b/src/SMAPI.Web/Framework/Storage/StorageProvider.cs index 062bfa558..f18aa5bdf 100644 --- a/src/SMAPI.Web/Framework/Storage/StorageProvider.cs +++ b/src/SMAPI.Web/Framework/Storage/StorageProvider.cs @@ -107,9 +107,12 @@ public async Task GetAsync(string id, bool forceRenew) string content = this.GzipHelper.DecompressString(await reader.ReadToEndAsync()); // extend expiry if needed + DateTimeOffset newExpiry = oldExpiry; if (forceRenew || this.IsWithinAutoRenewalWindow(result.Details.LastModified)) + { await blob.SetMetadataAsync(new Dictionary { ["expiryRenewed"] = DateTime.UtcNow.ToString("O") }); // change the blob's last-modified date (the specific property set doesn't matter) - DateTimeOffset newExpiry = this.GetExpiry(DateTimeOffset.UtcNow); + newExpiry = this.GetExpiry(DateTimeOffset.UtcNow); + } // build model return new StoredFileInfo(content, oldExpiry, newExpiry); diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index 475e6c7d2..eab900f92 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -52,7 +52,7 @@ internal static class EarlyConstants internal static int? LogScreenId { get; set; } /// SMAPI's current raw semantic version. - internal static string RawApiVersion = "3.18.5"; + internal static string RawApiVersion = "3.18.6"; } /// Contains SMAPI's constants and assumptions. diff --git a/src/SMAPI/Events/AssetEditPriority.cs b/src/SMAPI/Events/AssetEditPriority.cs index d41dfd7d9..977c91568 100644 --- a/src/SMAPI/Events/AssetEditPriority.cs +++ b/src/SMAPI/Events/AssetEditPriority.cs @@ -1,7 +1,7 @@ namespace StardewModdingAPI.Events { /// The priority for an asset edit when multiple apply for the same asset. - /// You can also specify arbitrary intermediate values, like AssetLoadPriority.Low + 5. + /// You can also specify arbitrary intermediate values, like AssetEditPriority.Early + 5. public enum AssetEditPriority { /// This edit should be applied before (i.e. 'under') edits. diff --git a/src/SMAPI/Framework/ModLoading/RewriteFacades/AccessToolsFacade.cs b/src/SMAPI/Framework/ModLoading/RewriteFacades/AccessToolsFacade.cs new file mode 100644 index 000000000..e4adbdd59 --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/RewriteFacades/AccessToolsFacade.cs @@ -0,0 +1,13 @@ +#if SMAPI_DEPRECATED +using System; +using System.Diagnostics.CodeAnalysis; +using StardewModdingAPI.Framework.ModLoading.Framework; + +namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades +{ + /// Stub version of to avoid breaking SpriteMaster. + [Obsolete("This only exists for compatibility with older versions of SpriteMaster.")] + [SuppressMessage("ReSharper", "UnusedMember.Global", Justification = SuppressReasons.UsedViaRewriting)] + public class AccessToolsFacade { } +} +#endif diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index 8b55faeff..b48b6f96b 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -395,6 +395,18 @@ static ISet GetWarpSet(GameLocation location) Game1.birdsSpriteSheet = content.Load(key); return true; + case "loosesprites/chatbox": // ChatBox constructor + if (Game1.chatBox?.chatBox != null) + { + Texture2D texture = content.Load(key); + + this.Reflection.GetField(Game1.chatBox.chatBox, "_textBoxTexture").SetValue(texture); + this.Reflection.GetField(Game1.chatBox.emojiMenu, "chatBoxTexture").SetValue(texture); + + return true; + } + return false; + case "loosesprites/concessions": // Game1.LoadContent Game1.concessionsSpriteSheet = content.Load(key); return true; @@ -423,6 +435,18 @@ static ISet GetWarpSet(GameLocation location) Game1.daybg = content.Load(key); return true; + case "loosesprites/emojis": // ChatBox constructor + if (Game1.chatBox != null) + { + Texture2D texture = content.Load(key); + + this.Reflection.GetField(Game1.chatBox.emojiMenu, "emojiTexture").SetValue(texture); + Game1.chatBox.emojiMenuIcon.texture = texture; + + return true; + } + return false; + case "loosesprites/font_bold": // Game1.LoadContent SpriteText.spriteTexture = content.Load(key); return true;