Esempio n. 1
0
            private static IEnumerable <CodeInstruction> TryPlayCustomTopicAdvTpl(IEnumerable <CodeInstruction> instructions)
            {
                var matcher = new CodeMatcher(instructions)
                              .MatchForward(true, new CodeMatch(OpCodes.Ldstr, "話題を振る"))
                              .MatchForward(true, new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(TalkScene), nameof(TalkScene.isNPC))))
                              .Advance(1)
                              .ThrowIfNotMatch("Brtrue not found", new CodeMatch(OpCodes.Brtrue));

                var startPos = matcher.Pos;

                // Figure out where the if else ends so we can jump there if we want to skip it
                // First go to the start of else, then step back and get the label at the end of if that skips over the else
                var elseLabel = ((Label)matcher.Operand);

                matcher.MatchForward(false, new CodeMatch(instruction => instruction.labels.Contains(elseLabel)))
                .Advance(-1)
                .ThrowIfNotMatch("Br not found", new CodeMatch(OpCodes.Br));
                var skipIfelseLabel = matcher.Operand;

                // Go back to the start of the if
                matcher.Advance(startPos - matcher.Pos).ThrowIfNotMatch("Brtrue not found 2", new CodeMatch(OpCodes.Brtrue));

                // Go back to the first if, then insert our if before it
                // Copy the `this` load instead of hardcoding it just in case (isNPC takes it)
                matcher.Advance(-2);
                var loadInstrCopy = new CodeInstruction(matcher.Opcode, matcher.Operand);

                matcher.Advance(1).Insert(
                    new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(TopicHooks), nameof(TryPlayCustomTopicAdvHook))),
                    new CodeInstruction(OpCodes.Brtrue, skipIfelseLabel),
                    loadInstrCopy);

                return(matcher.Instructions());
            }
Esempio n. 2
0
        public static IEnumerable <CodeInstruction> GameTick_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(true,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerControlGizmo), "player")),
                                                new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_controller"),
                                                new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_modelVisible"),
                                                new CodeMatch(OpCodes.Brfalse));
            var jmpPos = matcher.Operand;

            matcher.Advance(1)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
            .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <PlayerControlGizmo, bool> >((PlayerControlGizmo _this) =>
            {
                return(Multiplayer.IsActive && _this.player.navigation.indicatorAstroId > 100000);
            }))
            .Insert(new CodeInstruction(OpCodes.Brtrue, jmpPos));

            matcher.MatchForward(true,
                                 new CodeMatch(OpCodes.Ldarg_0),
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerControlGizmo), "player")),
                                 new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_navigation"),
                                 new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_indicatorAstroId"),
                                 new CodeMatch(OpCodes.Ldc_I4_0),
                                 new CodeMatch(OpCodes.Ble));
            jmpPos = matcher.Operand;
            matcher.Advance(1)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
            .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <PlayerControlGizmo, bool> >((PlayerControlGizmo _this) =>
            {
                return(Multiplayer.IsActive && _this.player.navigation.indicatorAstroId > 100000);
            }))
            .Insert(new CodeInstruction(OpCodes.Brtrue, jmpPos));

            matcher.MatchForward(true,
                                 new CodeMatch(OpCodes.Ldarg_0),
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerControlGizmo), "player")),
                                 new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_navigation"),
                                 new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_indicatorAstroId"),
                                 new CodeMatch(OpCodes.Ldc_I4_0),
                                 new CodeMatch(OpCodes.Ble));
            jmpPos = matcher.Operand;
            matcher.Advance(1)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
            .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <PlayerControlGizmo, bool> >((PlayerControlGizmo _this) =>
            {
                return(Multiplayer.IsActive && _this.player.navigation.indicatorAstroId > 100000);
            }))
            .Insert(new CodeInstruction(OpCodes.Brtrue, jmpPos));

            return(matcher.InstructionEnumeration());
        }
Esempio n. 3
0
        public static IEnumerable <CodeInstruction> CargoPathPatch(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(CargoPath), nameof(CargoPath.chunks))),
                                                new CodeMatch(OpCodes.Ldloc_S)
                                                );

            matcher.MatchForward(false, new CodeMatch(OpCodes.Stloc_S));
            object beginArg = matcher.Operand;

            matcher.Advance(1).MatchForward(false, new CodeMatch(OpCodes.Stloc_S));
            object speedArg = matcher.Operand;

            matcher.MatchForward(false,
                                 new CodeMatch(OpCodes.Ldc_I4_0),
                                 new CodeMatch(OpCodes.Stloc_S));

            matcher.Advance(2)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloca_S, beginArg))
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloca_S, speedArg))
            .InsertAndAdvance(Transpilers.EmitDelegate <RefAction <CargoPath, int, int> >((CargoPath path, ref int begin, ref int speed) =>
            {
                // The change
                if (speed > 10)     // If the speed is greater than 10, the length judgment process is performed to prevent crossing the boundary
                {
                    for (int i = 10; i <= speed; i++)
                    {
                        if (begin + i + 10 >= path.bufferLength)     // About to leave the end of the conveyor belt
                        {
                            speed = i;
                            break;
                        }

                        if (path.buffer[begin + i] != 0)     // Not empty within the speed range
                        {
                            speed = i;
                            break;
                        }
                    }

                    if (speed < 10)
                    {
                        speed = 10;     // If the speed slows down to within a safe speed, set it to a safe speed
                    }
                }
            }));

            return(matcher.InstructionEnumeration());
        }
