本文整理汇总了C#中Mono.Cecil.MethodDefinition.InjectEndCallback方法的典型用法代码示例。如果您正苦于以下问题:C# MethodDefinition.InjectEndCallback方法的具体用法?C# MethodDefinition.InjectEndCallback怎么用?C# MethodDefinition.InjectEndCallback使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Mono.Cecil.MethodDefinition
的用法示例。
在下文中一共展示了MethodDefinition.InjectEndCallback方法的2个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: HookNpcLoot
private void HookNpcLoot()
{
//Create an empty method with the same parameters as Terraria.Main.NewItem
//Then with the method body, add the hooks and the actual call to ""
//Replace all calls to NewItem in NPCLoot
var npcLoot = Terraria.NPC.Method("NPCLoot");
var newItem = Terraria.Item.Method("NewItem");
//Create the new DropLoot call in the Terraria.NPC class
var dropLoot = new MethodDefinition("DropLoot", MethodAttributes.Public | MethodAttributes.Static, newItem.ReturnType);
Terraria.NPC.Methods.Add(dropLoot);
//Clone the parameters
foreach (var prm in newItem.Parameters)
dropLoot.Parameters.Add(prm);
// //Add the this call to the end
// dropLoot.Parameters.Add(new ParameterDefinition("npcId", ParameterAttributes.HasDefault, Terraria.TypeSystem.Int32));
//Collect the hooks
var apiMatch = API.NPCCallback.Methods.Where(x => x.Name.StartsWith("OnDropLoot"));
if (apiMatch.Count() != 2) throw new InvalidOperationException("There is no matching OnDropLoot Begin/End calls in the API");
var cbkBegin = apiMatch.Single(x => x.Name.EndsWith("Begin"));
var cbkEnd = apiMatch.Single(x => x.Name.EndsWith("End"));
//Create the value to hold the new item id
var il = dropLoot.Body.GetILProcessor();
var vrbItemId = new VariableDefinition("otaItem", (cbkBegin.Parameters[0].ParameterType as ByReferenceType).ElementType);
dropLoot.Body.Variables.Add(vrbItemId);
il.Emit(OpCodes.Ldloca_S, vrbItemId); //Loads our variable as a reference
var beginResult = dropLoot.InjectBeginCallback(cbkBegin, false, false);
var insFirstForMethod = dropLoot.InjectMethodCall(newItem, false, false);
il.Emit(OpCodes.Stloc, vrbItemId);
//Set the instruction to be resumed upon not cancelling, if not already
if (beginResult != null && beginResult.OpCode == OpCodes.Pop)
{
beginResult.OpCode = OpCodes.Brtrue_S;
beginResult.Operand = insFirstForMethod;
il.InsertAfter(beginResult, il.Create(OpCodes.Ret));
il.InsertAfter(beginResult, il.Create(OpCodes.Ldloc, vrbItemId));
}
dropLoot.InjectEndCallback(cbkEnd, false);
il.Emit(OpCodes.Ldloc, vrbItemId);
il.Emit(OpCodes.Ret);
var itemCalls = npcLoot.Body.Instructions.Where(x => x.OpCode == OpCodes.Call
&& x.Operand is MethodReference
&& (x.Operand as MethodReference).Name == "NewItem"
&& (x.Operand as MethodReference).DeclaringType.Name == "Item").ToArray();
// var whoAmI = Terraria.Entity.Field("whoAmI");
foreach (var call in itemCalls)
{
call.Operand = dropLoot;
// il.InsertBefore(call, il.Create(OpCodes.Ldarg_0));
// il.InsertBefore(call, il.Create(OpCodes.Ldfld, whoAmI));
}
//This section will add '&& num40 >= 0' to the statement above "Main.item [num40].color = this.color;"
var insColour = npcLoot.Body.Instructions.Single(x => x.OpCode == OpCodes.Ldfld && x.Operand == Terraria.NPC.Field("color")); //Grab where the call is located
var insColorStart = insColour.FindPreviousInstructionByOpCode(OpCodes.Ldsfld); //Find the first instruction for the color call
var resumeInstruction = insColorStart.Previous.Operand as Instruction; //Find the instruction where it should be transferred to if false is evaludated
il = npcLoot.Body.GetILProcessor();
//Insert the num40 variable
il.InsertBefore(insColorStart, il.Create(OpCodes.Ldloc, (VariableDefinition)insColorStart.Next.Operand));
//Place 0 on the stack
il.InsertBefore(insColorStart, il.Create(OpCodes.Ldc_I4_0));
//Compare the current values on stack, using >=
il.InsertBefore(insColorStart, il.Create(OpCodes.Blt, resumeInstruction));
npcLoot.Body.OptimizeMacros();
// //Add the instance to DropLoot [still kills the stack]
// var dropLootCalls = npcLoot.Body.Instructions.Where(x => x.OpCode == OpCodes.Call
// && x.Operand is MethodReference
// && (x.Operand as MethodReference).Name == "DropLoot").ToArray();
// dropLoot.Parameters.Add(new ParameterDefinition("npc", ParameterAttributes.None, Terraria.NPC)
// {
// HasDefault = true,
// IsOptional = true
// });
//
// foreach (var call in dropLootCalls)
// {
// il.InsertBefore(call, il.Create(OpCodes.Ldarg_0));
// }
}
示例2: Wrap
/// <summary>
/// Wraps the method with the specified begin/end calls
/// </summary>
/// <param name="method"></param>
/// <param name="begin"></param>
/// <param name="end"></param>
public static MethodDefinition Wrap(this MethodDefinition method, MethodReference begin, MethodReference end = null, bool beginIsCancellable = false)
{
if (!method.HasBody) throw new InvalidOperationException("Method must have a body.");
if (method.ReturnType.Name == "Void")
{
//Create the new replacement method
var wrapped = new MethodDefinition(method.Name, method.Attributes, method.ReturnType);
var instanceMethod = (method.Attributes & MethodAttributes.Static) == 0;
//Rename the existing method, and replace it
method.Name = method.Name + WrappedMethodNameSuffix;
method.ReplaceWith(wrapped);
//Copy over parameters
if (method.HasParameters)
foreach (var prm in method.Parameters)
{
wrapped.Parameters.Add(prm);
}
//Place the new method in the declaring type of the method we are cloning
method.DeclaringType.Methods.Add(wrapped);
var beginResult = wrapped.InjectBeginCallback(begin, instanceMethod, beginIsCancellable);
//Execute the actual code
var insFirstForMethod = wrapped.InjectMethodCall(method, instanceMethod);
//Set the instruction to be resumed upon not cancelling, if not already
if (beginIsCancellable && beginResult != null && beginResult.OpCode == OpCodes.Nop)
{
beginResult.OpCode = OpCodes.Brtrue_S;
beginResult.Operand = insFirstForMethod;
}
if (end != null)
{
wrapped.InjectEndCallback(end, instanceMethod);
}
wrapped.InjectMethodEnd();
// var xstFirst = method.Body.Instructions.First();
//// var xstLast = method.Body.Instructions.Last(x => x.OpCode == OpCodes.Ret);
// var lastInstruction = method.Body.Instructions.Last();
//
// if (begin.HasParameters) //Parameter order must be the same
// {
// for (var i = 0; i < begin.Parameters.Count; i++)
// {
// var prm = method.CreateParameterInstruction(i);
// il.InsertBefore(xstFirst, prm);
// }
// }
// il.InsertBefore(xstFirst, il.Create(OpCodes.Call, impBegin));
//
//
//
// Instruction insertion = il.Create(OpCodes.Ret);
// Instruction endpoint = null;
// il.InsertAfter(lastInstruction, insertion);
//
//
//
// var nop = il.Create(OpCodes.Nop);
// if (null == endpoint) endpoint = nop;
// il.InsertBefore(insertion, nop);
//
// if (end.HasParameters) //Parameter order must be the same
// {
// for (var i = 0; i < end.Parameters.Count; i++)
// {
// var prm = method.CreateParameterInstruction(i);
// il.InsertBefore(insertion, prm);
//// il.InsertBefore(lastInstruction, prm);
// if (null == endpoint) endpoint = prm;
// }
// }
//
// var injected = new List<Instruction>();
// var total = 0;
// while (total++ < 6)
// {
// var ins = method.Body.Instructions.Except(injected).First(xx => xx.OpCode == OpCodes.Ret);
//
// if (end.HasParameters) //Parameter order must be the same
// {
// for (var i = 0; i < end.Parameters.Count; i++)
// {
// var prm = method.CreateParameterInstruction(i);
// il.InsertBefore(ins, prm);
// }
// }
// il.InsertBefore(ins, il.Create(OpCodes.Call, impEnd));
// il.InsertBefore(ins, il.Create(OpCodes.Pop));
//.........这里部分代码省略.........