Beispiel #1
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .End()
                                  .MatchBack(false,
                                             new CodeMatch(OpCodes.Ldarg_0),
                                             new CodeMatch(OpCodes.Ldflda, AccessTools.Field(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.cursorTarget))));

            CodeMatcher matcher2 = matcher.Clone().MatchForward(false,
                                                                new CodeMatch(OpCodes.Ldloc_S),
                                                                new CodeMatch(OpCodes.Ldc_I4_S)
                                                                , new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(BuildPreview), nameof(BuildPreview.condition))));

            object previewVariable = matcher2.Operand;

            matcher.Advance(1);

            while (matcher.Opcode != OpCodes.Stloc_S)
            {
                matcher.RemoveInstruction();
            }

            matcher.InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, previewVariable))
            .InsertAndAdvance(Transpilers.EmitDelegate <Func <BuildTool_BlueprintPaste, BuildPreview, Vector3> >((tool, preview) =>
                                                                                                                 preview.lpos.normalized * Mathf.Min(tool.planet.realRadius * 0.025f, 20f)));

            return(matcher.InstructionEnumeration());
        }
Beispiel #2
0
            private static IEnumerable<CodeInstruction> FixUpdateCalcGarbage(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var c = new CodeMatcher(instructions, generator);
                // Remove unnecessary new object creation that gets immediately overwritten
                c.MatchForward(false,
                    new CodeMatch(OpCodes.Newobj),
                    new CodeMatch(OpCodes.Stloc_1),
                    new CodeMatch(OpCodes.Ldarg_0),
                    new CodeMatch(OpCodes.Ldfld));

                if (c.IsInvalid) return instructions;

                return c
                    .RemoveInstruction()
                    .RemoveInstruction()
                    .Instructions();
            }
        static IEnumerable <CodeInstruction> RefreshPreviews(IEnumerable <CodeInstruction> instructions, ILGenerator generator)
        {
            float MirrorBuildingRotation(float yaw, BlueprintBuilding building)
            {
                if (buildingsAxis.ContainsKey(building.modelIndex) && buildingsAxis[building.modelIndex] == MajorAxis.XAXIS)
                {
                    return(MirrorRotation(yaw + 90f) - 90f);
                }

                return(MirrorRotation(yaw));
            }

            CodeMatcher matcher = new CodeMatcher(instructions, generator)
                                  .MatchForward(true,
                                                new CodeMatch(OpCodes.Ldelem, typeof(Vector4)),
                                                new CodeMatch(OpCodes.Stloc_S),
                                                new CodeMatch(OpCodes.Ldloca_S));

            matcher.Advance(1);

            object longAxisVar = matcher.Operand;

            while (matcher.Opcode != OpCodes.Stfld)
            {
                matcher.RemoveInstruction();
            }

            matcher.RemoveInstructions(2);

            object latAxisVar = matcher.Operand;

            while (matcher.Opcode != OpCodes.Stfld)
            {
                matcher.RemoveInstruction();
            }

            matcher.RemoveInstruction()
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, longAxisVar))
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, latAxisVar))
            .InsertAndAdvance(Transpilers.EmitDelegate <RefAction>(MirrorArea));

            matcher.MatchForward(false,
                                 new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(BlueprintUtils), nameof(BlueprintUtils.TransitionWidthAndHeight))))
            .Advance(-3)
            .RemoveInstruction().RemoveInstruction().RemoveInstruction()
            .SetInstruction(Transpilers.EmitDelegate <Func <float, BlueprintBuilding, Vector2> >((yaw, building) =>
            {
                float x = building.localOffset_x;
                float y = building.localOffset_y;


                if ((mirrorLat && !mirrorLong || !mirrorLat && mirrorLong) && buildingsOffsets.ContainsKey(building.modelIndex))
                {
                    Vector2 offset   = buildingsOffsets[building.modelIndex];
                    float rotatedYaw = MirrorBuildingRotation(building.yaw, building);

                    offset = offset.Rotate(rotatedYaw + (mirrorLong ? 180 : 0));

                    x += offset.x;
                    y += offset.y;
                }

                return(BlueprintUtils.TransitionWidthAndHeight(yaw, x, y));
            }));

            matcher.MatchForward(false,
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BlueprintBuilding), nameof(BlueprintBuilding.yaw)))
                                 ).Advance(1)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 30))
            .InsertAndAdvance(Transpilers.EmitDelegate <Func <float, BlueprintBuilding, float> >(MirrorBuildingRotation)).Advance(2);

            matcher.MatchForward(false,
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BlueprintBuilding), nameof(BlueprintBuilding.yaw2)))
                                 ).Advance(1)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 30))
            .InsertAndAdvance(Transpilers.EmitDelegate <Func <float, BlueprintBuilding, float> >(MirrorBuildingRotation));

            matcher.MatchForward(true,
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BuildPreview), nameof(BuildPreview.desc))),
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PrefabDesc), nameof(PrefabDesc.isInserter))))
            .Advance(2);

            object previewVar2 = matcher.Operand;

            matcher.Advance(1)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, previewVar2))
            .InsertAndAdvance(Transpilers.EmitDelegate <Action <BuildPreview> >(preview =>
            {
                if (preview.input != null && preview.input.desc.slotPoses.Length > preview.inputFromSlot &&
                    !preview.input.desc.isBelt)
                {
                    Quaternion invRot       = Quaternion.Inverse(preview.input.lrot);
                    Vector3 slotPosition    = preview.lpos - preview.input.lpos;
                    slotPosition            = invRot * slotPosition;
                    Quaternion slotRotation = invRot * preview.lrot;


                    for (int i = 0; i < preview.input.desc.slotPoses.Length; i++)
                    {
                        Pose slotPose = preview.input.desc.slotPoses[i];
                        if (!((slotPose.position - slotPosition).sqrMagnitude < 0.1f))
                        {
                            continue;
                        }
                        if (!slotPose.rotation.Approximately(slotRotation))
                        {
                            continue;
                        }
                        if (preview.inputFromSlot == i)
                        {
                            break;
                        }

                        preview.inputFromSlot = i;
                        break;
                    }
                }

                if (preview.output != null && preview.output.desc.slotPoses.Length > preview.outputToSlot &&
                    !preview.output.desc.isBelt)
                {
                    Quaternion invRot       = Quaternion.Inverse(preview.output.lrot);
                    Vector3 slotPosition    = preview.lpos2 - preview.output.lpos;
                    slotPosition            = invRot * slotPosition;
                    Quaternion slotRotation = invRot * (preview.lrot2 * Quaternion.Euler(0f, -180f, 0f));

                    for (int i = 0; i < preview.output.desc.slotPoses.Length; i++)
                    {
                        Pose slotPose = preview.output.desc.slotPoses[i];
                        if (!((slotPose.position - slotPosition).sqrMagnitude < 0.1f))
                        {
                            continue;
                        }
                        if (!slotPose.rotation.Approximately(slotRotation))
                        {
                            continue;
                        }
                        if (preview.outputToSlot == i)
                        {
                            break;
                        }

                        preview.outputToSlot = i;
                        break;
                    }
                }
            }));


            return(matcher.InstructionEnumeration());
        }