Esempio n. 4
0
        public static IEnumerable <CodeInstruction> MultiplyUnlockText(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false, new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(TechProto), nameof(TechProto.UnlockFunctions))))
                                  .MatchForward(false, new CodeMatch(instr => instr.IsStloc()));

            OpCode typeStlocOpcode  = matcher.Opcode.ToLoad();
            object typeStlocOperand = matcher.Operand;

            matcher.MatchForward(false, new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(TechProto), nameof(TechProto.UnlockValues))))
            .MatchForward(false, new CodeMatch(OpCodes.Stloc_S));

            object arg = matcher.Operand;

            matcher.Advance(1)
            .InsertAndAdvance(new CodeInstruction(typeStlocOpcode, typeStlocOperand))
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloca_S, arg))
            .InsertAndAdvance(Transpilers.EmitDelegate <RefAction <int, int> >((int type, ref int value) =>
            {
                if (type == 18)
                {
                    value *= GigaStationsPlugin.droneCapacityMultiplier;
                }
                else if (type == 19)
                {
                    value *= GigaStationsPlugin.vesselCapacityMultiplier;
                }
            }));

            return(matcher.InstructionEnumeration());
        }
Esempio n. 5
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());
        }
        static IEnumerable <CodeInstruction> FindNext_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL)
        {
            var codeMatcher = new CodeMatcher(instructions, iL)
                              .MatchForward(false,
                                            new CodeMatch(i => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "serving"),
                                            new CodeMatch(i => i.IsLdloc()),
                                            new CodeMatch(OpCodes.Callvirt),
                                            new CodeMatch(OpCodes.Brtrue)
                                            );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("MechaDroneLogic_Transpiler.FindNext failed. Mod version not compatible with game version.");
                return(instructions);
            }

            var target = codeMatcher.InstructionAt(1);
            var jump   = codeMatcher.InstructionAt(3).operand;

            return(codeMatcher
                   .Advance(4)
                   .InsertAndAdvance(target)
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <int, bool> >((targetId) =>
            {
                return DroneManager.IsPendingBuildRequest(targetId);
            }))
                   .Insert(new CodeInstruction(OpCodes.Brtrue, jump))
                   .InstructionEnumeration());
        }
 public static IEnumerable <CodeInstruction> PowerSystem_RequestDysonSpherePower_Transpiler(IEnumerable <CodeInstruction> instructions)
 {
     //Prevent dysonSphere.energyReqCurrentTick from changing on the client side
     //Change: if (this.dysonSphere != null)
     //To:     if (this.dysonSphere != null && (!Multiplayer.IsActive || Multiplayer.Session.LocalPlayer.IsHost))
     try
     {
         CodeMatcher codeMatcher = new CodeMatcher(instructions)
                                   .MatchForward(true,
                                                 new CodeMatch(OpCodes.Ldarg_0),
                                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), "dysonSphere")),
                                                 new CodeMatch(OpCodes.Brfalse) //IL #93
                                                 );
         object label = codeMatcher.Instruction.operand;
         codeMatcher.Advance(1)
         .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
         {
             return(!Multiplayer.IsActive || Multiplayer.Session.LocalPlayer.IsHost);
         }))
         .InsertAndAdvance(new CodeInstruction(OpCodes.Brfalse_S, label));
         return(codeMatcher.InstructionEnumeration());
     }
     catch
     {
         NebulaModel.Logger.Log.Error("PowerSystem.RequestDysonSpherePower_Transpiler failed. Mod version not compatible with game version.");
         return(instructions);
     }
 }
Esempio n. 8
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator il)
        {
            var matcher = new CodeMatcher(instructions, il);

            // Search for the first time we check if the player has opened a chest, this happens when adding the items in the opened inventory to the dictionary
            matcher.MatchForward(false, new CodeMatch(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.player))), new CodeMatch(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.myPlayer))), new CodeMatch(OpCodes.Ldelem_Ref), new CodeMatch(OpCodes.Ldfld, typeof(Player).GetField(nameof(Player.chest))), new CodeMatch(OpCodes.Ldc_I4_M1), new CodeMatch(OpCodes.Beq));

            matcher.Instruction.opcode  = OpCodes.Nop;
            matcher.Instruction.operand = null;
            matcher.Advance(1);

            var getItemCode = new CodeInstruction[]
            {
                new CodeInstruction(OpCodes.Ldarg_0),
                new CodeInstruction(OpCodes.Ldloca_S, 1),
                new CodeInstruction(OpCodes.Ldloca_S, 2),
                new CodeInstruction(OpCodes.Call, typeof(StorageUI).GetMethod(nameof(StorageUI.DoWithdrawItemForCraft), new Type[] { typeof(Recipe), typeof(Item).MakeByRefType(), typeof(int).MakeByRefType() })),

                // The old instruction we destroyed
                new CodeInstruction(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.player)))
            };

            matcher.InsertAndAdvance(getItemCode);

            return(matcher.InstructionEnumeration());
        }
        private static IEnumerable <CodeInstruction> PickupBeltItems_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL)
        {
            CodeMatcher codeMatcher = new CodeMatcher(instructions, iL)
                                      .MatchForward(true,
                                                    new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == nameof(CargoPath.TryPickItem))
                                                    );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("CargoTraffic.PickupBeltItems_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }

            return(codeMatcher
                   .Advance(2)
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 5))
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_3))
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_2))
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_3))
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Action <int, int, int, bool> >((item, cnt, belt, all) =>
            {
                // Only pickup by hand needs to be synced
                if (Multiplayer.IsActive && !all)
                {
                    Multiplayer.Session.Belts.RegisterBeltPickupUpdate(item, cnt, belt);
                }
            }))
                   .InstructionEnumeration());
        }
