using System.Diagnostics.CodeAnalysis; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Mono.Cecil; using Mono.Cecil.Cil; using StardewModdingAPI.AssemblyRewriters.Framework; namespace StardewModdingAPI.AssemblyRewriters.Rewriters { /// Rewrites references to to fix inconsistent method signatures between MonoGame and XNA. /// MonoGame has one SpriteBatch.Begin method with optional arguments, but XNA has multiple method overloads. Incompatible method references are rewritten to use , which redirects all method signatures to the proper compiled MonoGame/XNA method. public class SpriteBatchRewriter : BaseMethodRewriter { /********* ** Protected methods *********/ /// Get whether a method reference should be rewritten. /// The IL instruction. /// The method reference. /// Whether the mod was compiled on a different platform. protected override bool ShouldRewrite(Instruction instruction, MethodReference methodRef, bool platformChanged) { return platformChanged && methodRef.DeclaringType.FullName == typeof(SpriteBatch).FullName && this.HasMatchingSignature(typeof(SpriteBatchRewriter.WrapperMethods), methodRef); } /// Rewrite a method for compatibility. /// The module being rewritten. /// The CIL rewriter. /// The instruction which calls the method. /// The method reference invoked by the . /// Metadata for mapping assemblies to the current platform. protected override void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, MethodReference methodRef, PlatformAssemblyMap assemblyMap) { methodRef.DeclaringType = module.Import(typeof(SpriteBatchRewriter.WrapperMethods)); } /********* ** Wrapper methods *********/ /// Wraps methods that are incompatible when converting compiled code between MonoGame and XNA. public class WrapperMethods : SpriteBatch { /********* ** Public methods *********/ /// Construct an instance. public WrapperMethods(GraphicsDevice graphicsDevice) : base(graphicsDevice) { } /**** ** MonoGame signatures ****/ [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Linux/Mac.")] public new void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix? matrix) { base.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, matrix ?? Matrix.Identity); } /**** ** XNA signatures ****/ [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] public new void Begin() { base.Begin(); } [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] public new void Begin(SpriteSortMode sortMode, BlendState blendState) { base.Begin(sortMode, blendState); } [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] public new void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState) { base.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState); } [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] public new void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect) { base.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect); } [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] public new void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix transformMatrix) { base.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, transformMatrix); } } } }