using System; using Mono.Cecil; using Mono.Cecil.Cil; using StardewModdingAPI.Framework.ModLoading.Framework; namespace StardewModdingAPI.Framework.ModLoading.Rewriters { /// Rewrites static field references into constant values. /// The constant value type. internal class StaticFieldToConstantRewriter : BaseInstructionHandler { /********* ** Fields *********/ /// The type containing the field to which references should be rewritten. private readonly Type Type; /// The field name to which references should be rewritten. private readonly string FromFieldName; /// The constant value to replace with. private readonly TValue Value; /********* ** Public methods *********/ /// Construct an instance. /// The type whose field to which references should be rewritten. /// The field name to rewrite. /// The constant value to replace with. public StaticFieldToConstantRewriter(Type type, string fieldName, TValue value) : base(defaultPhrase: $"{type.FullName}.{fieldName} field") { this.Type = type; this.FromFieldName = fieldName; this.Value = value; } /// public override bool Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, Action replaceWith) { // get field reference FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction); if (!RewriteHelper.IsFieldReferenceTo(fieldRef, this.Type.FullName, this.FromFieldName)) return false; // rewrite to constant if (typeof(TValue) == typeof(int)) { instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = this.Value; } else if (typeof(TValue) == typeof(string)) { instruction.OpCode = OpCodes.Ldstr; instruction.Operand = this.Value; } else throw new NotSupportedException($"Rewriting to constant values of type {typeof(TValue)} isn't currently supported."); return this.MarkRewritten(); } } }