diff --git a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldFinder.cs b/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldFinder.cs index 96e8b1c0..f2074f22 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldFinder.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldFinder.cs @@ -6,6 +6,13 @@ namespace StardewModdingAPI.AssemblyRewriters.Framework /// Base class for a field finder. public abstract class BaseFieldFinder : IInstructionFinder { + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public abstract string NounPhrase { get; } + + /********* ** Public methods *********/ diff --git a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodFinder.cs b/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodFinder.cs index 7526286a..bb71a9d7 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodFinder.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodFinder.cs @@ -9,6 +9,13 @@ namespace StardewModdingAPI.AssemblyRewriters.Framework /// Base class for a method finder. public abstract class BaseMethodFinder : IInstructionFinder { + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public abstract string NounPhrase { get; } + + /********* ** Public methods *********/ diff --git a/src/StardewModdingAPI.AssemblyRewriters/IInstructionFinder.cs b/src/StardewModdingAPI.AssemblyRewriters/IInstructionFinder.cs index 47a4247b..cc3006b9 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/IInstructionFinder.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/IInstructionFinder.cs @@ -5,6 +5,16 @@ namespace StardewModdingAPI.AssemblyRewriters /// Finds CIL instructions considered incompatible. public interface IInstructionFinder { + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + string NounPhrase { get; } + + + /********* + ** Methods + *********/ /// Get whether a CIL instruction matches. /// The IL instruction. /// Whether the mod was compiled on a different platform. diff --git a/src/StardewModdingAPI.AssemblyRewriters/IInstructionRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/IInstructionRewriter.cs index f99a0a5a..b230f227 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/IInstructionRewriter.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/IInstructionRewriter.cs @@ -6,6 +6,9 @@ namespace StardewModdingAPI.AssemblyRewriters /// Rewrites a CIL instruction for compatibility. public interface IInstructionRewriter : IInstructionFinder { + /********* + ** Methods + *********/ /// Rewrite a CIL instruction for compatibility. /// The module being rewritten. /// The CIL rewriter. diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/Crossplatform/SpriteBatch_MethodRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/Crossplatform/SpriteBatch_MethodRewriter.cs index a47b8410..1459ff17 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/Crossplatform/SpriteBatch_MethodRewriter.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/Crossplatform/SpriteBatch_MethodRewriter.cs @@ -12,6 +12,13 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters.Crossplatform [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "This class is not meant to be used directly, and is deliberately named to make it easier to know what it changes at a glance.")] public class SpriteBatch_MethodRewriter : BaseMethodRewriter { + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public override string NounPhrase { get; } = $"{nameof(SpriteBatch)} methods"; + + /********* ** Protected methods *********/ diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_ActiveClickableMenu_FieldRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_ActiveClickableMenu_FieldRewriter.cs index 66fe0369..bb49f16c 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_ActiveClickableMenu_FieldRewriter.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_ActiveClickableMenu_FieldRewriter.cs @@ -11,6 +11,13 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters.SDV1_2 [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "This class is not meant to be used directly, and is deliberately named to make it easier to know what it changes at a glance.")] public class Game1_ActiveClickableMenu_FieldRewriter : BaseFieldRewriter { + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public override string NounPhrase { get; } = $"{nameof(Game1)}.{nameof(Game1.activeClickableMenu)} field"; + + /********* ** Protected methods *********/ diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_GameMode_FieldRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_GameMode_FieldRewriter.cs index 9cb6e13d..4d84d9ac 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_GameMode_FieldRewriter.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_GameMode_FieldRewriter.cs @@ -11,6 +11,13 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters.SDV1_2 [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "This class is not meant to be used directly, and is deliberately named to make it easier to know what it changes at a glance.")] public class Game1_GameMode_FieldRewriter : BaseFieldRewriter { + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public override string NounPhrase { get; } = $"{nameof(Game1)}.{nameof(Game1.gameMode)} field"; + + /********* ** Protected methods *********/ diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_Player_FieldRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_Player_FieldRewriter.cs index 115e3d7d..f43f5d57 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_Player_FieldRewriter.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SDV1_2/Game1_Player_FieldRewriter.cs @@ -11,6 +11,13 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters.SDV1_2 [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "This class is not meant to be used directly, and is deliberately named to make it easier to know what it changes at a glance.")] public class Game1_Player_FieldRewriter : BaseFieldRewriter { + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public override string NounPhrase { get; } = $"{nameof(Game1)}.{nameof(Game1.player)} field"; + + /********* ** Protected methods *********/ diff --git a/src/StardewModdingAPI/Framework/AssemblyLoader.cs b/src/StardewModdingAPI/Framework/AssemblyLoader.cs index eb5d1cf4..8af67772 100644 --- a/src/StardewModdingAPI/Framework/AssemblyLoader.cs +++ b/src/StardewModdingAPI/Framework/AssemblyLoader.cs @@ -162,6 +162,7 @@ namespace StardewModdingAPI.Framework private bool RewriteAssembly(AssemblyDefinition assembly) { ModuleDefinition module = assembly.MainModule; + HashSet loggedRewrites = new HashSet(); // swap assembly references if needed (e.g. XNA => MonoGame) bool platformChanged = false; @@ -170,6 +171,7 @@ namespace StardewModdingAPI.Framework // remove old assembly reference if (this.AssemblyMap.RemoveNames.Any(name => module.AssemblyReferences[i].Name == name)) { + this.LogOnce(this.Monitor, loggedRewrites, $"Rewriting {assembly.Name.Name} for OS..."); platformChanged = true; module.AssemblyReferences.RemoveAt(i); i--; @@ -197,14 +199,16 @@ namespace StardewModdingAPI.Framework if (!canRewrite) continue; - // prepare method - ILProcessor cil = method.Body.GetILProcessor(); - // rewrite instructions + ILProcessor cil = method.Body.GetILProcessor(); foreach (Instruction op in cil.Body.Instructions.ToArray()) { IInstructionRewriter rewriter = rewriters.FirstOrDefault(p => p.IsMatch(op, platformChanged)); - rewriter?.Rewrite(module, cil, op, this.AssemblyMap); + if (rewriter != null) + { + this.LogOnce(this.Monitor, loggedRewrites, $"Rewriting {assembly.Name.Name} to fix {rewriter.NounPhrase}..."); + rewriter.Rewrite(module, cil, op, this.AssemblyMap); + } } // finalise method @@ -244,5 +248,19 @@ namespace StardewModdingAPI.Framework select method ); } + + /// Log a message for the player or developer the first time it occurs. + /// The monitor through which to log the message. + /// The hash of logged messages. + /// The message to log. + /// The log severity level. + private void LogOnce(IMonitor monitor, HashSet hash, string message, LogLevel level = LogLevel.Trace) + { + if (!hash.Contains(message)) + { + this.Monitor.Log(message, level); + hash.Add(message); + } + } } }