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);
+ }
+ }
}
}