diff --git a/build/common.targets b/build/common.targets index 4e16194cb..e450c77e0 100644 --- a/build/common.targets +++ b/build/common.targets @@ -7,7 +7,7 @@ repo. It imports the other MSBuild files as needed. - 4.1.9 + 4.1.10 SMAPI latest $(AssemblySearchPaths);{GAC} diff --git a/build/unix/prepare-install-package.sh b/build/unix/prepare-install-package.sh index fb723b31e..2be7c7dc5 100755 --- a/build/unix/prepare-install-package.sh +++ b/build/unix/prepare-install-package.sh @@ -9,10 +9,35 @@ ########## -## Fetch values +## Find the game folder +########## +possibleGamePaths=( + # override + "$HOME/StardewValley" + + # Linux + "$HOME/GOG Games/Stardew Valley/game" + "$HOME/.steam/steam/steamapps/common/Stardew Valley" + "$HOME/.local/share/Steam/steamapps/common/Stardew Valley" + "$HOME/.var/app/com.valvesoftware.Steam/data/Steam/steamapps/common/Stardew Valley" + + # macOS + "/Applications/Stardew Valley.app/Contents/MacOS" + "$HOME/Library/Application Support/Steam/steamapps/common/Stardew Valley/Contents/MacOS" +) +gamePath="" +for possibleGamePath in "${possibleGamePaths[@]}"; do + if [[ -d "$possibleGamePath" ]]; then + gamePath="$possibleGamePath" + break + fi +done + + +########## +## Preset values ########## # paths -gamePath="/home/pathoschild/Stardew Valley" bundleModNames=("ConsoleCommands" "SaveBackup") # build configuration diff --git a/build/windows/prepare-install-package.ps1 b/build/windows/prepare-install-package.ps1 index 25667118c..8739af90f 100644 --- a/build/windows/prepare-install-package.ps1 +++ b/build/windows/prepare-install-package.ps1 @@ -13,10 +13,34 @@ ########## -## Fetch values +## Find the game folder +########## +$possibleGamePaths=( + # GOG + "C:\Program Files\GalaxyClient\Games\Stardew Valley", + "C:\Program Files\GOG Galaxy\Games\Stardew Valley", + "C:\Program Files\GOG Games\Stardew Valley", + "C:\Program Files (x86)\GalaxyClient\Games\Stardew Valley", + "C:\Program Files (x86)\GOG Galaxy\Games\Stardew Valley", + "C:\Program Files (x86)\GOG Games\Stardew Valley", + + # Steam + "C:\Program Files\Steam\steamapps\common\Stardew Valley", + "C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley" +) +$gamePath = "" +foreach ($possibleGamePath in $possibleGamePaths) { + if (Test-Path $possibleGamePath -PathType Container) { + $gamePath = $possibleGamePath + break + } +} + + +########## +## Preset values ########## # paths -$gamePath = "C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley" $bundleModNames = "ConsoleCommands", "SaveBackup" # build configuration diff --git a/docs/release-notes.md b/docs/release-notes.md index 729030948..f1a530b80 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,6 +1,24 @@ ← [README](README.md) # Release notes +## 4.1.10 +Released 18 December 2024 for Stardew Valley 1.6.14 or later. + +* For players: + * Updated for the upcoming Stardew Valley 1.6.15. + * Fixed errors when cross-playing between PC and Android. + +* For mod authors: + * Improved [Content Patcher JSON schema](technical/web.md#using-a-schema-file-directly) to allow boolean and numeric values in dynamic tokens. + + +> [!IMPORTANT] +> **For players on macOS:** +> There are recent security changes in macOS. Make sure to follow the updated [install guide for +> macOS](https://stardewvalleywiki.com/Modding:Installing_SMAPI_on_Mac) when installing or updating SMAPI. +> +> Players on Linux or Windows can ignore this. + # 4.1.9 Released 08 December 2024 for Stardew Valley 1.6.14 or later. diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index 8b3acc33a..958a1440f 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.9", + "Version": "4.1.10", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "4.1.9" + "MinimumApiVersion": "4.1.10" } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index 4f815aaa9..a383a1610 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.9", + "Version": "4.1.10", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueID": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "4.1.9" + "MinimumApiVersion": "4.1.10" } diff --git a/src/SMAPI.Web/wwwroot/schemas/content-patcher.json b/src/SMAPI.Web/wwwroot/schemas/content-patcher.json index 1a62405c2..82bf418e5 100644 --- a/src/SMAPI.Web/wwwroot/schemas/content-patcher.json +++ b/src/SMAPI.Web/wwwroot/schemas/content-patcher.json @@ -147,7 +147,7 @@ "Value": { "title": "Token value", "description": "The value(s) to set. This can be a comma-delimited value to give it multiple values. If any block for a token name has multiple values, it will only be usable in conditions. This field supports tokens, including dynamic tokens defined before this entry.", - "type": "string" + "type": [ "boolean", "integer", "number", "string" ] }, "When": { "title": "When", diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index 7771f5163..da9c4bcaf 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.9"; + internal static string RawApiVersion = "4.1.10"; } /// Contains SMAPI's constants and assumptions. diff --git a/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade.cs b/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade_160.cs similarity index 95% rename from src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade.cs rename to src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade_160.cs index 017345c95..c2421071a 100644 --- a/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade.cs +++ b/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade_160.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using StardewModdingAPI.Framework.ModLoading.Framework; using StardewValley; @@ -5,7 +6,8 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters.StardewValley_1_6; /// Maps Stardew Valley 1.5.6's methods to their newer form to avoid breaking older mods. /// This is public to support SMAPI rewriting and should never be referenced directly by mods. See remarks on for more info. -public class StatsFacade : Stats, IRewriteFacade +[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Named due to technical limitations, since we can't have two different facades for the same fields in 1.6.0 and 1.6.15.")] +public class StatsFacade_160 : Stats, IRewriteFacade { /********* ** Accessors @@ -18,7 +20,6 @@ public class StatsFacade : Stats, IRewriteFacade get => base.specificMonstersKilled; } - //started using this in 1.4 to track stats, rather than the annoying and messy uint fields above public SerializableDictionary stat_dictionary { get => base.Values; @@ -328,7 +329,7 @@ public void incrementStat(string label, int amount) /********* ** Private methods *********/ - private StatsFacade() + private StatsFacade_160() { RewriteHelper.ThrowFakeConstructorCalled(); } diff --git a/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade_1615.cs b/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade_1615.cs new file mode 100644 index 000000000..62b8c23fe --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/StatsFacade_1615.cs @@ -0,0 +1,33 @@ +using System.Diagnostics.CodeAnalysis; +using StardewModdingAPI.Framework.ModLoading.Framework; +using StardewValley; + +namespace StardewModdingAPI.Framework.ModLoading.Rewriters.StardewValley_1_6; + +/// Maps Stardew Valley 1.6.14's methods to their newer form to avoid breaking older mods. +/// This is public to support SMAPI rewriting and should never be referenced directly by mods. See remarks on for more info. +[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Named due to technical limitations, since we can't have two different facades for the same fields in 1.6.0 and 1.6.15.")] +public class StatsFacade_1615 : Stats, IRewriteFacade +{ + /********* + ** Accessors + *********/ + public new SerializableDictionaryWithCaseInsensitiveKeys specificMonstersKilled + { + get => base.specificMonstersKilled; + } + + public SerializableDictionaryWithCaseInsensitiveKeys Values + { + get => base.Values; + } + + + /********* + ** Private methods + *********/ + private StatsFacade_1615() + { + RewriteHelper.ThrowFakeConstructorCalled(); + } +} diff --git a/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/UtilityFacade.cs b/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/UtilityFacade.cs index 57d70df2d..0a7adce2d 100644 --- a/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/UtilityFacade.cs +++ b/src/SMAPI/Framework/ModLoading/Rewriters/StardewValley_1_6/UtilityFacade.cs @@ -17,6 +17,12 @@ public class UtilityFacade : Utility, IRewriteFacade /********* ** Public methods *********/ + /// Replaced in Stardew Valley 1.6.15. + public static void checkForBooksReadAchievement() + { + Game1.stats.checkForBooksReadAchievement(); + } + public static bool doesItemWithThisIndexExistAnywhere(int index, bool bigCraftable = false) { bool found = false; diff --git a/src/SMAPI/Framework/Networking/RemoteContextModel.cs b/src/SMAPI/Framework/Networking/RemoteContextModel.cs index 792e7d6dd..1707e4d22 100644 --- a/src/SMAPI/Framework/Networking/RemoteContextModel.cs +++ b/src/SMAPI/Framework/Networking/RemoteContextModel.cs @@ -1,4 +1,6 @@ using System; +using Newtonsoft.Json; +using StardewModdingAPI.Toolkit.Serialization.Converters; namespace StardewModdingAPI.Framework.Networking; @@ -15,9 +17,11 @@ internal class RemoteContextModel public GamePlatform Platform { get; } /// The installed version of Stardew Valley. + [JsonConverter(typeof(NonStandardSemanticVersionConverter))] // versions from Android players may have a fourth number for the platform-specific build public ISemanticVersion? GameVersion { get; } /// The installed version of SMAPI. + [JsonConverter(typeof(NonStandardSemanticVersionConverter))] public ISemanticVersion? ApiVersion { get; } /// The installed mods. diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index c4f90c167..1856d5598 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -493,7 +493,8 @@ private void OnGameInitialized() private void OnInstanceContentLoaded() { // override map display device - Game1.mapDisplayDevice = new SDisplayDevice(Game1.content, Game1.game1.GraphicsDevice); + if (Constants.GameVersion.IsOlderThan("1.6.15")) + Game1.mapDisplayDevice = this.GetMapDisplayDevice_OBSOLETE(); // log GPU info #if SMAPI_FOR_WINDOWS @@ -616,8 +617,8 @@ private void OnPlayerInstanceUpdating(SGame instance, GameTime gameTime, Action *********/ if (this.JustReturnedToTitle) { - if (Game1.mapDisplayDevice is not SDisplayDevice) - Game1.mapDisplayDevice = this.GetMapDisplayDevice(); + if (Game1.mapDisplayDevice is not SDisplayDevice && Constants.GameVersion.IsOlderThan("1.6.15")) + Game1.mapDisplayDevice = this.GetMapDisplayDevice_OBSOLETE(); this.JustReturnedToTitle = false; } @@ -2370,8 +2371,8 @@ private IFileLookup GetFileLookup(string rootDirectory) } /// Get the map display device which applies SMAPI features like tile rotation to loaded maps. - /// This is separate to let mods like PyTK wrap it with their own functionality. - private IDisplayDevice GetMapDisplayDevice() + /// This only exists for backwards compatibility with Stardew Valley 1.6.14, and will be removed in the next SMAPI update. See instead. + private IDisplayDevice GetMapDisplayDevice_OBSOLETE() { return new SDisplayDevice(Game1.content, Game1.game1.GraphicsDevice); } diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index 1bb0fdbcb..03a476728 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -2,11 +2,13 @@ using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI.Enums; using StardewModdingAPI.Events; using StardewModdingAPI.Framework.Input; using StardewModdingAPI.Framework.Reflection; +using StardewModdingAPI.Framework.Rendering; using StardewModdingAPI.Framework.StateTracking.Snapshots; using StardewModdingAPI.Framework.Utilities; using StardewModdingAPI.Internal; @@ -15,6 +17,7 @@ using StardewValley.Logging; using StardewValley.Menus; using StardewValley.Minigames; +using xTile.Display; namespace StardewModdingAPI.Framework; @@ -166,9 +169,7 @@ public override bool ShouldDrawOnBuffer() /********* ** Protected methods *********/ - /// Construct a content manager to read game content files. - /// The service provider to use to locate services. - /// The root directory to search for content. + /// protected internal override LocalizedContentManager CreateContentManager(IServiceProvider serviceProvider, string rootDirectory) { if (SGame.CreateContentManagerImpl == null) @@ -177,6 +178,13 @@ protected internal override LocalizedContentManager CreateContentManager(IServic return SGame.CreateContentManagerImpl(serviceProvider, rootDirectory); } + /// + [SuppressMessage("ReSharper", "ParameterHidesMember")] + protected internal override IDisplayDevice CreateDisplayDevice(ContentManager content, GraphicsDevice graphicsDevice) + { + return new SDisplayDevice(content, graphicsDevice); + } + /// Initialize the instance when the game starts. protected override void Initialize() { diff --git a/src/SMAPI/Metadata/InstructionMetadata.cs b/src/SMAPI/Metadata/InstructionMetadata.cs index 97b5f8e4b..816cb368a 100644 --- a/src/SMAPI/Metadata/InstructionMetadata.cs +++ b/src/SMAPI/Metadata/InstructionMetadata.cs @@ -255,7 +255,8 @@ public IEnumerable GetHandlers(bool paranoidMode, bool rewr .MapFacade() .MapFacade() .MapFacade() - .MapFacade() + .MapFacade() + .MapFacade() .MapFacade() .MapFacade() .MapFacade()