Пример #1
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());
        }
Пример #2
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator il)
        {
            var matcher = new CodeMatcher(instructions, il);

            // Search for the first 4 consecative Ldc_I4 instructions (a Color constructor after if statements which move the trash can in other conditions)
            matcher.MatchForward(false, new CodeMatch(OpCodes.Ldc_I4, 150), new CodeMatch(OpCodes.Ldc_I4, 150), new CodeMatch(OpCodes.Ldc_I4, 150), new CodeMatch(OpCodes.Ldc_I4, 150), new CodeMatch(OpCodes.Newobj));

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

            Label bailOut;

            matcher.CreateLabelAt(matcher.Pos, out bailOut);

            var trashOffsetCode = new CodeInstruction[]
            {
                new CodeInstruction(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.playerInventory))),
                new CodeInstruction(OpCodes.Brfalse_S, bailOut),

                new CodeInstruction(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.player))),
                new CodeInstruction(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.myPlayer))),
                new CodeInstruction(OpCodes.Ldelem_Ref),

                new CodeInstruction(OpCodes.Callvirt, typeof(Player).GetMethod("GetModPlayer", new Type[] { }).MakeGenericMethod(typeof(StoragePlayer))),
                new CodeInstruction(OpCodes.Ldfld, typeof(StoragePlayer).GetField(nameof(StoragePlayer.StorageAccess))),
                new CodeInstruction(OpCodes.Ldfld, typeof(Point16).GetField(nameof(Point16.X))),
                new CodeInstruction(OpCodes.Ldc_I4_0),
                new CodeInstruction(OpCodes.Blt_S, bailOut),

                new CodeInstruction(OpCodes.Ldloc_0),
                new CodeInstruction(OpCodes.Ldsflda, typeof(UI).GetField(nameof(UI.TrashSlotOffset))),
                new CodeInstruction(OpCodes.Ldfld, typeof(Point16).GetField(nameof(Point16.X))),
                new CodeInstruction(OpCodes.Add),
                new CodeInstruction(OpCodes.Stloc_0),

                new CodeInstruction(OpCodes.Ldloc_1),
                new CodeInstruction(OpCodes.Ldsflda, typeof(UI).GetField(nameof(UI.TrashSlotOffset))),
                new CodeInstruction(OpCodes.Ldfld, typeof(Point16).GetField(nameof(Point16.Y))),
                new CodeInstruction(OpCodes.Add),
                new CodeInstruction(OpCodes.Stloc_1),

                new CodeInstruction(OpCodes.Ldc_R4, 0.755f),
                new CodeInstruction(OpCodes.Stsfld, typeof(Main).GetField(nameof(Main.inventoryScale)))
            };

            matcher.InsertAndAdvance(trashOffsetCode);

            matcher.Advance(1);
            matcher.InsertAndAdvance(new CodeInstruction(OpCodes.Ldc_I4, 150));

            matcher.MatchForward(true, new CodeMatch(OpCodes.Call, typeof(ChestUI).GetMethod("Draw", new Type[] { typeof(Microsoft.Xna.Framework.Graphics.SpriteBatch) })));
            matcher.MatchForward(true, new CodeMatch(OpCodes.Ldsfld), new CodeMatch(OpCodes.Ldsfld), new CodeMatch(OpCodes.Ldelem_Ref), new CodeMatch(OpCodes.Ldfld), new CodeMatch(OpCodes.Ldc_I4_M1), new CodeMatch(OpCodes.Bne_Un), new CodeMatch(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.npcShop))), new CodeMatch(OpCodes.Brtrue));

            var iconsLabel = matcher.Instruction.operand;

            matcher.Advance(1);

            var icon1Code = new CodeInstruction[]
            {
                new CodeInstruction(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.player))),
                new CodeInstruction(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.myPlayer))),
                new CodeInstruction(OpCodes.Ldelem_Ref),

                new CodeInstruction(OpCodes.Callvirt, typeof(Player).GetMethod("GetModPlayer", new Type[] { }).MakeGenericMethod(typeof(StoragePlayer))),
                new CodeInstruction(OpCodes.Ldfld, typeof(StoragePlayer).GetField(nameof(StoragePlayer.StorageAccess))),
                new CodeInstruction(OpCodes.Ldfld, typeof(Point16).GetField(nameof(Point16.X))),

                new CodeInstruction(OpCodes.Ldc_I4_0),
                new CodeInstruction(OpCodes.Bgt, iconsLabel)
            };

            matcher.InsertAndAdvance(icon1Code);

            matcher.MatchForward(true, new CodeMatch(OpCodes.Callvirt, typeof(Player).GetMethod("QuickStackAllChests")));
            var quickStackCode = new CodeInstruction[]
            {
                new CodeInstruction(OpCodes.Ldc_I4_0),
                new CodeInstruction(OpCodes.Call, typeof(StorageUI).GetMethod("TryQuickStack", new Type[] { typeof(bool) })),
                new CodeInstruction(OpCodes.Pop)
            };

            matcher.InsertAndAdvance(quickStackCode);

            matcher.MatchForward(true, new CodeMatch(OpCodes.Ldsfld), new CodeMatch(OpCodes.Ldsfld), new CodeMatch(OpCodes.Ldelem_Ref), new CodeMatch(OpCodes.Ldfld), new CodeMatch(OpCodes.Ldc_I4_M1), new CodeMatch(OpCodes.Bne_Un), new CodeMatch(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.npcShop))), new CodeMatch(OpCodes.Brtrue));

            iconsLabel = matcher.Instruction.operand;
            matcher.Advance(1);

            var icon2Code = new CodeInstruction[]
            {
                new CodeInstruction(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.player))),
                new CodeInstruction(OpCodes.Ldsfld, typeof(Main).GetField(nameof(Main.myPlayer))),
                new CodeInstruction(OpCodes.Ldelem_Ref),

                new CodeInstruction(OpCodes.Callvirt, typeof(Player).GetMethod("GetModPlayer", new Type[] { }).MakeGenericMethod(typeof(StoragePlayer))),
                new CodeInstruction(OpCodes.Ldfld, typeof(StoragePlayer).GetField(nameof(StoragePlayer.StorageAccess))),
                new CodeInstruction(OpCodes.Ldfld, typeof(Point16).GetField(nameof(Point16.X))),

                new CodeInstruction(OpCodes.Ldc_I4_0),
                new CodeInstruction(OpCodes.Bgt, iconsLabel)
            };

            matcher.InsertAndAdvance(icon2Code);

            return(matcher.InstructionEnumeration());
        }
