private void LightingRenderer_DrawLightOccluders(ILContext il) { MethodReference m_get_Tracker = il.Import(typeof(Scene).GetProperty("Tracker").GetGetMethod()); MethodReference m_GetComponents = il.Import(typeof(Tracker).GetMethod("GetComponents").MakeGenericMethod(typeof(LightOccludeList))); MethodReference f_get_Tracker = il.Import(typeof(Tracker).GetProperty("Tracker").GetGetMethod()); ILCursor c = new ILCursor(il); c.GotoNext(i => i.OpCode == OpCodes.Callvirt && ((MethodReference)i.Operand).Name == "GetComponents") .GotoNext(MoveType.After); //c.Emit(OpCodes.Ldloc_1); }
internal static void IlEditing(ILContext il) { MethodReference getItemReference = null; MethodReference setItemReference = null; foreach (var instruction in il.Body.Instructions) { if (instruction.OpCode == OpCodes.Ldftn) { MethodReference function = (MethodReference)instruction.Operand; if (!function.Name.Contains(_blacklistLoadFnt[0]) && !function.Name.Contains(_blacklistLoadFnt[1]) && !function.Name.Contains(_blacklistLoadFnt[2])) { InfWorld.Instance.Logger.Info("Loadfnt detected : " + function.Name); HookEndpointManager.Modify(function.ResolveReflection(), new ILContext.Manipulator(IlEditing)); } } else if (instruction.OpCode == OpCodes.Ldsfld) { if (instruction.Operand is FieldReference fieldRef && fieldRef.DeclaringType.FullName == "Terraria.Main" && fieldRef.Name == "tile") { FieldReference tileReference = il.Module.ImportReference(typeof(InfWorld).GetField("Tile", BindingFlags.Public | BindingFlags.Static)); instruction.Operand = tileReference; } } else if (instruction.OpCode == OpCodes.Call && instruction.Operand is Mono.Cecil.MethodReference reference) { if (reference.FullName == ("Terraria.Tile Terraria.Tile[0...,0...]::Get(System.Int32,System.Int32)")) { instruction.OpCode = OpCodes.Callvirt; if (getItemReference == null) { getItemReference = il.Import(getItem); } instruction.Operand = getItemReference; } else if (reference.FullName == ("System.Void Terraria.Tile[0...,0...]::Set(System.Int32,System.Int32,Terraria.Tile)")) { instruction.OpCode = OpCodes.Callvirt; if (setItemReference == null) { setItemReference = il.Import(setItem); } instruction.Operand = setItemReference; } } } }
private static void CreatePatchedMethod(ILContext il) { ILCursor c = new ILCursor(il); // The original method uses System.Reflection.Emit. System.Type t_DynamicTools = GetHarmonyType("DynamicTools"); // Find and replace DynamicTools.CreateDynamicMethod if (!c.TryGotoNext(i => i.MatchCall(t_DynamicTools, "CreateDynamicMethod"))) { // Not the right method. Harmony defines two CreatePatchedMethod methods. il.MakeReadOnly(); return; } c.Next.OpCode = OpCodes.Call; c.Next.Operand = il.Import(typeof(HarmonyDetourBridge).GetMethod("CreateDMD", BindingFlags.NonPublic | BindingFlags.Static)); // Find the variable holding the "dynamic method" and update it. int varDMDi = -1; c.GotoNext(i => i.MatchStloc(out varDMDi)); VariableDefinition varDMD = il.Body.Variables[varDMDi]; varDMD.VariableType = il.Import(typeof(DynamicMethodDefinition)); // Find and replace patch.GetILGenerator c.GotoNext(i => i.MatchCallvirt<System.Reflection.Emit.DynamicMethod>("GetILGenerator")); c.Next.OpCode = OpCodes.Call; c.Next.Operand = il.Import(typeof(DynamicMethodDefinition).GetMethod("GetILGenerator", BindingFlags.Public | BindingFlags.Instance)); // Find and remove DynamicTools.PrepareDynamicMethod c.GotoNext(i => i.MatchCall(t_DynamicTools, "PrepareDynamicMethod")); c.Next.OpCode = OpCodes.Pop; c.Next.Operand = null; // Go to the next ldloc that loads the DynamicMethod. // No matter if it gets stored into a local variable or returned immediately, // grab it, store it separately and push null as a replacement. c.GotoNext(i => i.MatchLdloc(varDMDi)); c.Index++; c.EmitDelegate<Func<DynamicMethodDefinition, System.Reflection.Emit.DynamicMethod>>(dmd => { _LastWrapperDMD = dmd; return null; }); }
private static void SmoothDropDownSuggestionNavigation(ILContext il) { var cursor = new ILCursor(il); var getKey = il.Import(typeof(Input).GetMethodCached("GetKey", new [] { typeof(KeyCode) })); cursor.GotoNext( MoveType.After, x => x.MatchLdcI4(0x111), x => x.MatchCallOrCallvirt <Input>("GetKeyDown") ); cursor.Prev.Operand = getKey; cursor.EmitDelegate <Func <bool, bool> >(LimitChangeItemFrequency); cursor.GotoNext( MoveType.After, x => x.MatchLdcI4(0x112), x => x.MatchCallOrCallvirt <Input>("GetKeyDown") ); cursor.Prev.Operand = getKey; cursor.EmitDelegate <Func <bool, bool> >(LimitChangeItemFrequency); bool LimitChangeItemFrequency(bool canChangeItem) { if (canChangeItem) { var timeNow = Time.time; if (timeNow > changeSelectedItemTimer + _lastSelectedItemChange) { _lastSelectedItemChange = timeNow; return(true); } else { return(false); } } return(canChangeItem); } }
internal static void Sequence(ILContext il) { FieldReference fieldRef = il.Import(f_Sequence_this); ILCursor c = new ILCursor(il); c.GotoNext(MoveType.After, instr => instr.MatchCallOrCallvirt(typeof(Platform), "StopShaking")); Instruction next = c.Next; Instruction after = new ILCursor(c).GotoNext(instr => instr.Match(OpCodes.Ldarg_0) && instr.Next.OpCode == OpCodes.Ldc_R4 && ((float)instr.Next.Operand) == 0f).Next; c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, fieldRef); c.Emit(OpCodes.Isinst, typeof(FancyFallingBlock)); c.Emit(OpCodes.Brfalse_S, next); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, fieldRef); c.Emit(OpCodes.Call, typeof(FancyFallingBlock).GetMethod(nameof(FallParticles), BindingFlags.NonPublic | BindingFlags.Instance)); c.Emit(OpCodes.Br, after); }
internal static void Sequence(ILContext il) { FieldReference fieldRef = il.Import(f_Sequence_this); TypeDefinition typeRef = ModuleDefinition.ReadModule(typeof(FancyFallingBlock).Assembly.Location).GetType("Celeste.Mod.FancyTileEntities.FancyFallingBlock"); ILCursor c = new ILCursor(il); c.GotoNext(MoveType.After, instr => instr.MatchCallOrCallvirt(typeof(Platform), "StopShaking")); Instruction next = c.Next; Instruction after = new ILCursor(c).GotoNext(instr => instr.Match(OpCodes.Ldarg_0) && instr.Next.OpCode == OpCodes.Ldc_R4 && ((float)instr.Next.Operand) == 0f).Next; c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, fieldRef); c.Emit(OpCodes.Isinst, typeRef); c.Emit(OpCodes.Brfalse_S, next); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, fieldRef); c.Emit(OpCodes.Call, typeRef.FindMethod("System.Void FallParticles()")); c.Emit(OpCodes.Br, after); }
private static void FixMoveAllPerformance(ILContext il) { var cursor = new ILCursor(il); var optimizedRemoveItemMethodReference = il.Import(typeof(SaveManager).GetMethod(nameof(SaveManager.OptimizedRemoveItem), ReflectionHelper.AllBindingFlags)); if (cursor.TryGotoNext(i => i.MatchCallOrCallvirt <Inventory>(nameof(Inventory.RemoveItem)))) { cursor.Next.Operand = optimizedRemoveItemMethodReference; if (cursor.TryGotoNext(i => i.MatchCallOrCallvirt <Inventory>(nameof(Inventory.RemoveItem)))) { cursor.Next.Operand = optimizedRemoveItemMethodReference; } else { Logger.LogError($"Failed ILHook {nameof(Inventory.MoveAll)} 2."); } } else { Logger.LogError($"Failed ILHook {nameof(Inventory.MoveAll)} 1."); } }
private static void Player_QuickBuff(ILContext il) { il.Body.Variables.Add(new VariableDefinition(il.Import(typeof(ValueTuple <LegacySoundStyle, bool>)))); ILCursor cursor = new ILCursor(il); if (cursor.TryGotoNext(i => i.MatchLdnull(), i => i.MatchStloc(0))) { cursor.Index += 2; ILLabel label = cursor.DefineLabel(); cursor.Emit(OpCodes.Ldarg_0); cursor.EmitDelegate <Func <Player, ValueTuple <LegacySoundStyle, bool> > >(player => { LegacySoundStyle legacySoundStyle = null; foreach (Item item in player.inventory.OfType <AlchemistBag>().SelectMany(x => x.Handler.Items)) { if (player.CountBuffs() == 22) { return(null, true); } if (item.stack > 0 && item.type > 0 && item.buffType > 0 && !item.summon && item.buffType != 90) { int buffType = item.buffType; bool useItem = ItemLoader.CanUseItem(item, player); for (int buffIndex = 0; buffIndex < 22; buffIndex++) { if (buffType == 27 && (player.buffType[buffIndex] == buffType || player.buffType[buffIndex] == 101 || player.buffType[buffIndex] == 102)) { useItem = false; break; } if (player.buffType[buffIndex] == buffType) { useItem = false; break; } if (Main.meleeBuff[buffType] && Main.meleeBuff[player.buffType[buffIndex]]) { useItem = false; break; } } if (Main.lightPet[item.buffType] || Main.vanityPet[item.buffType]) { for (int buffIndex = 0; buffIndex < 22; buffIndex++) { if (Main.lightPet[player.buffType[buffIndex]] && Main.lightPet[item.buffType]) { useItem = false; } if (Main.vanityPet[player.buffType[buffIndex]] && Main.vanityPet[item.buffType]) { useItem = false; } } } if (item.mana > 0 && useItem) { if (player.statMana >= (int)(item.mana * player.manaCost)) { player.manaRegenDelay = (int)player.maxRegenDelay; player.statMana -= (int)(item.mana * player.manaCost); } else { useItem = false; } } if (player.whoAmI == Main.myPlayer && item.type == 603 && !Main.cEd) { useItem = false; } if (buffType == 27) { buffType = Main.rand.Next(3); if (buffType == 0) { buffType = 27; } if (buffType == 1) { buffType = 101; } if (buffType == 2) { buffType = 102; } } if (useItem) { ItemLoader.UseItem(item, player); legacySoundStyle = item.UseSound; int buffTime = item.buffTime; if (buffTime == 0) { buffTime = 3600; } player.AddBuff(buffType, buffTime); if (item.consumable) { if (ItemLoader.ConsumeItem(item, player)) { item.stack--; } if (item.stack <= 0) { item.TurnToAir(); } } } } } return(legacySoundStyle, false); }); Type type = typeof(ValueTuple <LegacySoundStyle, bool>); cursor.Emit(OpCodes.Stloc, 7); cursor.Emit(OpCodes.Ldloc, 7); cursor.Emit(OpCodes.Ldfld, type.GetField("Item1", BaseLibrary.Utility.defaultFlags)); cursor.Emit(OpCodes.Stloc, 0); cursor.Emit(OpCodes.Ldloc, 7); cursor.Emit(OpCodes.Ldfld, type.GetField("Item2", BaseLibrary.Utility.defaultFlags)); cursor.Emit(OpCodes.Brfalse, label); cursor.Emit(OpCodes.Ret); cursor.MarkLabel(label); } }