public static IEnumerable <CodeInstruction> _OnUpdate_Transpiler(IEnumerable <CodeInstruction> instructions) { try { int pos1, pos2; CodeMatcher matcher = new CodeMatcher(instructions); matcher.MatchForward(false, new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(DysonNode), "color"))); pos1 = matcher.Pos; matcher.MatchBack(false, new CodeMatch(OpCodes.Ldloc_S)); pos2 = matcher.Pos; matcher.Advance(pos1 - pos2 + 1) .Insert( new CodeInstruction(matcher.InstructionAt(pos2 - pos1 - 1)), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(UIDysonBrush_Paint_Transpiler), "SendNodePacket")) ); matcher.MatchForward(false, new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(DysonFrame), "color"))); pos1 = matcher.Pos; matcher.MatchBack(false, new CodeMatch(OpCodes.Ldloc_S)); pos2 = matcher.Pos; matcher.Advance(pos1 - pos2 + 1) .Insert( new CodeInstruction(matcher.InstructionAt(pos2 - pos1 - 1)), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(UIDysonBrush_Paint_Transpiler), "SendFramePacket")) ); matcher.MatchForward(false, new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(DysonShell), "color"))); pos1 = matcher.Pos; matcher.MatchBack(false, new CodeMatch(OpCodes.Ldloc_S)); pos2 = matcher.Pos; matcher.Advance(pos1 - pos2 + 1) .Insert( new CodeInstruction(matcher.InstructionAt(pos2 - pos1 - 1)), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(UIDysonBrush_Paint_Transpiler), "SendShellPacket")) ); return(matcher.InstructionEnumeration()); } catch { NebulaModel.Logger.Log.Error("UIDysonBrush_Paint._OnUpdate_Transpiler failed. Mod version not compatible with game version."); return(instructions); } }
private static IEnumerable <CodeInstruction> CreatePrebuilds_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator il) { /* * Inserts * if(!Multiplayer.IsActive) * Before trying to take items, so that all prebuilds are assumed to require items while in MP */ CodeMatcher matcher = new CodeMatcher(instructions, il) .MatchForward(true, new CodeMatch(i => i.IsLdloc()), // count new CodeMatch(OpCodes.Ldc_I4_1), new CodeMatch(OpCodes.Ceq), new CodeMatch(OpCodes.Brfalse) ); if (matcher.IsInvalid) { NebulaModel.Logger.Log.Error("BuildTool_BlueprintPaste.CreatePrebuilds_Transpiler failed. Mod version not compatible with game version."); return(instructions); } object jumpOperand = matcher.Instruction.operand; matcher = matcher .MatchBack(false, new CodeMatch(i => i.IsLdloc()), new CodeMatch(i => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "item"), new CodeMatch(i => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "ID"), new CodeMatch(i => i.IsStloc()) ); if (matcher.IsInvalid) { NebulaModel.Logger.Log.Error("BuildTool_BlueprintPaste.CreatePrebuilds_Transpiler 2 failed. Mod version not compatible with game version."); return(instructions); } return(matcher .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() => { return Multiplayer.IsActive; })) .InsertAndAdvance(new CodeInstruction(OpCodes.Brtrue, jumpOperand)) .InstructionEnumeration()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { CodeMatcher codeMatcher = new CodeMatcher(instructions); object label; // CodeMatcher needs some better label manipulating methods // replace rotation stuff codeMatcher .MatchForward( false, new CodeMatch(OpCodes.Callvirt, _localRotationSetter)) .Advance(1); int endPos = codeMatcher.Pos; label = codeMatcher.Labels.First(); codeMatcher .MatchBack( false, new CodeMatch(null, label)) .Advance(1) .RemoveInstructions(endPos - codeMatcher.Pos) .InsertAndAdvance( new CodeInstruction(OpCodes.Ldloc_1), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _startRotationField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _middleRotationField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _endRotationField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _playerTransformsField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _rotatedObjectField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Call, _getTransform), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _inverseWorldRotationField), new CodeInstruction(OpCodes.Call, _doNoteLook)) // Add addition check to our quirky little variable to skip end position offset when we are using definitePosition .MatchForward( true, new CodeMatch(OpCodes.Ldfld, _threeQuartersMarkReportedField), new CodeMatch(OpCodes.Brfalse)); label = codeMatcher.Operand; codeMatcher .Advance(1) .Insert( new CodeInstruction(OpCodes.Ldsfld, _definitePositionField), new CodeInstruction(OpCodes.Brtrue_S, label)) .Start(); return(codeMatcher // time adjust .MatchForward(false, new CodeMatch(OpCodes.Stloc_0)) .InsertAndAdvance( new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _jumpDurationField), new CodeInstruction(OpCodes.Call, _noteJumpTimeAdjust)) // final position .MatchForward(false, new CodeMatch(OpCodes.Stind_R4)) .Advance(2) .InsertAndAdvance( new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _localPositionField), new CodeInstruction(OpCodes.Ldloc_1), new CodeInstruction(OpCodes.Call, _definiteNoteJump), new CodeInstruction(OpCodes.Stfld, _localPositionField)) .InstructionEnumeration()); }