From 5518b8d461732796b0da5f4c9ba85be96bddc205 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 8 Jan 2023 16:48:30 -0500 Subject: update packages --- src/SMAPI/SMAPI.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/SMAPI') diff --git a/src/SMAPI/SMAPI.csproj b/src/SMAPI/SMAPI.csproj index e5d8937c..59ad47f0 100644 --- a/src/SMAPI/SMAPI.csproj +++ b/src/SMAPI/SMAPI.csproj @@ -22,12 +22,12 @@ - + - + - + -- cgit From e5407417a0cc80f9cb3d7eb7b43bdb207322a4ec Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 8 Jan 2023 22:05:22 -0500 Subject: add delegating mod hooks for mod use --- docs/release-notes.md | 1 + src/SMAPI/Framework/SCore.cs | 10 ++- src/SMAPI/Framework/SModHooks.cs | 18 ++-- src/SMAPI/Utilities/DelegatingModHooks.cs | 137 ++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 13 deletions(-) create mode 100644 src/SMAPI/Utilities/DelegatingModHooks.cs (limited to 'src/SMAPI') diff --git a/docs/release-notes.md b/docs/release-notes.md index 3731157b..d095ce7c 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -12,6 +12,7 @@ * Fixed save backups being empty in rare cases on macOS. * For mod authors: + * Added `DelegatingModHooks` utility for rare cases where a mod needs to override SMAPI's mod hooks in the game directly. * Updated to Newtonsoft.Json 13.0.2 (see [changes](https://github.com/JamesNK/Newtonsoft.Json/releases/tag/13.0.2)) and Pintail 2.2.1 (see [changes](https://github.com/Nanoray-pl/Pintail/blob/master/docs/release-notes.md#222)). ## 3.18.1 diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index c977ad65..1d146d5f 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -258,7 +258,11 @@ namespace StardewModdingAPI.Framework monitor: this.Monitor, reflection: this.Reflection, eventManager: this.EventManager, - modHooks: new SModHooks(this.OnNewDayAfterFade, this.Monitor), + modHooks: new SModHooks( + parent: new ModHooks(), + beforeNewDayAfterFade: this.OnNewDayAfterFade, + monitor: this.Monitor + ), multiplayer: this.Multiplayer, exitGameImmediately: this.ExitGameImmediately, @@ -1795,7 +1799,7 @@ namespace StardewModdingAPI.Framework // call entry method try { - mod.Entry(mod.Helper!); + mod.Entry(mod.Helper); } catch (Exception ex) { @@ -1822,7 +1826,7 @@ namespace StardewModdingAPI.Framework } // validate mod doesn't implement both GetApi() and GetApi(mod) - if (metadata.Api != null && mod.GetType().GetMethod(nameof(Mod.GetApi), new Type[] { typeof(IModInfo) })!.DeclaringType != typeof(Mod)) + if (metadata.Api != null && mod.GetType().GetMethod(nameof(Mod.GetApi), new[] { typeof(IModInfo) })!.DeclaringType != typeof(Mod)) metadata.LogAsMod($"Mod implements both {nameof(Mod.GetApi)}() and {nameof(Mod.GetApi)}({nameof(IModInfo)}), which isn't allowed. The latter will be ignored.", LogLevel.Error); } Context.HeuristicModsRunningCode.TryPop(out _); diff --git a/src/SMAPI/Framework/SModHooks.cs b/src/SMAPI/Framework/SModHooks.cs index a7736c8b..ac4f242c 100644 --- a/src/SMAPI/Framework/SModHooks.cs +++ b/src/SMAPI/Framework/SModHooks.cs @@ -1,11 +1,12 @@ using System; using System.Threading.Tasks; +using StardewModdingAPI.Utilities; using StardewValley; namespace StardewModdingAPI.Framework { /// Invokes callbacks for mod hooks provided by the game. - internal class SModHooks : ModHooks + internal class SModHooks : DelegatingModHooks { /********* ** Fields @@ -21,25 +22,24 @@ namespace StardewModdingAPI.Framework ** Public methods *********/ /// Construct an instance. + /// The underlying hooks to call by default. /// A callback to invoke before runs. /// Writes messages to the console. - public SModHooks(Action beforeNewDayAfterFade, IMonitor monitor) + public SModHooks(ModHooks parent, Action beforeNewDayAfterFade, IMonitor monitor) + : base(parent) { this.BeforeNewDayAfterFade = beforeNewDayAfterFade; this.Monitor = monitor; } - /// A hook invoked when is called. - /// The vanilla logic. + /// public override void OnGame1_NewDayAfterFade(Action action) { this.BeforeNewDayAfterFade(); action(); } - /// Start an asynchronous task for the game. - /// The task to start. - /// A unique key which identifies the task. + /// public override Task StartTask(Task task, string id) { this.Monitor.Log($"Synchronizing '{id}' task..."); @@ -48,9 +48,7 @@ namespace StardewModdingAPI.Framework return task; } - /// Start an asynchronous task for the game. - /// The task to start. - /// A unique key which identifies the task. + /// public override Task StartTask(Task task, string id) { this.Monitor.Log($"Synchronizing '{id}' task..."); diff --git a/src/SMAPI/Utilities/DelegatingModHooks.cs b/src/SMAPI/Utilities/DelegatingModHooks.cs new file mode 100644 index 00000000..3ebcf997 --- /dev/null +++ b/src/SMAPI/Utilities/DelegatingModHooks.cs @@ -0,0 +1,137 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Xna.Framework.Input; +using StardewModdingAPI.Events; +using StardewModdingAPI.Framework; +using StardewValley; +using StardewValley.Events; + +namespace StardewModdingAPI.Utilities +{ + /// An implementation of which automatically calls the parent instance for any method that's not overridden. + /// The mod hooks are primarily meant for SMAPI to use. Using this directly in mods is a last resort, since it's very easy to break SMAPI this way. This class requires that SMAPI is present in the parent chain. + public class DelegatingModHooks : ModHooks + { + /********* + ** Accessors + *********/ + /// The underlying instance to delegate to by default. + public ModHooks Parent { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The underlying instance to delegate to by default. + public DelegatingModHooks(ModHooks modHooks) + { + this.AssertSmapiInChain(modHooks); + + this.Parent = modHooks; + } + + /// Raised before the in-game clock changes. + /// Run the vanilla update logic. + /// In mods, consider using instead. + public override void OnGame1_PerformTenMinuteClockUpdate(Action action) + { + this.Parent.OnGame1_PerformTenMinuteClockUpdate(action); + } + + /// Raised before initializing the new day and saving. + /// Run the vanilla update logic. + /// In mods, consider using or instead. + public override void OnGame1_NewDayAfterFade(Action action) + { + this.Parent.OnGame1_NewDayAfterFade(action); + } + + /// Raised before showing the end-of-day menus (e.g. shipping menus, level-up screen, etc). + /// Run the vanilla update logic. + public override void OnGame1_ShowEndOfNightStuff(Action action) + { + this.Parent.OnGame1_ShowEndOfNightStuff(action); + } + + /// Raised before updating the gamepad, mouse, and keyboard input state. + /// The keyboard state. + /// The mouse state. + /// The gamepad state. + /// Run the vanilla update logic. + /// In mods, consider using instead. + public override void OnGame1_UpdateControlInput(ref KeyboardState keyboardState, ref MouseState mouseState, ref GamePadState gamePadState, Action action) + { + this.Parent.OnGame1_UpdateControlInput(ref keyboardState, ref mouseState, ref gamePadState, action); + } + + /// Raised before a location is updated for the local player entering it. + /// The location that will be updated. + /// Run the vanilla update logic. + /// In mods, consider using instead. + public override void OnGameLocation_ResetForPlayerEntry(GameLocation location, Action action) + { + this.Parent.OnGameLocation_ResetForPlayerEntry(location, action); + } + + /// Raised before the game checks for an action to trigger for a player interaction with a tile. + /// The location being checked. + /// The tile position being checked. + /// The game's current position and size within the map, measured in pixels. + /// The player interacting with the tile. + /// Run the vanilla update logic. + /// Returns whether the interaction was handled. + public override bool OnGameLocation_CheckAction(GameLocation location, xTile.Dimensions.Location tileLocation, xTile.Dimensions.Rectangle viewport, Farmer who, Func action) + { + return this.Parent.OnGameLocation_CheckAction(location, tileLocation, viewport, who, action); + } + + /// Raised before the game picks a night event to show on the farm after the player sleeps. + /// Run the vanilla update logic. + /// Returns the selected farm event. + public override FarmEvent OnUtility_PickFarmEvent(Func action) + { + return this.Parent.OnUtility_PickFarmEvent(action); + } + + /// Start an asynchronous task for the game. + /// The task to start. + /// A unique key which identifies the task. + public override Task StartTask(Task task, string id) + { + return this.Parent.StartTask(task, id); + } + + /// Start an asynchronous task for the game. + /// The type returned by the task when it completes. + /// The task to start. + /// A unique key which identifies the task. + public override Task StartTask(Task task, string id) + { + return this.Parent.StartTask(task, id); + } + + + /********* + ** Private methods + *********/ + /// Assert that SMAPI's mod hook implementation is in the inheritance chain. + /// The mod hooks to check. + private void AssertSmapiInChain(ModHooks hooks) + { + // this is SMAPI + if (this is SModHooks) + return; + + // SMAPI in delegated chain + for (ModHooks? cur = hooks; cur != null; cur = (cur as DelegatingModHooks)?.Parent) + { + if (cur is SModHooks) + return; + } + + // SMAPI not found + throw new InvalidOperationException($"Can't create a {nameof(DelegatingModHooks)} instance without SMAPI's mod hooks in the parent chain."); + } + } +} -- cgit From 25b8e13ba827a0512f5089d3bd22e8ed1a15e7ba Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 9 Jan 2023 12:27:29 -0500 Subject: prepare for release --- build/common.targets | 2 +- docs/release-notes.md | 11 +++++++---- docs/technical/mod-package.md | 6 ++++-- src/SMAPI.ModBuildConfig/SMAPI.ModBuildConfig.csproj | 2 +- src/SMAPI.Mods.ConsoleCommands/manifest.json | 4 ++-- src/SMAPI.Mods.ErrorHandler/manifest.json | 4 ++-- src/SMAPI.Mods.SaveBackup/manifest.json | 4 ++-- src/SMAPI/Constants.cs | 2 +- 8 files changed, 20 insertions(+), 15 deletions(-) (limited to 'src/SMAPI') diff --git a/build/common.targets b/build/common.targets index 512107a0..590e0415 100644 --- a/build/common.targets +++ b/build/common.targets @@ -7,7 +7,7 @@ repo. It imports the other MSBuild files as needed. - 3.18.1 + 3.18.2 SMAPI latest $(AssemblySearchPaths);{GAC} diff --git a/docs/release-notes.md b/docs/release-notes.md index d095ce7c..9eb55b36 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -7,13 +7,16 @@ _If needed, you can update to SMAPI 3.16.0 first and then install the latest version._ --> -## Upcoming release +## 3.18.2 +Released 09 January 2023 for Stardew Valley 1.5.6 or later. + * For players: - * Fixed save backups being empty in rare cases on macOS. + * Fixed empty save backups for some macOS players. + * Fixed `player_add` console command not handling custom slingshots correctly (thanks too DaLion!). * For mod authors: - * Added `DelegatingModHooks` utility for rare cases where a mod needs to override SMAPI's mod hooks in the game directly. - * Updated to Newtonsoft.Json 13.0.2 (see [changes](https://github.com/JamesNK/Newtonsoft.Json/releases/tag/13.0.2)) and Pintail 2.2.1 (see [changes](https://github.com/Nanoray-pl/Pintail/blob/master/docs/release-notes.md#222)). + * Added `DelegatingModHooks` utility for mods which need to override SMAPI's mod hooks directly. + * Updated to Newtonsoft.Json 13.0.2 (see [changes](https://github.com/JamesNK/Newtonsoft.Json/releases/tag/13.0.2)) and Pintail 2.2.2 (see [changes](https://github.com/Nanoray-pl/Pintail/blob/master/docs/release-notes.md#222)). ## 3.18.1 Released 01 December 2022 for Stardew Valley 1.5.6 or later. diff --git a/docs/technical/mod-package.md b/docs/technical/mod-package.md index 0e710e50..23f0b221 100644 --- a/docs/technical/mod-package.md +++ b/docs/technical/mod-package.md @@ -412,9 +412,11 @@ The NuGet package is generated automatically in `StardewModdingAPI.ModBuildConfi when you compile it. ## Release notes -## Upcoming release +### 4.1.0 +Released 08 January 2023. + * Added `manifest.json` format validation on build (thanks to tylergibbs2!). -* Fixed game assemblies no longer excluded from the release zip if referenced explicitly without setting `BundleExtraAssemblies`. +* Fixed game DLLs not excluded from the release zip when they're referenced explicitly but `BundleExtraAssemblies` isn't set. ### 4.0.2 Released 09 October 2022. diff --git a/src/SMAPI.ModBuildConfig/SMAPI.ModBuildConfig.csproj b/src/SMAPI.ModBuildConfig/SMAPI.ModBuildConfig.csproj index efc808a1..badabfc7 100644 --- a/src/SMAPI.ModBuildConfig/SMAPI.ModBuildConfig.csproj +++ b/src/SMAPI.ModBuildConfig/SMAPI.ModBuildConfig.csproj @@ -10,7 +10,7 @@ Pathoschild.Stardew.ModBuildConfig Build package for SMAPI mods - 4.0.2 + 4.1.0 Pathoschild Automates the build configuration for crossplatform Stardew Valley SMAPI mods. For SMAPI 3.13.0 or later. MIT diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index 0afb5837..6ababef0 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.1", + "Version": "3.18.2", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "3.18.1" + "MinimumApiVersion": "3.18.2" } diff --git a/src/SMAPI.Mods.ErrorHandler/manifest.json b/src/SMAPI.Mods.ErrorHandler/manifest.json index fe802d88..82630479 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.1", + "Version": "3.18.2", "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.1" + "MinimumApiVersion": "3.18.2" } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index 9a587a2b..e29a3ed3 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.1", + "Version": "3.18.2", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueID": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "3.18.1" + "MinimumApiVersion": "3.18.2" } diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index c5058e4b..482ec816 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -52,7 +52,7 @@ namespace StardewModdingAPI internal static int? LogScreenId { get; set; } /// SMAPI's current raw semantic version. - internal static string RawApiVersion = "3.18.1"; + internal static string RawApiVersion = "3.18.2"; } /// Contains SMAPI's constants and assumptions. -- cgit