Esempio n. 10
0
        public static IEnumerable <CodeInstruction> Get_nearestFactory_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            var matcher = new CodeMatcher(instructions)
                          .MatchForward(false,
                                        new CodeMatch(OpCodes.Ldloc_3),
                                        new CodeMatch(OpCodes.Ldloc_S),
                                        new CodeMatch(OpCodes.Ldelem_Ref),
                                        new CodeMatch(OpCodes.Stloc_S),
                                        new CodeMatch(OpCodes.Ldloc_S),
                                        new CodeMatch(OpCodes.Brfalse));

            if (matcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("Get_nearestFactory_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }

            var op = matcher.InstructionAt(5).operand;

            return(matcher
                   .Advance(-1)
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
            {
                return LocalPlayer.IsMasterClient || !SimulatedWorld.Initialized;
            }))
                   .Insert(new CodeInstruction(OpCodes.Brfalse, op))
                   .InstructionEnumeration());
        }
Esempio n. 11
0
        public static IEnumerable <CodeInstruction> Get_nearestFactory_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldloc_3),
                                                new CodeMatch(OpCodes.Ldloc_S),
                                                new CodeMatch(OpCodes.Ldelem_Ref),
                                                new CodeMatch(OpCodes.Stloc_S),
                                                new CodeMatch(OpCodes.Ldloc_S),
                                                new CodeMatch(OpCodes.Brfalse));

            if (matcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("Player.Get_nearestFactory_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }

            object op = matcher.InstructionAt(5).operand;

            return(matcher
                   .Advance(-1)
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
            {
                return !Multiplayer.IsActive || Multiplayer.Session.LocalPlayer.IsHost;
            }))
                   .Insert(new CodeInstruction(OpCodes.Brfalse, op))
                   .InstructionEnumeration());
        }
Esempio n. 12
0
        private static void MatchInserterEntityOnly(BuildTool_BlueprintPaste tool, BuildPreview bp)
        {
            IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
            {
                CodeMatcher matcher = new CodeMatcher(instructions)
                                      .MatchForward(true,
                                                    new CodeMatch(OpCodes.Ldloca_S),
                                                    new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(ColliderData), nameof(ColliderData.objType)))
                                                    )
                                      .MatchForward(false,
                                                    new CodeMatch(OpCodes.Ldloca_S),
                                                    new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(ColliderData), nameof(ColliderData.objType)))
                                                    );

                matcher.Opcode  = OpCodes.Nop;
                matcher.Operand = null;
                matcher.Advance(1)
                .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Nop))
                .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Nop))
                .SetOpcodeAndAdvance(OpCodes.Br);

                return(matcher.InstructionEnumeration());
            }

            // make compiler happy
            _ = Transpiler(null);
        }
Esempio n. 13
0
 static IEnumerable <CodeInstruction> InternalUpdateResearch_Transpiler(IEnumerable <CodeInstruction> instructions)
 {
     //Change: if (ts.hashUploaded >= ts.hashNeeded)
     //To:     if (ts.hashUploaded >= ts.hashNeeded && (!Multiplayer.IsActive || Multiplayer.Session.LocalPlayer.IsHost))
     try
     {
         CodeMatcher matcher = new CodeMatcher(instructions)
                               .MatchForward(true,
                                             new CodeMatch(i => i.IsLdarg()),
                                             new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(TechState), nameof(TechState.hashUploaded))),
                                             new CodeMatch(i => i.IsLdarg()),
                                             new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(TechState), nameof(TechState.hashNeeded))),
                                             new CodeMatch(OpCodes.Blt) //IL 339
                                             );
         object label = matcher.Instruction.operand;
         matcher.Advance(1)
         .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
         {
             return(!Multiplayer.IsActive || Multiplayer.Session.LocalPlayer.IsHost);
         }))
         .InsertAndAdvance(new CodeInstruction(OpCodes.Brfalse_S, label));
         return(matcher.InstructionEnumeration());
     }
     catch
     {
         NebulaModel.Logger.Log.Error("LabComponent.InternalUpdateResearch_Transpiler failed. Mod version not compatible with game version.");
         return(instructions);
     }
 }
        public static IEnumerable <CodeInstruction> Refresh_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL)
        {
            CodeMatcher codeMatcher = new CodeMatcher(instructions, iL)
                                      .MatchForward(true,
                                                    new CodeMatch(i => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "userName")
                                                    );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("UIVersionText.Refresh_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }

            return(codeMatcher
                   .Advance(1)
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <string, string> >((text) =>
            {
                if (Multiplayer.IsActive)
                {
                    text = $"{PluginInfo.PLUGIN_SHORT_NAME} {PluginInfo.PLUGIN_DISPLAY_VERSION}\r\n{text}";
                }
                return text;
            }))
                   .InstructionEnumeration());
        }
Esempio n. 15
0
        static IEnumerable <CodeInstruction> PickupBeltItems_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL)
        {
            var codeMatcher = new CodeMatcher(instructions, iL)
                              .MatchForward(true,
                                            new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == nameof(CargoPath.TryPickItem))
                                            );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("CargoTraffic.PickupBeltItems_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }

            var itemId = codeMatcher.InstructionAt(3);
            var count  = codeMatcher.InstructionAt(4);
            var beltId = new CodeInstruction(OpCodes.Ldarg_2);
            var segId  = codeMatcher.InstructionAt(-6);

            return(codeMatcher
                   .Advance(2)
                   .InsertAndAdvance(itemId)
                   .InsertAndAdvance(count)
                   .InsertAndAdvance(beltId)
                   .InsertAndAdvance(segId)
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Action <int, int, int, int> >((item, cnt, belt, seg) =>
            {
                if (SimulatedWorld.Initialized)
                {
                    BeltManager.RegisterBeltPickupUpdate(item, cnt, belt, seg);
                }
            }))
                   .InstructionEnumeration());
        }
