From 73321eceb96f263f10857667d7b3726a5098e770 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 17 Mar 2021 20:36:31 -0400 Subject: split compile flag into separate Windows + XNA flags (#767) --- src/SMAPI/Framework/InternalExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/InternalExtensions.cs') diff --git a/src/SMAPI/Framework/InternalExtensions.cs b/src/SMAPI/Framework/InternalExtensions.cs index ba1879da..449aa2b7 100644 --- a/src/SMAPI/Framework/InternalExtensions.cs +++ b/src/SMAPI/Framework/InternalExtensions.cs @@ -181,7 +181,7 @@ namespace StardewModdingAPI.Framework { // get field name const string fieldName = -#if SMAPI_FOR_WINDOWS +#if SMAPI_FOR_XNA "inBeginEndPair"; #else "_beginCalled"; -- cgit From ca67dcc920560f3fd19a4531c40fdb03d19e96c5 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 17 Mar 2021 20:36:32 -0400 Subject: add Constants.GameFramework field (#767) --- docs/release-notes.md | 2 + .../Patches/SpriteBatchValidationPatches.cs | 8 +- src/SMAPI/Constants.cs | 95 +++++++++++++++------- src/SMAPI/Framework/Content/ContentCache.cs | 2 +- src/SMAPI/Framework/InternalExtensions.cs | 11 +-- src/SMAPI/Framework/Logging/LogManager.cs | 7 +- src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 5 +- src/SMAPI/Framework/SCore.cs | 2 +- src/SMAPI/GameFramework.cs | 12 +++ 9 files changed, 96 insertions(+), 48 deletions(-) create mode 100644 src/SMAPI/GameFramework.cs (limited to 'src/SMAPI/Framework/InternalExtensions.cs') diff --git a/docs/release-notes.md b/docs/release-notes.md index 075dfe4d..728b50c0 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -19,6 +19,8 @@ * Reduced performance impact of invalidating cached assets before a save is loaded. * Fixed asset changes not reapplied in the edge case where you're playing in non-English, and the changes are only applied after the save is loaded, and the player returns to title and reloads a save, and the game reloads the target asset before the save is loaded. * Added a second `KeybindList` constructor to simplify single-key default bindings. + * Added a `Constants.GameFramework` field which indicates whether the game is using XNA Framework or MonoGame. + _Note: mods don't need to handle the difference in most cases, but some players may use MonoGame on Windows in upcoming versions. Mods which use the `Constants.TargetPlatform` should review usages to determine whether they're actually checking the platform or the game framework._ ## 3.9.4 Released 07 March 2021 for Stardew Valley 1.5.4 or later. diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchValidationPatches.cs b/src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchValidationPatches.cs index f605b2ce..8056fd71 100644 --- a/src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchValidationPatches.cs +++ b/src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchValidationPatches.cs @@ -27,11 +27,9 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches #endif { harmony.Patch( -#if SMAPI_FOR_XNA - original: AccessTools.Method(typeof(SpriteBatch), "InternalDraw"), -#else - original: AccessTools.Method(typeof(SpriteBatch), "CheckValid", new[] { typeof(Texture2D) }), -#endif + original: Constants.GameFramework == GameFramework.Xna + ? AccessTools.Method(typeof(SpriteBatch), "InternalDraw") + : AccessTools.Method(typeof(SpriteBatch), "CheckValid", new[] { typeof(Texture2D) }), postfix: new HarmonyMethod(this.GetType(), nameof(SpriteBatchValidationPatches.After_SpriteBatch_CheckValid)) ); } diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index 0de2b12f..ec5cbe17 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; @@ -37,6 +38,14 @@ namespace StardewModdingAPI /// The target game platform. internal static GamePlatform Platform { get; } = (GamePlatform)Enum.Parse(typeof(GamePlatform), LowLevelEnvironmentUtility.DetectPlatform()); + /// The game framework running the game. + internal static GameFramework GameFramework { get; } = +#if SMAPI_FOR_XNA + GameFramework.Xna; +#else + GameFramework.MonoGame; +#endif + /// The game's assembly name. internal static string GameAssemblyName => EarlyConstants.Platform == GamePlatform.Windows ? "Stardew Valley" : "StardewValley"; @@ -65,6 +74,9 @@ namespace StardewModdingAPI /// The target game platform. public static GamePlatform TargetPlatform { get; } = EarlyConstants.Platform; + /// The game framework running the game. + public static GameFramework GameFramework { get; } = EarlyConstants.GameFramework; + /// The path to the game folder. public static string ExecutionPath { get; } = EarlyConstants.ExecutionPath; @@ -208,56 +220,79 @@ namespace StardewModdingAPI /// Get metadata for mapping assemblies to the current platform. /// The target game platform. - internal static PlatformAssemblyMap GetAssemblyMap(Platform targetPlatform) + /// The game framework running the game. + internal static PlatformAssemblyMap GetAssemblyMap(Platform targetPlatform, GameFramework framework) { - // get assembly changes needed for platform - string[] removeAssemblyReferences; - Assembly[] targetAssemblies; + var removeAssemblyReferences = new List(); + var targetAssemblies = new List(); + + // get assembly renamed in SMAPI 3.0 + removeAssemblyReferences.Add("StardewModdingAPI.Toolkit.CoreInterfaces"); + targetAssemblies.Add(typeof(StardewModdingAPI.IManifest).Assembly); + + // get changes for platform switch (targetPlatform) { case Platform.Linux: case Platform.Mac: - removeAssemblyReferences = new[] + removeAssemblyReferences.AddRange(new[] { "Netcode", - "Stardew Valley", + "Stardew Valley" + }); + targetAssemblies.Add( + typeof(StardewValley.Game1).Assembly // note: includes Netcode types on Linux/Mac + ); + break; + + case Platform.Windows: + removeAssemblyReferences.Add( + "StardewValley" + ); + targetAssemblies.AddRange(new[] + { + typeof(Netcode.NetBool).Assembly, + typeof(StardewValley.Game1).Assembly + }); + break; + + default: + throw new InvalidOperationException($"Unknown target platform '{targetPlatform}'."); + } + + // get changes for game framework + switch (framework) + { + case GameFramework.MonoGame: + removeAssemblyReferences.AddRange(new[] + { "Microsoft.Xna.Framework", "Microsoft.Xna.Framework.Game", "Microsoft.Xna.Framework.Graphics", - "Microsoft.Xna.Framework.Xact", - "StardewModdingAPI.Toolkit.CoreInterfaces" // renamed in SMAPI 3.0 - }; - targetAssemblies = new[] - { - typeof(StardewValley.Game1).Assembly, // note: includes Netcode types on Linux/Mac - typeof(Microsoft.Xna.Framework.Vector2).Assembly, - typeof(StardewModdingAPI.IManifest).Assembly - }; + "Microsoft.Xna.Framework.Xact" + }); + targetAssemblies.Add( + typeof(Microsoft.Xna.Framework.Vector2).Assembly + ); break; - case Platform.Windows: - removeAssemblyReferences = new[] + case GameFramework.Xna: + removeAssemblyReferences.Add( + "MonoGame.Framework" + ); + targetAssemblies.AddRange(new[] { - "StardewValley", - "MonoGame.Framework", - "StardewModdingAPI.Toolkit.CoreInterfaces" // renamed in SMAPI 3.0 - }; - targetAssemblies = new[] - { - typeof(Netcode.NetBool).Assembly, - typeof(StardewValley.Game1).Assembly, typeof(Microsoft.Xna.Framework.Vector2).Assembly, typeof(Microsoft.Xna.Framework.Game).Assembly, - typeof(Microsoft.Xna.Framework.Graphics.SpriteBatch).Assembly, - typeof(StardewModdingAPI.IManifest).Assembly - }; + typeof(Microsoft.Xna.Framework.Graphics.SpriteBatch).Assembly + }); break; default: - throw new InvalidOperationException($"Unknown target platform '{targetPlatform}'."); + throw new InvalidOperationException($"Unknown game framework '{framework}'."); } - return new PlatformAssemblyMap(targetPlatform, removeAssemblyReferences, targetAssemblies); + return new PlatformAssemblyMap(targetPlatform, removeAssemblyReferences.ToArray(), targetAssemblies.ToArray()); } diff --git a/src/SMAPI/Framework/Content/ContentCache.cs b/src/SMAPI/Framework/Content/ContentCache.cs index af65e07e..7edc9ab9 100644 --- a/src/SMAPI/Framework/Content/ContentCache.cs +++ b/src/SMAPI/Framework/Content/ContentCache.cs @@ -52,7 +52,7 @@ namespace StardewModdingAPI.Framework.Content this.Cache = reflection.GetField>(contentManager, "loadedAssets").GetValue(); // get key normalization logic - if (Constants.Platform == Platform.Windows) + if (Constants.GameFramework == GameFramework.Xna) { IReflectedMethod method = reflection.GetMethod(typeof(TitleContainer), "GetCleanPath"); this.NormalizeAssetNameForPlatform = path => method.Invoke(path); diff --git a/src/SMAPI/Framework/InternalExtensions.cs b/src/SMAPI/Framework/InternalExtensions.cs index 449aa2b7..ab7f1e6c 100644 --- a/src/SMAPI/Framework/InternalExtensions.cs +++ b/src/SMAPI/Framework/InternalExtensions.cs @@ -179,15 +179,10 @@ namespace StardewModdingAPI.Framework /// The reflection helper with which to access private fields. public static bool IsOpen(this SpriteBatch spriteBatch, Reflector reflection) { - // get field name - const string fieldName = -#if SMAPI_FOR_XNA - "inBeginEndPair"; -#else - "_beginCalled"; -#endif + string fieldName = Constants.GameFramework == GameFramework.Xna + ? "inBeginEndPair" + : "_beginCalled"; - // get result return reflection.GetField(Game1.spriteBatch, fieldName).GetValue(); } } diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs index 0dd45355..243ca3ae 100644 --- a/src/SMAPI/Framework/Logging/LogManager.cs +++ b/src/SMAPI/Framework/Logging/LogManager.cs @@ -283,8 +283,13 @@ namespace StardewModdingAPI.Framework.Logging /// The custom SMAPI settings. public void LogIntro(string modsPath, IDictionary customSettings) { + // get platform label + string platformLabel = EnvironmentUtility.GetFriendlyPlatformName(Constants.Platform); + if ((Constants.GameFramework == GameFramework.Xna) != (Constants.Platform == Platform.Windows)) + platformLabel += $" with {Constants.GameFramework}"; + // init logging - this.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Constants.GameVersion} on {EnvironmentUtility.GetFriendlyPlatformName(Constants.Platform)}", LogLevel.Info); + this.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Constants.GameVersion} on {platformLabel}", LogLevel.Info); this.Monitor.Log($"Mods go here: {modsPath}", LogLevel.Info); if (modsPath != Constants.DefaultModsPath) this.Monitor.Log("(Using custom --mods-path argument.)"); diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 69535aa5..3606eb66 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -46,15 +46,16 @@ namespace StardewModdingAPI.Framework.ModLoading *********/ /// Construct an instance. /// The current game platform. + /// The game framework running the game. /// Encapsulates monitoring and logging. /// Whether to detect paranoid mode issues. /// Whether to rewrite mods for compatibility. - public AssemblyLoader(Platform targetPlatform, IMonitor monitor, bool paranoidMode, bool rewriteMods) + public AssemblyLoader(Platform targetPlatform, GameFramework framework, IMonitor monitor, bool paranoidMode, bool rewriteMods) { this.Monitor = monitor; this.ParanoidMode = paranoidMode; this.RewriteMods = rewriteMods; - this.AssemblyMap = this.TrackForDisposal(Constants.GetAssemblyMap(targetPlatform)); + this.AssemblyMap = this.TrackForDisposal(Constants.GetAssemblyMap(targetPlatform, framework)); // init resolver this.AssemblyDefinitionResolver = this.TrackForDisposal(new AssemblyDefinitionResolver()); diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index c758a793..ebb21555 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1410,7 +1410,7 @@ namespace StardewModdingAPI.Framework // load mods IList skippedMods = new List(); - using (AssemblyLoader modAssemblyLoader = new AssemblyLoader(Constants.Platform, this.Monitor, this.Settings.ParanoidWarnings, this.Settings.RewriteMods)) + using (AssemblyLoader modAssemblyLoader = new AssemblyLoader(Constants.Platform, Constants.GameFramework, this.Monitor, this.Settings.ParanoidWarnings, this.Settings.RewriteMods)) { // init HashSet suppressUpdateChecks = new HashSet(this.Settings.SuppressUpdateChecks, StringComparer.OrdinalIgnoreCase); diff --git a/src/SMAPI/GameFramework.cs b/src/SMAPI/GameFramework.cs new file mode 100644 index 00000000..7670ce8f --- /dev/null +++ b/src/SMAPI/GameFramework.cs @@ -0,0 +1,12 @@ +namespace StardewModdingAPI +{ + /// The game framework running the game. + public enum GameFramework + { + /// The XNA Framework on Windows. + Xna, + + /// The MonoGame framework, usually on non-Windows platforms. + MonoGame + } +} -- cgit