Пример #3
0
        public static void ILSUpdateShipPos(StationComponent stationComponent, PlanetFactory factory, int timeGene, double dt, float shipSailSpeed, float shipWarpSpeed, int shipCarries, StationComponent[] gStationPool, AstroPose[] astroPoses, VectorLF3 relativePos, Quaternion relativeRot, bool starmap, int[] consumeRegister)
        {
            IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator il)
            {
                // find begin of ship movement computation, c# 460 IL 2090
                CodeMatcher matcher    = new CodeMatcher(instructions, il);
                int         indexStart = matcher
                                         .MatchForward(false,
                                                       new CodeMatch(i => i.IsLdarg()),
                                                       new CodeMatch(OpCodes.Ldc_R4),
                                                       new CodeMatch(OpCodes.Div),
                                                       new CodeMatch(i => i.opcode == OpCodes.Call && ((MethodInfo)i.operand).Name == "Sqrt"),
                                                       new CodeMatch(OpCodes.Stloc_S),
                                                       new CodeMatch(OpCodes.Ldloc_S),
                                                       new CodeMatch(OpCodes.Stloc_S),
                                                       new CodeMatch(OpCodes.Ldloc_S),
                                                       new CodeMatch(OpCodes.Ldc_R4),
                                                       new CodeMatch(OpCodes.Ble_Un))
                                         .Pos;

                // cut out only that part of original function, but keep the first 5 IL lines (they create the 'bool flag' which is needed)
                for (matcher.Start().Advance(6); matcher.Pos < indexStart;)
                {
                    matcher.SetAndAdvance(OpCodes.Nop, null);
                }

                // add null check at the beginning of the while(){} for gStationPool[shipData.otherGId] and if it is null skip this shipData until all data received from server
                matcher
                .MatchForward(true,
                              new CodeMatch(OpCodes.Br),
                              new CodeMatch(OpCodes.Ldarg_0),
                              new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(StationComponent), "workShipDatas")),
                              new CodeMatch(OpCodes.Ldloc_S),
                              new CodeMatch(OpCodes.Ldelem, typeof(ShipData)),
                              new CodeMatch(OpCodes.Stloc_S));
                object jmpNextLoopIter = matcher.InstructionAt(-5).operand;

                matcher.CreateLabelAt(matcher.Pos + 1, out Label jmpNormalFlow);
                matcher
                .Advance(1)
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_S, 7))     // gStationPool
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 60))    // shipData
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ShipData), "otherGId")))
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldelem, typeof(StationComponent)))
                .InsertAndAdvance(new CodeInstruction(OpCodes.Brtrue, jmpNormalFlow))
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 59))     // j
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldc_I4_1))
                .InsertAndAdvance(new CodeInstruction(OpCodes.Add))
                .InsertAndAdvance(new CodeInstruction(OpCodes.Stloc_S, 59))
                .InsertAndAdvance(new CodeInstruction(OpCodes.Br, jmpNextLoopIter));

                // remove c# 502-525 (adding item from landing ship to station and modify remote order and shifitng those arrays AND j-- (as we end up in an endless loop if not))
                indexStart = matcher
                             .MatchForward(false,
                                           new CodeMatch(OpCodes.Ldarg_0),
                                           new CodeMatch(OpCodes.Ldloc_S),
                                           new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(ShipData), "itemId")),
                                           new CodeMatch(OpCodes.Ldloc_S),
                                           new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(ShipData), "itemCount")),
                                           new CodeMatch(OpCodes.Ldloc_S),
                                           new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(ShipData), "inc")),
                                           new CodeMatch(i => i.opcode == OpCodes.Call && ((MethodInfo)i.operand).Name == "AddItem"))
                             .Pos;
                int indexEnd = matcher
                               .MatchForward(true,
                                             new CodeMatch(OpCodes.Sub),
                                             new CodeMatch(i => i.opcode == OpCodes.Call && ((MethodInfo)i.operand).Name == "Clear"),
                                             new CodeMatch(OpCodes.Ldloc_S),
                                             new CodeMatch(OpCodes.Ldc_I4_1),
                                             new CodeMatch(OpCodes.Sub),
                                             new CodeMatch(OpCodes.Stloc_S))
                               .Advance(1)
                               .Pos;

                for (matcher.Start().Advance(indexStart); matcher.Pos < indexEnd;)
                {
                    matcher.SetAndAdvance(OpCodes.Nop, null);
                }

                // c# 621 remove warp state entering as we do this triggered by host. client always messed up here for whatever reason so just tell him what to do.
                matcher
                .MatchForward(false,
                              new CodeMatch(OpCodes.Ldloca_S),
                              new CodeMatch(OpCodes.Ldflda, AccessTools.Field(typeof(ShipData), "warperCnt")),
                              new CodeMatch(OpCodes.Dup),
                              new CodeMatch(OpCodes.Ldind_I4),
                              new CodeMatch(OpCodes.Ldc_I4_1),
                              new CodeMatch(OpCodes.Sub),
                              new CodeMatch(OpCodes.Stind_I4),
                              new CodeMatch(OpCodes.Ldloca_S),
                              new CodeMatch(OpCodes.Ldflda, AccessTools.Field(typeof(ShipData), "warpState")));
                for (int i = 0; i < 15; i++)
                {
                    matcher.SetAndAdvance(OpCodes.Nop, null);
                }

                // remove c# 956 - 1054 (adding item from landing ship to station and modify remote order)
                indexStart = matcher
                             .MatchForward(false,
                                           new CodeMatch(OpCodes.Ldarg_S),
                                           new CodeMatch(OpCodes.Ldloc_S),
                                           new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(ShipData), "otherGId")),
                                           new CodeMatch(OpCodes.Ldelem_Ref),
                                           new CodeMatch(OpCodes.Stloc_S),
                                           new CodeMatch(OpCodes.Ldloc_S),
                                           new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(StationComponent), "storage")),
                                           new CodeMatch(OpCodes.Stloc_S),
                                           new CodeMatch(OpCodes.Ldarg_S),
                                           new CodeMatch(OpCodes.Ldloc_S),
                                           new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(ShipData), "planetA")))
                             .Pos;
                indexEnd = matcher
                           .MatchForward(true,
                                         new CodeMatch(OpCodes.Ldarg_0),
                                         new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(StationComponent), "remotePairCount")),
                                         new CodeMatch(OpCodes.Rem),
                                         new CodeMatch(OpCodes.Stloc_S),
                                         new CodeMatch(OpCodes.Ldloc_S),
                                         new CodeMatch(OpCodes.Ldloc_S),
                                         new CodeMatch(OpCodes.Bne_Un))
                           .Pos;
                for (matcher.Start().Advance(indexStart); matcher.Pos <= indexEnd;)
                {
                    matcher.SetAndAdvance(OpCodes.Nop, null);
                }

                // remove c# 1058 - 1093 (taking item from station and modify remote order)
                indexStart = matcher
                             .MatchForward(false,
                                           new CodeMatch(OpCodes.Ldloc_S),
                                           new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(ShipData), "itemId")),
                                           new CodeMatch(OpCodes.Stloc_S),
                                           new CodeMatch(OpCodes.Ldarg_S),
                                           new CodeMatch(OpCodes.Stloc_S),
                                           new CodeMatch(OpCodes.Ldloc_S),
                                           new CodeMatch(OpCodes.Ldloca_S),
                                           new CodeMatch(OpCodes.Ldloca_S),
                                           new CodeMatch(OpCodes.Ldloca_S),
                                           new CodeMatch(i => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "TakeItem"))
                             .Pos;
                indexEnd = matcher
                           .MatchForward(true,
                                         new CodeMatch(OpCodes.Stind_I4),
                                         new CodeMatch(OpCodes.Leave),
                                         new CodeMatch(OpCodes.Ldloc_S),
                                         new CodeMatch(OpCodes.Brfalse),
                                         new CodeMatch(OpCodes.Ldloc_S),
                                         new CodeMatch(OpCodes.Call),
                                         new CodeMatch(OpCodes.Endfinally))
                           .Pos;
                for (matcher.Start().Advance(indexStart); matcher.Pos <= indexEnd;)
                {
                    matcher.SetAndAdvance(OpCodes.Nop, null);
                }

                return(matcher.InstructionEnumeration());
            }

            _ = Transpiler(null, null);
        }