Esempio n. 16
0
        public static CodeMatcher MoveToLabel(this CodeMatcher matcher, Label label)
        {
            while (!matcher.Labels.Contains(label))
            {
                matcher.Advance(1);
            }

            return(matcher);
        }
        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);
            }
        }
Esempio n. 18
0
        private static IEnumerable <CodeInstruction> FixedUpdate_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL)
        {
            CodeMatcher codeMatcher = new CodeMatcher(instructions, iL)
                                      .MatchForward(true,
                                                    new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Player), "ApplyGamePauseState")),
                                                    new CodeMatch(OpCodes.Ldarg_0),
                                                    new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameMain), "_paused")),
                                                    new CodeMatch(OpCodes.Brtrue)
                                                    );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("GameMain.FixedUpdate_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }
            object skipLabel1 = codeMatcher.Instruction.operand;

            codeMatcher
            .CreateLabelAt(codeMatcher.Pos + 1, out Label nextLabel1)
            .InsertAndAdvance(
                new CodeInstruction(OpCodes.Brfalse_S, nextLabel1),     //_paused== false => enter loop
                new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))),
                new CodeInstruction(OpCodes.Brfalse_S, skipLabel1),     //_paused== true && Multiplayer.Session == null => can pause, skip loop
                new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))),
                new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MultiplayerSession), nameof(MultiplayerSession.CanPause)))
                )
            .MatchForward(true,
                          new CodeMatch(OpCodes.Ldarg_0),
                          new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameMain), "_fullscreenPaused")),
                          new CodeMatch(OpCodes.Brfalse)
                          );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("GameMain.FixedUpdate_Transpiler 2 failed. Mod version not compatible with game version.");
                return(instructions);
            }

            object skipLabel2 = codeMatcher.Instruction.operand;

            return(codeMatcher
                   .Advance(1)
                   .CreateLabel(out Label nextLabel2)  //position of checking _fullscreenPausedUnlockOneFrame
                   .InsertAndAdvance(
                       new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))),
                       new CodeInstruction(OpCodes.Brfalse_S, nextLabel2),  //_fullscreenPaused && Multiplayer.Session == null => can pause, jump to next check
                       new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))),
                       new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MultiplayerSession), nameof(MultiplayerSession.CanPause))),
                       new CodeInstruction(OpCodes.Brfalse_S, skipLabel2)  //_fullscreenPaused && Multiplayer.Session.CanPause == fasle => can't pause, skip
                       )
                   .InstructionEnumeration());
        }
Esempio n. 19
0
        public static IEnumerable <CodeInstruction> AddColors(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldloc_1),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BeltComponent), nameof(BeltComponent.speed))),
                                                new CodeMatch(OpCodes.Ldc_I4_1)
                                                );

            CodeMatcher matcher2 = matcher.Clone();

            matcher2.MatchForward(true,
                                  new CodeMatch(OpCodes.Ldloc_S),
                                  new CodeMatch(OpCodes.Stloc_S));

            object arg = matcher2.Operand;

            matcher2.Advance(1);
            object label = matcher2.Operand;

            matcher.Advance(2)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, arg))
            .SetInstruction(Transpilers.EmitDelegate <Func <int, int, int> >((speed, other) =>
            {
                if (speed <= 1)
                {
                    return(other);
                }

                if (speed <= 2)
                {
                    other += 4;
                }
                else if (speed <= 5)
                {
                    other += 8;
                }
                else if (speed <= 12)
                {
                    other += 12;
                }

                return(other);
            }))
            .Advance(1)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Stloc_S, arg))
            .SetInstruction(new CodeInstruction(OpCodes.Br, label));


            return(matcher.InstructionEnumeration());
        }
Esempio n. 20
0
        public static IEnumerable <CodeInstruction> OnPopulateFamiliars(IEnumerable <CodeInstruction> instructions, ILGenerator il)
        {
            var matcher = new CodeMatcher(instructions, il)
                          .MatchForward(true, new CodeMatch(i => i.opcode == OpCodes.Blt));

            // Patches the loop so it stops after all the vanilla familiars.
            var ret = matcher
                      .Advance(-3)
                      .RemoveInstructions(3)
                      .InsertAndAdvance(new CodeInstruction(OpCodes.Ldc_I4, 13))
                      .InstructionEnumeration();

            return(ret);
        }
Esempio n. 21
0
        static IEnumerable <CodeInstruction> RemoveBrokenConnections(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(true,
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BuildPreview), nameof(BuildPreview.bpgpuiModelId))),
                                                new CodeMatch(OpCodes.Ldc_I4_0)
                                                ).Advance(1);
            Label label = (Label)matcher.Instruction.operand;

            matcher.Advance(-2)
            .InsertAndAdvance(Transpilers.EmitDelegate <Func <BuildPreview, bool> >(bp =>
            {
                if (!isEnabled && !NebulaModAPI.NebulaIsInstalled)
                {
                    return(true);
                }
                if (bp.desc.multiLevel)
                {
                    BuildPreview current = bp;
                    while (current.input != null)
                    {
                        if (!current.input.IsGood())
                        {
                            return(false);
                        }

                        current = current.input;
                    }
                }

                if (bp.desc.isInserter)
                {
                    if (bp.input != null && !bp.input.IsGood())
                    {
                        return(bp.input.desc.isBelt);
                    }

                    if (bp.output != null && !bp.output.IsGood())
                    {
                        return(bp.output.desc.isBelt);
                    }
                }

                return(true);
            }))
            .InsertAndAdvance(new CodeInstruction(OpCodes.Brfalse, label))
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_3));

            return(matcher.InstructionEnumeration());
        }
