summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SMAPI.Installer/InteractiveInstaller.cs5
-rw-r--r--src/SMAPI/Constants.cs3
-rw-r--r--src/SMAPI/Framework/Patching/GameLocationPatch.cs60
-rw-r--r--src/SMAPI/Framework/Patching/GamePatcher.cs45
-rw-r--r--src/SMAPI/Framework/Patching/IHarmonyPatch.cs15
-rw-r--r--src/SMAPI/Program.cs17
-rw-r--r--src/SMAPI/StardewModdingAPI.csproj7
-rw-r--r--src/lib/0Harmony.dllbin0 -> 99840 bytes
-rw-r--r--src/lib/0Harmony.pdbbin0 -> 323072 bytes
9 files changed, 143 insertions, 9 deletions
diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs
index 30cb10b4..f9239604 100644
--- a/src/SMAPI.Installer/InteractiveInstaller.cs
+++ b/src/SMAPI.Installer/InteractiveInstaller.cs
@@ -87,11 +87,16 @@ namespace StardewModdingApi.Installer
string GetInstallPath(string path) => Path.Combine(installDir.FullName, path);
// common
+ yield return GetInstallPath("0Harmony.dll");
+ yield return GetInstallPath("0Harmony.pdb");
yield return GetInstallPath("Mono.Cecil.dll");
yield return GetInstallPath("Newtonsoft.Json.dll");
yield return GetInstallPath("StardewModdingAPI.exe");
yield return GetInstallPath("StardewModdingAPI.config.json");
yield return GetInstallPath("StardewModdingAPI.metadata.json");
+ yield return GetInstallPath("StardewModdingAPI.Toolkit.dll");
+ yield return GetInstallPath("StardewModdingAPI.Toolkit.pdb");
+ yield return GetInstallPath("StardewModdingAPI.xml");
yield return GetInstallPath("System.ValueTuple.dll");
yield return GetInstallPath("steam_appid.txt");
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index 31744ccd..532112ff 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -106,6 +106,9 @@ namespace StardewModdingAPI
/// <summary>The target game platform.</summary>
internal static Platform Platform { get; } = EnvironmentUtility.DetectPlatform();
+ /// <summary>The game's assembly name.</summary>
+ internal static string GameAssemblyName => Constants.Platform == Platform.Windows ? "Stardew Valley" : "StardewValley";
+
/*********
** Internal methods
diff --git a/src/SMAPI/Framework/Patching/GameLocationPatch.cs b/src/SMAPI/Framework/Patching/GameLocationPatch.cs
new file mode 100644
index 00000000..c0216b8f
--- /dev/null
+++ b/src/SMAPI/Framework/Patching/GameLocationPatch.cs
@@ -0,0 +1,60 @@
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Reflection;
+using Harmony;
+using StardewValley;
+using xTile.Tiles;
+
+namespace StardewModdingAPI.Framework.Patching
+{
+ /// <summary>A Harmony patch for the <see cref="GameLocation.updateSeasonalTileSheets"/> method.</summary>
+ internal class GameLocationPatch : IHarmonyPatch
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>A unique name for this patch.</summary>
+ public string Name => $"{nameof(GameLocation)}.{nameof(GameLocation.updateSeasonalTileSheets)}";
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Apply the Harmony patch.</summary>
+ /// <param name="harmony">The Harmony instance.</param>
+ public void Apply(HarmonyInstance harmony)
+ {
+ MethodInfo method = AccessTools.Method(typeof(GameLocation), nameof(GameLocation.updateSeasonalTileSheets));
+ MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(GameLocationPatch.Prefix));
+
+ harmony.Patch(method, new HarmonyMethod(prefix), null);
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>An implementation of <see cref="GameLocation.updateSeasonalTileSheets"/> which correctly handles custom map tilesheets.</summary>
+ /// <param name="__instance">The location instance being patched.</param>
+ [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument name is defined by Harmony.")]
+ private static bool Prefix(GameLocation __instance)
+ {
+ if (!__instance.IsOutdoors || __instance.Name.Equals("Desert"))
+ return false;
+ foreach (TileSheet tilesheet in __instance.Map.TileSheets)
+ {
+ string imageSource = tilesheet.ImageSource;
+ string imageFile = Path.GetFileName(imageSource);
+ if (imageFile.StartsWith("spring_") || imageFile.StartsWith("summer_") || imageFile.StartsWith("fall_") || imageFile.StartsWith("winter_"))
+ {
+ string imageDir = Path.GetDirectoryName(imageSource);
+ if (string.IsNullOrWhiteSpace(imageDir))
+ imageDir = "Maps";
+ tilesheet.ImageSource = Path.Combine(imageDir, Game1.currentSeason + "_" + imageFile.Split('_')[1]);
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/Patching/GamePatcher.cs b/src/SMAPI/Framework/Patching/GamePatcher.cs
new file mode 100644
index 00000000..71ca8e55
--- /dev/null
+++ b/src/SMAPI/Framework/Patching/GamePatcher.cs
@@ -0,0 +1,45 @@
+using System;
+using Harmony;
+
+namespace StardewModdingAPI.Framework.Patching
+{
+ /// <summary>Encapsulates applying Harmony patches to the game.</summary>
+ internal class GamePatcher
+ {
+ /*********
+ ** Properties
+ *********/
+ /// <summary>Encapsulates monitoring and logging.</summary>
+ private readonly IMonitor Monitor;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ public GamePatcher(IMonitor monitor)
+ {
+ this.Monitor = monitor;
+ }
+
+ /// <summary>Apply all loaded patches to the game.</summary>
+ /// <param name="patches">The patches to apply.</param>
+ public void Apply(params IHarmonyPatch[] patches)
+ {
+ HarmonyInstance harmony = HarmonyInstance.Create("io.smapi");
+ foreach (IHarmonyPatch patch in patches)
+ {
+ try
+ {
+ patch.Apply(harmony);
+ }
+ catch (Exception ex)
+ {
+ this.Monitor.Log($"Couldn't apply runtime patch '{patch.Name}' to the game. Some SMAPI features may not work correctly. See log file for details.", LogLevel.Error);
+ this.Monitor.Log(ex.GetLogSummary(), LogLevel.Trace);
+ }
+ }
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/Patching/IHarmonyPatch.cs b/src/SMAPI/Framework/Patching/IHarmonyPatch.cs
new file mode 100644
index 00000000..cb42f40e
--- /dev/null
+++ b/src/SMAPI/Framework/Patching/IHarmonyPatch.cs
@@ -0,0 +1,15 @@
+using Harmony;
+
+namespace StardewModdingAPI.Framework.Patching
+{
+ /// <summary>A Harmony patch to apply.</summary>
+ internal interface IHarmonyPatch
+ {
+ /// <summary>A unique name for this patch.</summary>
+ string Name { get; }
+
+ /// <summary>Apply the Harmony patch.</summary>
+ /// <param name="harmony">The Harmony instance.</param>
+ void Apply(HarmonyInstance harmony);
+ }
+}
diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs
index 28523722..4ede45d5 100644
--- a/src/SMAPI/Program.cs
+++ b/src/SMAPI/Program.cs
@@ -24,6 +24,7 @@ using StardewModdingAPI.Framework.ModData;
using StardewModdingAPI.Framework.Models;
using StardewModdingAPI.Framework.ModHelpers;
using StardewModdingAPI.Framework.ModLoading;
+using StardewModdingAPI.Framework.Patching;
using StardewModdingAPI.Framework.Reflection;
using StardewModdingAPI.Framework.Serialisation;
using StardewModdingAPI.Internal;
@@ -32,7 +33,7 @@ using StardewModdingAPI.Toolkit.Serialisation;
using StardewModdingAPI.Toolkit.Serialisation.Converters;
using StardewModdingAPI.Toolkit.Utilities;
using StardewValley;
-using Keys = System.Windows.Forms.Keys;
+using Keys = Microsoft.Xna.Framework.Input.Keys;
using Monitor = StardewModdingAPI.Framework.Monitor;
using SObject = StardewValley.Object;
using ThreadState = System.Threading.ThreadState;
@@ -141,6 +142,11 @@ namespace StardewModdingAPI
};
this.EventManager = new EventManager(this.Monitor, this.ModRegistry);
+ // apply game patches
+ new GamePatcher(this.Monitor).Apply(
+ new GameLocationPatch()
+ );
+
// init JSON parser
JsonConverter[] converters = {
new StringEnumConverter<Buttons>(),
@@ -348,14 +354,7 @@ namespace StardewModdingAPI
Console.ResetColor();
Program.PressAnyKeyToExit(showMessage: true);
}
-
- // get game assembly name
- const string gameAssemblyName =
-#if SMAPI_FOR_WINDOWS
- "Stardew Valley";
-#else
- "StardewValley";
-#endif
+ string gameAssemblyName = Constants.GameAssemblyName;
// game not present
if (Type.GetType($"StardewValley.Game1, {gameAssemblyName}", throwOnError: false) == null)
diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj
index 7eb5f95a..2df3e63f 100644
--- a/src/SMAPI/StardewModdingAPI.csproj
+++ b/src/SMAPI/StardewModdingAPI.csproj
@@ -53,6 +53,10 @@
<ApplicationIcon>icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="0Harmony, Version=1.0.9.1, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\0Harmony.dll</HintPath>
+ </Reference>
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
<Private>True</Private>
@@ -103,6 +107,8 @@
<Compile Include="Framework\ContentManagers\GameContentManager.cs" />
<Compile Include="Framework\ContentManagers\IContentManager.cs" />
<Compile Include="Framework\ContentManagers\ModContentManager.cs" />
+ <Compile Include="Framework\Patching\GamePatcher.cs" />
+ <Compile Include="Framework\Patching\IHarmonyPatch.cs" />
<Compile Include="Framework\Serialisation\ColorConverter.cs" />
<Compile Include="Framework\Serialisation\PointConverter.cs" />
<Compile Include="Framework\Serialisation\RectangleConverter.cs" />
@@ -279,6 +285,7 @@
<Compile Include="Framework\Monitor.cs" />
<Compile Include="Metadata\InstructionMetadata.cs" />
<Compile Include="Mod.cs" />
+ <Compile Include="Framework\Patching\GameLocationPatch.cs" />
<Compile Include="PatchMode.cs" />
<Compile Include="GamePlatform.cs" />
<Compile Include="Program.cs" />
diff --git a/src/lib/0Harmony.dll b/src/lib/0Harmony.dll
new file mode 100644
index 00000000..63619429
--- /dev/null
+++ b/src/lib/0Harmony.dll
Binary files differ
diff --git a/src/lib/0Harmony.pdb b/src/lib/0Harmony.pdb
new file mode 100644
index 00000000..d7a4c67c
--- /dev/null
+++ b/src/lib/0Harmony.pdb
Binary files differ