From 15f829e48c1ee9731a812798841ee102e024775d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 12 Jun 2022 12:26:51 -0400 Subject: patch PyTK temporarily to fix scale-up compatibility in SMAPI 3.15 --- .../ModPatches/PyTkPatcher.cs | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/SMAPI.Mods.ErrorHandler/ModPatches/PyTkPatcher.cs (limited to 'src/SMAPI.Mods.ErrorHandler/ModPatches') diff --git a/src/SMAPI.Mods.ErrorHandler/ModPatches/PyTkPatcher.cs b/src/SMAPI.Mods.ErrorHandler/ModPatches/PyTkPatcher.cs new file mode 100644 index 00000000..9ee864db --- /dev/null +++ b/src/SMAPI.Mods.ErrorHandler/ModPatches/PyTkPatcher.cs @@ -0,0 +1,79 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using HarmonyLib; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using StardewModdingAPI.Framework; +using StardewModdingAPI.Framework.Content; +using StardewModdingAPI.Internal; +using StardewModdingAPI.Internal.Patching; + +// +// This is part of a three-part fix for PyTK 1.23.0 and earlier. When removing this, search +// 'Platonymous.Toolkit' to find the other part in SMAPI and Content Patcher. +// + +namespace StardewModdingAPI.Mods.ErrorHandler.ModPatches +{ + /// Harmony patches for the PyTK mod for compatibility with newer SMAPI versions. + /// Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments. + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + [SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + [SuppressMessage("ReSharper", "StringLiteralTypo", Justification = "'Platonymous' is part of the mod ID.")] + internal class PyTkPatcher : BasePatcher + { + /********* + ** Fields + *********/ + /// The PyTK mod metadata, if it's installed. + private static IModMetadata? PyTk; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The mod registry from which to read PyTK metadata. + public PyTkPatcher(IModRegistry modRegistry) + { + IModMetadata? pyTk = (IModMetadata?)modRegistry.Get(@"Platonymous.Toolkit"); + if (pyTk is not null && !pyTk.Manifest.Version.IsNewerThan("1.23.0")) + PyTkPatcher.PyTk = pyTk; + } + + /// + public override void Apply(Harmony harmony, IMonitor monitor) + { + try + { + // get mod info + IModMetadata? pyTk = PyTkPatcher.PyTk; + if (pyTk is null) + return; + + // get patch method + const string patchMethodName = "PatchImage"; + MethodInfo? patch = AccessTools.Method(pyTk.Mod!.GetType(), patchMethodName); + if (patch is null) + { + monitor.Log("Failed applying compatibility patch for PyTK. Its image scaling feature may not work correctly.", LogLevel.Warn); + monitor.Log($"Couldn't find patch method '{pyTk.Mod.GetType().FullName}.{patchMethodName}'."); + return; + } + + // apply patch + harmony = new($"{harmony.Id}.compatibility-patches.PyTK"); + harmony.Patch( + original: AccessTools.Method(typeof(AssetDataForImage), nameof(AssetDataForImage.PatchImage), new[] { typeof(Texture2D), typeof(Rectangle), typeof(Rectangle), typeof(PatchMode) }), + prefix: new HarmonyMethod(patch) + ); + } + catch (Exception ex) + { + monitor.Log("Failed applying compatibility patch for PyTK. Its image scaling feature may not work correctly.", LogLevel.Warn); + monitor.Log(ex.GetLogSummary()); + } + } + } +} -- cgit