Esempio n. 22
0
        private static IEnumerable <CodeInstruction> InternalUpdate_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            // Store projectile data after sphere.AddDysonRocket(dysonRocket, autoDysonNode) if IsUpdateNeeded == true
            try
            {
                CodeMatcher matcher = new CodeMatcher(instructions)
                                      .MatchForward(false,
                                                    new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(DysonSphere), nameof(DysonSphere.AddDysonRocket))) //IL#310
                                                    );
                CodeInstruction loadInstruction = matcher.InstructionAt(-1);                                                                                     //autoDysonNode
                matcher.Advance(2)
                .InsertAndAdvance(
                    new CodeInstruction(OpCodes.Ldarg_0),
                    new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SiloComponent), nameof(SiloComponent.planetId))),
                    new CodeInstruction(OpCodes.Ldarg_0),
                    new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SiloComponent), nameof(SiloComponent.localPos))),
                    loadInstruction,
                    HarmonyLib.Transpilers.EmitDelegate <Action <int, Vector3, DysonNode> >((planetId, localPos, autoDysonNode) =>
                {
                    // If the dyson sphere has no subscribers anymore, skip this data
                    if (!Multiplayer.IsActive || !Multiplayer.Session.Launch.Snapshots.ContainsKey(planetId / 100 - 1))
                    {
                        return;
                    }

                    // Assume layerId < 16, nodeId < 4096
                    DysonLaunchData.Projectile data = new DysonLaunchData.Projectile
                    {
                        PlanetId = planetId,
                        TargetId = (ushort)((autoDysonNode.layerId << 12) | (autoDysonNode.id & 0x0FFF)),
                        LocalPos = localPos
                    };
                    Multiplayer.Session.Launch.ProjectileBag.Add(data);
                })
                    );
                return(matcher.InstructionEnumeration());
            }
            catch
            {
                NebulaModel.Logger.Log.Error("SiloComponent.InternalUpdate_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }
        }
Esempio n. 23
0
 static IEnumerable <CodeInstruction> BoneArmor_Import_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iLGenerator)
 {
     try
     {
         var matcher = new CodeMatcher(instructions, iLGenerator)
                       .MatchForward(false, new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(BoneArmor), "SetSize")));
         if (matcher.IsValid)
         {
             //.MatchForward(false, new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryReader), "ReadInt32")))
             matcher.Advance(3)
             .Set(OpCodes.Pop, null);
         }
         return(matcher.InstructionEnumeration());
     }
     catch (Exception ex)
     {
         UnityEngine.Debug.LogError(ex.ToString());
     }
     return(instructions);
 }
            private static IEnumerable <CodeInstruction> PhPluginSceneInfoSaveTranspiler(IEnumerable <CodeInstruction> instructions)
            {
                var matcher = new CodeMatcher(instructions);

                matcher.MatchForward(false, new CodeMatch(OpCodes.Ldstr, "【PHStudio】"));
                var getWriterInstr = matcher.InstructionAt(-1);

                matcher.Advance(2);
                matcher.InsertAndAdvance(
                    new CodeInstruction(OpCodes.Ldarg_0),
                    getWriterInstr,
                    CodeInstruction.Call(typeof(Hooks), nameof(SceneInfoSaveHook)));

                if (matcher.Instruction.opcode != OpCodes.Leave && matcher.Instruction.opcode != OpCodes.Leave_S)
                {
                    throw new Exception("Failed to patch SceneInfo.Save");
                }

                return(matcher.Instructions());
            }
Esempio n. 25
0
        public static IEnumerable <CodeInstruction> PlayerActionMine_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            var codeMatcher = new CodeMatcher(instructions)
                              .MatchForward(true,
                                            new CodeMatch(OpCodes.Ldarg_0),
                                            new CodeMatch(OpCodes.Ldfld),
                                            new CodeMatch(OpCodes.Ldelema),
                                            new CodeMatch(OpCodes.Ldflda),
                                            new CodeMatch(OpCodes.Dup),
                                            new CodeMatch(OpCodes.Ldind_I4),
                                            new CodeMatch(OpCodes.Ldc_I4_1),
                                            new CodeMatch(OpCodes.Sub),
                                            new CodeMatch(OpCodes.Stind_I4));

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("PlayerActionMine_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }

            return(codeMatcher
                   .Advance(1)
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <FetchVeinMineAmount>((PlayerAction_Mine _this) =>
            {
                // do we need to check for the event here? its very unlikely that we call the GameTick() by hand...
                if (SimulatedWorld.Initialized && !PlanetManager.EventFromClient && !PlanetManager.EventFromServer)
                {
                    LocalPlayer.SendPacketToLocalStar(new VegeMinedPacket(_this.player.planetId, _this.miningId, _this.player.factory.veinPool[_this.miningId].amount, true));
                }

                return 0;
            }))
                   .Insert(new CodeInstruction(OpCodes.Pop))
                   .InstructionEnumeration());
        }
        static IEnumerable <CodeInstruction> CreatePrebuilds_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL)
        {
            var codeMatcher = new CodeMatcher(instructions, iL)
                              .MatchForward(true,
                                            new CodeMatch(i => i.opcode == OpCodes.Ldsfld && ((FieldInfo)i.operand).Name == "buildTargetAutoMove")
                                            );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("BuildTool_Click.CreatePrebuilds_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }

            var label = codeMatcher.InstructionAt(1).operand;

            return(codeMatcher
                   .Advance(2)
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
            {
                return SimulatedWorld.Initialized && (FactoryManager.EventFromServer || FactoryManager.EventFromClient) && FactoryManager.PacketAuthor != LocalPlayer.PlayerId;
            }))
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Brtrue, label))
                   .InstructionEnumeration());
        }
Esempio n. 27
0
        private static IEnumerable <CodeInstruction> CreatePrebuilds_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL)
        {
            CodeMatcher codeMatcher = new CodeMatcher(instructions, iL)
                                      .MatchForward(true,
                                                    new CodeMatch(i => i.opcode == OpCodes.Ldsfld && ((FieldInfo)i.operand).Name == "buildTargetAutoMove")
                                                    );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("BuildTool_Click.CreatePrebuilds_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }

            object label = codeMatcher.InstructionAt(1).operand;

            return(codeMatcher
                   .Advance(2)
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
            {
                return Multiplayer.IsActive && Multiplayer.Session.Factories.IsIncomingRequest.Value && Multiplayer.Session.Factories.PacketAuthor != Multiplayer.Session.LocalPlayer.Id;
            }))
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Brtrue, label))
                   .InstructionEnumeration());
        }
        static IEnumerable <CodeInstruction> UpdateTargets_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL)
        {
            /*
             * Update search for new targets. Do not include targets that are already pending response from server.
             * Change:
             *   if (!this.serving.Contains(num4) && (prebuildPool[i].itemRequired == 0 || prebuildPool[i].itemRequired <= this.player.package.GetItemCount((int)prebuildPool[i].protoId)))
             *
             * To:
             *   if (!this.serving.Contains(num4) && !DroneManager.IsPendingBuildRequest(num4) && (prebuildPool[i].itemRequired == 0 || prebuildPool[i].itemRequired <= this.player.package.GetItemCount((int)prebuildPool[i].protoId)))
             */
            var codeMatcher = new CodeMatcher(instructions, iL)
                              .MatchForward(true,
                                            new CodeMatch(i => i.IsLdarg()),
                                            new CodeMatch(i => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "serving"),
                                            new CodeMatch(i => i.IsLdloc()),
                                            new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "Contains"),
                                            new CodeMatch(OpCodes.Brtrue)
                                            );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("MechaDroneLogic_Transpiler.UpdateTargets_Transpiler 1 failed. Mod version not compatible with game version.");
                return(instructions);
            }

            var num4Instruction = codeMatcher.InstructionAt(-2);
            var jumpInstruction = codeMatcher.Instruction;

            codeMatcher = codeMatcher
                          .Advance(1)
                          .InsertAndAdvance(num4Instruction)
                          .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <int, bool> >((num4) =>
            {
                return(DroneManager.IsPendingBuildRequest(num4));
            }))
                          .InsertAndAdvance(jumpInstruction);

            /*
             * Make sure targets are only chosen if player is closest to the build preview
             * Change:
             *  if (a.sqrMagnitude > this.sqrMinBuildAlt && sqrMagnitude <= num2)
             * To:
             *  if (DroneManager.AmIClosestPlayer(ref a) && a.sqrMagnitude > this.sqrMinBuildAlt && sqrMagnitude <= num2)
             */
            codeMatcher = codeMatcher
                          .MatchForward(false,
                                        new CodeMatch(i => i.IsLdloc()),
                                        new CodeMatch(i => i.opcode == OpCodes.Call && ((MethodInfo)i.operand).Name == "get_sqrMagnitude"),
                                        new CodeMatch(OpCodes.Ldarg_0),
                                        new CodeMatch(i => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "sqrMinBuildAlt"),
                                        new CodeMatch(OpCodes.Ble_Un)
                                        );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("MechaDroneLogic_Transpiler.UpdateTargets_Transpiler 2 failed. Mod version not compatible with game version.");
                return(codeMatcher.InstructionEnumeration());
            }

            var aOperand    = codeMatcher.Instruction.operand;
            var jumpOperand = codeMatcher.InstructionAt(4).operand;

            codeMatcher = codeMatcher
                          .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, aOperand))
                          .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <Vector3, bool> >((aVar) =>
            {
                return(DroneManager.AmIClosestPlayer(ref aVar));
            }))
                          .InsertAndAdvance(new CodeInstruction(OpCodes.Brfalse, jumpOperand));

            /*
             * Insert
             *  DroneManager.BroadcastDroneOrder(droneId, entityId, stage);
             * After
             *  this.serving.Add(num3);
             */
            codeMatcher = codeMatcher
                          .MatchForward(true,
                                        new CodeMatch(i => i.IsLdarg()),
                                        new CodeMatch(i => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "serving"),
                                        new CodeMatch(i => i.IsLdloc()),
                                        new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "Add"),
                                        new CodeMatch(OpCodes.Pop)
                                        );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("MechaDroneLogic_Transpiler.UpdateTargets_Transpiler 3 failed. Mod version not compatible with game version.");
                return(codeMatcher.InstructionEnumeration());
            }

            // The index from drones[j]
            var droneIdInstruction = codeMatcher.InstructionAt(-8);

            // num3 from this.serving.Add(num3);
            var entityIdInstruction = codeMatcher.InstructionAt(-2);

            // drones[j].stage = 1;
            var stageInstruction = new CodeInstruction(OpCodes.Ldc_I4_1);

            return(codeMatcher
                   .Advance(1)
                   .InsertAndAdvance(droneIdInstruction)
                   .InsertAndAdvance(entityIdInstruction)
                   .InsertAndAdvance(stageInstruction)
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Action <int, int, int> >((droneId, entityId, stage) =>
            {
                DroneManager.BroadcastDroneOrder(droneId, entityId, stage);
            }))
                   .InstructionEnumeration());
        }
        public static IEnumerable <CodeInstruction> _OnLateUpdate_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(true,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIVirtualStarmap), "starPool")),
                                                new CodeMatch(OpCodes.Ldloc_S),
                                                new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_Item"),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIVirtualStarmap.StarNode), "nameText")),
                                                new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_gameObject"),
                                                new CodeMatch(OpCodes.Ldloc_S),
                                                new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "SetActive"),
                                                new CodeMatch(OpCodes.Ldloc_S));

            if (matcher.IsInvalid)
            {
                Log.Warn("UIVirtualStarmap transpiler could not find injection point, not patching!");
                return(instructions);
            }

            matcher.Advance(1)
            .SetAndAdvance(OpCodes.Ldloc_2, null)     // change 'if (flag2 && flag)' to 'if (flag2 && pressing)'
            .Advance(2);

            // now remove original logic in this if(){}
            for (int i = 0; i < 39; i++)
            {
                matcher.SetAndAdvance(OpCodes.Nop, null);
            }

            // add own logic
            matcher.InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0),
                                     new CodeInstruction(OpCodes.Ldloc_S, 12),
                                     HarmonyLib.Transpilers.EmitDelegate <ShowSolarsystemDetails>((UIVirtualStarmap starmap, int starIndex) =>
            {
                if (pressSpamProtector)
                {
                    return;
                }
                pressSpamProtector = true;

                if (Multiplayer.Session != null && Multiplayer.Session.IsInLobby && starmap.clickText == "")
                {
                    ClearStarmap(starmap);
                    ShowSolarSystem(starmap, starIndex);
                }
                else if (Multiplayer.Session != null && Multiplayer.Session.IsInLobby && starmap.clickText != "")
                {
                    string[] split = starmap.clickText.Split(' ');
                    int starId     = 0;

                    starId = Convert.ToInt32(split[0]);

                    StarData starData = starmap._galaxyData.StarById(starId); // no increment as we stored the actual id in there
                    if (starData == null || starIndex == 0)                   // starIndex == 0 is the star in the middle, so we need to decrement by 1 below
                    {
                        return;
                    }

                    PlanetData pData = starData.planets[starIndex - 1];
                    if (pData == null)
                    {
                        return;
                    }

                    if (UIRoot.instance.uiGame.planetDetail.planet != null && UIRoot.instance.uiGame.planetDetail.planet.id == pData.id && pData.type != EPlanetType.Gas)
                    {
                        // clicked on planet and details already visible, so set as new birth planet
                        starmap._galaxyData.birthStarId   = starId;
                        starmap._galaxyData.birthPlanetId = pData.id;

                        GameMain.data.galaxy.birthStarId   = starId;
                        GameMain.data.galaxy.birthPlanetId = pData.id;

                        customBirthStar   = starData.id;
                        customBirthPlanet = pData.id;

                        Log.Info($"set birth planet{pData.id} {pData.displayName}");
                        Text text = GameObject.Find("UI Root/Overlay Canvas/Galaxy Select/start-button/start-text").GetComponent <Text>();
                        text.text = $"Start Game at {pData.displayName}";
                        text.horizontalOverflow = HorizontalWrapMode.Overflow;

                        if (pData.data == null)
                        {
                            Button button          = GameObject.Find("UI Root/Overlay Canvas/Galaxy Select/start-button").GetComponent <Button>();
                            button.interactable    = false;
                            EPlanetType planetType = pData.type;
                            pData.type             = EPlanetType.Gas;
                            PlanetModelingManager.genPlanetReqList.Enqueue(pData);
                            pData.onLoaded += (PlanetData planet) =>
                            {
                                pData.type          = planetType;
                                button.interactable = true;
                            };
                        }
                    }

                    starmap.clickText = split[0] + " " + starIndex.ToString();
                    UIRoot.instance.uiGame.SetPlanetDetail(pData);

                    GameObject.Find("UI Root/Overlay Canvas/Galaxy Select/right-group")?.SetActive(false);

                    UIRoot.instance.uiGame.planetDetail.gameObject.SetActive(true);
                    UIRoot.instance.uiGame.planetDetail.gameObject.GetComponent <RectTransform>().parent.gameObject.SetActive(true);
                    UIRoot.instance.uiGame.planetDetail.gameObject.GetComponent <RectTransform>().parent.gameObject.GetComponent <RectTransform>().parent.gameObject.SetActive(true);

                    UIRoot.instance.uiGame.planetDetail._OnUpdate();
                }
            }));

            // change for loop to start at 0 instead of 1
            matcher.Start();
            matcher.MatchForward(true,
                                 new CodeMatch(OpCodes.Stloc_2),
                                 new CodeMatch(OpCodes.Ldarg_0),
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIVirtualStarmap), "clickText")),
                                 new CodeMatch(i => i.opcode == OpCodes.Call && ((MethodInfo)i.operand).Name == "IsNullOrEmpty"),
                                 new CodeMatch(OpCodes.Ldc_I4_0),
                                 new CodeMatch(OpCodes.Ceq),
                                 new CodeMatch(OpCodes.Stloc_3)
                                 )
            .Advance(1)
            .SetInstruction(new CodeInstruction(OpCodes.Ldc_I4_0));

            // mark the correct star as birth point
            matcher.Start();
            matcher.MatchForward(true,
                                 new CodeMatch(OpCodes.Ldc_R4),
                                 new CodeMatch(OpCodes.Stloc_1),
                                 new CodeMatch(OpCodes.Br),
                                 new CodeMatch(OpCodes.Ldloc_S),
                                 new CodeMatch(OpCodes.Stloc_1),
                                 new CodeMatch(OpCodes.Ldloc_S),
                                 new CodeMatch(OpCodes.Stloc_0),
                                 new CodeMatch(OpCodes.Ldloc_S),
                                 new CodeMatch(OpCodes.Brtrue)
                                 )
            .Advance(-1)
            .SetAndAdvance(OpCodes.Nop, null)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 5))
            .Insert(HarmonyLib.Transpilers.EmitDelegate <IsBirthStar>((UIVirtualStarmap starmap, int starIndex) =>
            {
                return(starmap.starPool[starIndex].starData.id != starmap._galaxyData.birthStarId && starmap.starPool[starIndex].starData.id != starmap._galaxyData.birthPlanetId);
            }));

            // listen for general mouse clicks to deselect planet / solar system
            matcher.Start();
            matcher.MatchForward(true,
                                 new CodeMatch(OpCodes.Br),
                                 new CodeMatch(OpCodes.Ldarg_0),
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIVirtualStarmap), "starPool")),
                                 new CodeMatch(OpCodes.Ldloc_S),
                                 new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "get_Item"),
                                 new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIVirtualStarmap.StarNode), "active")),
                                 new CodeMatch(OpCodes.Brfalse),
                                 new CodeMatch(OpCodes.Ldloc_S),
                                 new CodeMatch(OpCodes.Ldloc_0),
                                 new CodeMatch(OpCodes.Ceq)
                                 )
            .Advance(3)
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
            .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_0))
            .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <TrackPlayerClick>((UIVirtualStarmap starmap, int starIndex) =>
            {
                bool pressing = VFInput.rtsConfirm.pressing;
                if ((pressing && !pressSpamProtector) && starIndex == -1)
                {
                    if (starmap.clickText != "" && UIRoot.instance.uiGame.planetDetail.gameObject.activeSelf) // hide planet details
                    {
                        GameObject.Find("UI Root/Overlay Canvas/Galaxy Select/right-group").SetActive(true);
                        UIRoot.instance.uiGame.planetDetail.gameObject.SetActive(false);
                    }
                    else if (starmap.clickText != "" && !UIRoot.instance.uiGame.planetDetail.gameObject.activeSelf) // hide solar system details
                    {
                        starmap.clickText = "";
                        starmap.OnGalaxyDataReset();
                    }
                    pressSpamProtector = true;
                }
            }));

            return(matcher.InstructionEnumeration());
        }
Esempio n. 30
0
        private static IEnumerable <CodeInstruction> OnBeltBuilt_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iLGenerator)
        {
            /*
             * Calls
             * Multiplayer.Session.Factories.OnNewSetInserterPickTarget(objId, pickTarget, inserterId, offset, pointPos);
             * After
             * this.factorySystem.SetInserterPickTarget(inserterId, num6, num5 - num7);
             */
            CodeMatcher codeMatcher = new CodeMatcher(instructions, iLGenerator)
                                      .MatchForward(true,
                                                    new CodeMatch(i => i.opcode == OpCodes.Callvirt &&
                                                                  ((MethodInfo)i.operand).Name == nameof(FactorySystem.SetInserterPickTarget)
                                                                  )
                                                    );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("PlanetFactory_Transpiler.OnBeltBuilt 1 failed. Mod version not compatible with game version.");
                return(instructions);
            }

            List <CodeInstruction> setInserterTargetInsts = codeMatcher.InstructionsWithOffsets(-5, -1); // inserterId, pickTarget, offset
            CodeInstruction        objIdInst     = codeMatcher.InstructionAt(-13);                       // objId
            List <CodeInstruction> pointPosInsts = codeMatcher.InstructionsWithOffsets(8, 10);           // pointPos

            codeMatcher = codeMatcher
                          .Advance(1)
                          .InsertAndAdvance(setInserterTargetInsts.ToArray())
                          .InsertAndAdvance(objIdInst)
                          .InsertAndAdvance(pointPosInsts.ToArray())
                          .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Action <int, int, int, int, UnityEngine.Vector3> >((inserterId, pickTarget, offset, objId, pointPos) =>
            {
                if (Multiplayer.IsActive)
                {
                    Multiplayer.Session.Factories.OnNewSetInserterPickTarget(objId, pickTarget, inserterId, offset, pointPos);
                }
            }));

            /*
             * Calls
             * Multiplayer.Session.Factories.OnNewSetInserterInsertTarget(objId, pickTarget, inserterId, offset, pointPos);
             * After
             * this.factorySystem.SetInserterInsertTarget(inserterId, num9, num5 - num10);
             */
            codeMatcher = codeMatcher
                          .MatchForward(true,
                                        new CodeMatch(i => i.opcode == OpCodes.Callvirt &&
                                                      ((MethodInfo)i.operand).Name == nameof(FactorySystem.SetInserterInsertTarget)
                                                      )
                                        );

            if (codeMatcher.IsInvalid)
            {
                NebulaModel.Logger.Log.Error("PlanetFactory_Transpiler.OnBeltBuilt 2 failed. Mod version not compatible with game version.");
                return(codeMatcher.InstructionEnumeration());
            }

            setInserterTargetInsts = codeMatcher.InstructionsWithOffsets(-5, -1); // inserterId, pickTarget, offset
            objIdInst     = codeMatcher.InstructionAt(-13);                       // objId
            pointPosInsts = codeMatcher.InstructionsWithOffsets(9, 11);           // pointPos

            codeMatcher = codeMatcher
                          .Advance(1)
                          .InsertAndAdvance(setInserterTargetInsts.ToArray())
                          .InsertAndAdvance(objIdInst)
                          .InsertAndAdvance(pointPosInsts.ToArray())
                          .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Action <int, int, int, int, UnityEngine.Vector3> >((inserterId, pickTarget, offset, objId, pointPos) =>
            {
                if (Multiplayer.IsActive)
                {
                    Multiplayer.Session.Factories.OnNewSetInserterInsertTarget(objId, pickTarget, inserterId, offset, pointPos);
                }
            }));

            return(codeMatcher.InstructionEnumeration());
        }