예제 #1
0
 static IEnumerable <CodeInstruction> SaveCurrentGame_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iLGenerator)
 {
     /* BinaryWriter binaryWriter = new BinaryWriter(fileStream); => Create lzstream and replace binaryWriter.
      * set PerformanceMonitor.BeginStream to lzstream.
      * fileStream.Seek(6L, SeekOrigin.Begin); binaryWriter.Write(position); => Disable seek&write function.
      * binaryWriter.Dispose(); => Dispose lzstream before fileStream close.
      */
     try
     {
         var matcher = new CodeMatcher(instructions, iLGenerator)
                       .MatchForward(false, new CodeMatch(OpCodes.Newobj, AccessTools.Constructor(typeof(BinaryWriter), new Type[] { typeof(FileStream) })))
                       .Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "CreateBinaryWriter"))
                       .MatchForward(false, new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(PerformanceMonitor), "BeginStream")))
                       .Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "MonitorStream"))
                       .MatchForward(false, new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IO.Stream), "Seek")))
                       .Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "FileLengthWrite0"))
                       .MatchForward(false, new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryWriter), "Write", new Type[] { typeof(long) })))
                       .Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "FileLengthWrite1"))
                       .MatchForward(false, new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IDisposable), "Dispose")))
                       .Advance(1)
                       .Insert(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "DisposeLzstream")));
         EnableCompress = true;
         return(matcher.InstructionEnumeration());
     }
     catch (Exception ex)
     {
         SaveUtil.logger.LogError("SaveCurrentGame_Transpiler failed. Mod version not compatible with game version.");
         SaveUtil.logger.LogError(ex);
     }
     return(instructions);
 }
예제 #2
0
        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());
        }
예제 #3
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());
        }
예제 #4
0
        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());
        }
예제 #5
0
        public static IEnumerable <CodeInstruction> AllowBuildingWithLockedRecipes(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldarg_1),
                                                new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(GameHistoryData), nameof(GameHistoryData.RecipeUnlocked)))
                                                )
                                  .Repeat(codeMatcher =>
            {
                codeMatcher.Advance(-1).SetOpcodeAndAdvance(OpCodes.Nop)
                .SetOpcodeAndAdvance(OpCodes.Nop)
                .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Ldc_I4_1));
            });

            matcher.Start().MatchForward(false,
                                         new CodeMatch(OpCodes.Ldarg_3),
                                         new CodeMatch(OpCodes.Ldc_I4_0),
                                         new CodeMatch(OpCodes.Ldelem_I4),
                                         new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(GameHistoryData), nameof(GameHistoryData.ItemUnlocked)))
                                         )
            .Advance(-1).SetOpcodeAndAdvance(OpCodes.Nop)
            .SetOpcodeAndAdvance(OpCodes.Nop)
            .SetOpcodeAndAdvance(OpCodes.Nop)
            .SetOpcodeAndAdvance(OpCodes.Nop)
            .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Ldc_I4_1));

            return(matcher.InstructionEnumeration());
        }
예제 #6
0
    internal static CodeMatcher Print(this CodeMatcher codeMatcher, int before, int after)
    {
#if DEBUG
        for (int i = -before; i <= after; ++i)
        {
            int currentOffset = i;
            int index         = codeMatcher.Pos + currentOffset;

            if (index <= 0)
            {
                continue;
            }

            if (index >= codeMatcher.Length)
            {
                break;
            }

            try
            {
                var line = codeMatcher.InstructionAt(currentOffset);
                Log.LogTrace($"[{currentOffset}] " + line.ToString());
            }
            catch (Exception e)
            {
                Log.LogError(e.Message);
            }
        }
#endif
        return(codeMatcher);
    }
예제 #7
0
        static IEnumerable <CodeInstruction> Transpiler1(IEnumerable <CodeInstruction> instructions)
        {
            var custominstruc = new CodeMatcher(instructions)
                                .MatchForward(false,
                                              new CodeMatch(OpCodes.Ldarg_0),
                                              new CodeMatch(OpCodes.Ldarg_0),
                                              new CodeMatch(l => l.opcode == OpCodes.Call && l.Calls(AccessTools.Method(typeof(SceneEdit), "InitMenuNative"))))
                                .SetAndAdvance(OpCodes.Nop, null)
                                .SetAndAdvance(OpCodes.Nop, null)
                                .SetAndAdvance(OpCodes.Nop, null)
                                .SetAndAdvance(OpCodes.Nop, null)
                                .SetAndAdvance(OpCodes.Nop, null)
                                .Insert(
                new CodeInstruction(OpCodes.Ldarg_0),
                Transpilers.EmitDelegate <Action>(() =>
            {
                Debug.Log("Calling your control test coroutine.");
                @this2.StartCoroutine(InitMenuNative());
            }),
                new CodeInstruction(OpCodes.Pop)
                )
                                .InstructionEnumeration();

            return(custominstruc);
        }
예제 #8
0
        static IEnumerable <CodeInstruction> CreatePrebuilds_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator il)
        {
            CodeMatcher matcher = new CodeMatcher(instructions, il)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(i => i.opcode == OpCodes.Call && ((MethodInfo)i.operand).Name == "get_controller"),
                                                new CodeMatch(OpCodes.Ldflda, AccessTools.Field(typeof(PlayerController), "cmd")),
                                                new CodeMatch(OpCodes.Ldc_I4_1),
                                                new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(CommandState), "stage")));

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

            return(matcher
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
            {
                return SimulatedWorld.Initialized && (FactoryManager.EventFromServer || FactoryManager.EventFromClient) && FactoryManager.PacketAuthor != LocalPlayer.PlayerId;
            }))
                   .CreateLabelAt(matcher.Pos + 19, out Label jmpLabel)
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Brtrue, jmpLabel))
                   .InstructionEnumeration());
        }
예제 #9
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.Call, AccessTools.PropertyGetter(typeof(BuildTool), nameof(BuildTool.buildPreviews))),
                                                   new CodeMatch(OpCodes.Callvirt))
                                  .Advance(1)
                                  .InsertAndAdvance(Transpilers.EmitDelegate <Action <BuildTool_Inserter> >(tool =>
            {
                if (UndoManager.IgnoreAllEvents.Value)
                {
                    return;
                }
                if (NebulaModAPI.IsMultiplayerActive)
                {
                    if (NebulaModAPI.MultiplayerSession.LocalPlayer.IsClient)
                    {
                        return;
                    }
                }

                IEnumerable <int> objectIds = tool.buildPreviews.Select(preview => preview.objId);

                PlayerUndo data = UndoManager.GetCurrentPlayerData();
                data.AddUndoItem(new UndoBuild(data, objectIds));
            }))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0));

            return(matcher.InstructionEnumeration());
        }
        private static IEnumerable <CodeInstruction> Transpiler1(IEnumerable <CodeInstruction> instructions)
        {
            IEnumerable <CodeInstruction> custominstruc = new CodeMatcher(instructions)
                                                          .MatchForward(false,
                                                                        new CodeMatch(OpCodes.Ldarg_0),
                                                                        new CodeMatch(OpCodes.Ldarg_0),
                                                                        new CodeMatch(l => l.opcode == OpCodes.Call && l.Calls(AccessTools.Method(typeof(SceneEdit), "InitMenuNative"))))
                                                          .SetAndAdvance(OpCodes.Nop, null)
                                                          .SetAndAdvance(OpCodes.Nop, null)
                                                          .SetAndAdvance(OpCodes.Nop, null)
                                                          .SetAndAdvance(OpCodes.Nop, null)
                                                          .SetAndAdvance(OpCodes.Nop, null)
                                                          .Insert(
                new CodeInstruction(OpCodes.Ldarg_0),
                new CodeInstruction(OpCodes.Ldarg_0),
                Transpilers.EmitDelegate <Action <SceneEdit> >((lthis) =>
            {
                @this = lthis;

                Main.logger.LogDebug("Calling your modified CoRoutine");
                @this.StartCoroutine(InitMenuNative());
            }),
                new CodeInstruction(OpCodes.Pop)
                )
                                                          .InstructionEnumeration();

            return(custominstruc);
        }
 private static IEnumerable <CodeInstruction> _OnUpdate_Transpiler(IEnumerable <CodeInstruction> instructions)
 {
     // Replace: if (cargoPath.TryInsertItem(Mathf.Max(4, beltComponent.segIndex + beltComponent.segPivotOffset - 20), this.player.inhandItemId, 1, (byte)num))
     // To:      if (this.traffic.PutItemOnBelt(spraycoaterComponent.cargoBeltId, this.player.inhandItemId, (byte)num))
     try
     {
         CodeMatcher matcher = new CodeMatcher(instructions)
                               .MatchForward(false,
                                             new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(CargoPath), nameof(CargoPath.TryInsertItem))))
                               .InsertAndAdvance(
             new CodeInstruction(OpCodes.Ldarg_0),
             HarmonyLib.Transpilers.EmitDelegate <Func <byte, UISpraycoaterWindow, bool> >((foo, window) =>
         {
             // Recalculate itemInc here because the argument is not reliable
             int itemInc     = (window.player.inhandItemInc > 0) ? (window.player.inhandItemInc / window.player.inhandItemCount) : 0;
             itemInc         = ((itemInc > 10) ? 10 : itemInc);
             int itemId      = window.player.inhandItemId;
             int cargoBeltId = window.traffic.spraycoaterPool[window.spraycoaterId].cargoBeltId;
             return(window.traffic.PutItemOnBelt(cargoBeltId, itemId, (byte)itemInc));
         }))
                               .RemoveInstruction()
                               .Advance(-17)
                               .RemoveInstructions(14); // remove #81~94, leave only (byte)num
         return(matcher.InstructionEnumeration());
     }
     catch
     {
         NebulaModel.Logger.Log.Error("UISpraycoaterWindow._OnUpdate_Transpiler failed. Mod version not compatible with game version.");
         return(instructions);
     }
 }
예제 #12
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());
        }
예제 #13
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());
            }
예제 #14
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());
        }
예제 #15
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());
        }
예제 #16
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());
        }
예제 #17
0
        public static IEnumerable <CodeInstruction> CargoContainer_Expand2x_Patch(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(true,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldloc_0),
                                                new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(CargoContainer), nameof(CargoContainer.poolCapacity)))
                                                )
                                  .Advance(1)
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
                                  .InsertAndAdvance(Transpilers.EmitDelegate <Action <CargoContainer> >((CargoContainer __instance) =>
            {
                if (executeNow)
                {
                    UpdateCargoBuffer(__instance);
                }
                else
                {
                    expandedCargos.Add(__instance);
                }
            }))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ret));

            return(matcher.InstructionEnumeration());
        }
예제 #18
0
        public static IEnumerable <CodeInstruction> ChangeFunction(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .End()
                                  .MatchBack(false,
                                             new CodeMatch(OpCodes.Ldloc_S),
                                             new CodeMatch(OpCodes.Ldc_I4_1),
                                             new CodeMatch(OpCodes.Add)
                                             )
                                  .Advance(1)
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactoryStorage), nameof(FactoryStorage.tankPool))))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 4))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldelema, typeof(TankComponent)))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_0))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 5))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldelema, typeof(AnimData)))
                                  .InsertAndAdvance(Transpilers.EmitDelegate <RefAction <TankComponent, AnimData> >((ref TankComponent tank, ref AnimData anim) =>
            {
                if (tank.fluidCapacity > 11000)
                {
                    anim.time = InverseFunction(anim.time);
                }
            }));


            return(matcher.InstructionEnumeration());
        }
예제 #19
0
 public static IEnumerable <CodeInstruction> SetFilterToEntity_Transpiler(IEnumerable <CodeInstruction> instructions)
 {
     instructions = new CodeMatcher(instructions)
                    .MatchForward(true,
                                  new CodeMatch(OpCodes.Ldloc_2),
                                  new CodeMatch(OpCodes.Ldfld),
                                  new CodeMatch(OpCodes.Ldarg_0),
                                  new CodeMatch(OpCodes.Ldfld),
                                  new CodeMatch(OpCodes.Ldelema),
                                  new CodeMatch(OpCodes.Ldarg_0),
                                  new CodeMatch(OpCodes.Ldfld),
                                  new CodeMatch(OpCodes.Stfld))
                    .Advance(1)
                    .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_2),
                                      new CodeInstruction(OpCodes.Ldarg_0),
                                      new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UISlotPicker), "outputSlotId")),
                                      new CodeInstruction(OpCodes.Ldarg_0),
                                      new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UISlotPicker), "selectedIndex")))
                    .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <SetSlot>((StationComponent stationComponent, int outputSlotId, int selectedIndex) =>
     {
         if (!SimulatedWorld.Initialized)
         {
             return(0);
         }
         LocalPlayer.SendPacketToLocalStar(new ILSUpdateSlotData(stationComponent.planetId, stationComponent.id, stationComponent.gid, outputSlotId, selectedIndex));
         return(0);
     }))
                    .Insert(new CodeInstruction(OpCodes.Pop))
                    .InstructionEnumeration();
     return(instructions);
 }
예제 #20
0
        private static IEnumerable <CodeInstruction> CreatePrebuilds_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator il)
        {
            CodeMatcher matcher = new CodeMatcher(instructions, il)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(i => i.opcode == OpCodes.Call && ((MethodInfo)i.operand).Name == "get_controller"),
                                                new CodeMatch(OpCodes.Ldflda, AccessTools.Field(typeof(PlayerController), nameof(PlayerController.cmd))),
                                                new CodeMatch(OpCodes.Ldc_I4_1),
                                                new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(CommandState), nameof(CommandState.stage))));

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

            return(matcher
                   .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
            {
                return Multiplayer.IsActive && Multiplayer.Session.Factories.IsIncomingRequest.Value && Multiplayer.Session.Factories.PacketAuthor != Multiplayer.Session.LocalPlayer.Id;
            }))
                   .CreateLabelAt(matcher.Pos + 19 + 22, out Label jmpLabel)
                   .InsertAndAdvance(new CodeInstruction(OpCodes.Brtrue, jmpLabel))
                   .InstructionEnumeration());
        }
예제 #21
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());
        }
예제 #22
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);
        }
예제 #23
0
        private static IEnumerable <CodeInstruction> IsPlanetPhysicsColliderDirty_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator il)
        {
            CodeMatcher codeMatcher = new CodeMatcher(instructions, il)
                                      .MatchForward(false,
                                                    new CodeMatch(OpCodes.Ldarg_0),
                                                    new CodeMatch(i => i.opcode == OpCodes.Ldfld && i.operand?.ToString() == "PlanetData planet"),
                                                    new CodeMatch(i => i.opcode == OpCodes.Ldfld && i.operand?.ToString() == "PlanetPhysics physics"),
                                                    new CodeMatch(OpCodes.Ldc_I4_1),
                                                    new CodeMatch(i => i.opcode == OpCodes.Stfld && i.operand?.ToString() == "System.Boolean isPlanetPhysicsColliderDirty"));

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

            return(codeMatcher
                   .Repeat(matcher =>
            {
                matcher
                .CreateLabelAt(matcher.Pos + 5, out Label end)
                .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Func <bool> >(() =>
                {
                    return Multiplayer.IsActive && Multiplayer.Session.Factories.IsIncomingRequest.Value;
                }))
                .Insert(new CodeInstruction(OpCodes.Brtrue, end))
                .Advance(5);
            })
                   .InstructionEnumeration());
        }
예제 #24
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);
     }
 }
예제 #25
0
        static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldc_R4),
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld),
                                                new CodeMatch(i =>
                                                              i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "GetVeinsInAreaNonAlloc"))
                                  .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Ldloc_3))
                                  .InsertAndAdvance(
                Transpilers.EmitDelegate <Func <BuildPreview, float> >(preview => DSPAdvancedMiner.getMinerRadius(preview.desc) + 4)
                ).MatchForward(true,
                               new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(Vector3), nameof(Vector3.Dot))),
                               new CodeMatch(OpCodes.Stloc_S),
                               new CodeMatch(OpCodes.Ldloc_S),
                               new CodeMatch(OpCodes.Ldc_R4))
                                  .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Ldloc_3))
                                  .InsertAndAdvance(
                Transpilers.EmitDelegate <Func <BuildPreview, float> >(preview =>
            {
                float radius = DSPAdvancedMiner.getMinerRadius(preview.desc);
                return(radius * radius);
            })
                );

            return(matcher.InstructionEnumeration());
        }
예제 #26
0
        public static IEnumerable <CodeInstruction> ClickReform(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(true,
                                                new CodeMatch(x => x.IsLdloc()),
                                                new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(BuildTool_Reform), nameof(BuildTool_Click.castGroundPos)))
                                                )
                                  .Advance(1)
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
                                  .InsertAndAdvance(Transpilers.EmitDelegate <Action <BuildTool_Reform> >(tool =>
            {
                currentGridData.snapGrid = new Vector2(tool.brushSize, tool.brushSize);

                float longitude = 0;
                float latitude  = 0;
                BlueprintUtils.GetLongitudeLatitudeRad(tool.castGroundPos.normalized, ref longitude, ref latitude);

                if (isLockedLongitude)
                {
                    longitude = lockLongitude;
                }
                if (isLockedLatitude)
                {
                    latitude = lockLatitude;
                }

                tool.castGroundPos = BlueprintUtils.GetDir(longitude, latitude) * tool.castGroundPos.magnitude;
            }));

            return(matcher.InstructionEnumeration());
        }
예제 #27
0
        static IEnumerable <CodeInstruction> DysonSphereSegmentRenderer_DrawModels_Patch(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(true,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSphereSegmentRenderer), nameof(DysonSphereSegmentRenderer.dysonSphere))),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSphere), nameof(DysonSphere.layersIdBased)))
                                                )
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSphereSegmentRenderer), nameof(DysonSphereSegmentRenderer.dysonSphere))),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSphere), nameof(DysonSphere.layersIdBased)))
                                                )
                                  .SetOpcodeAndAdvance(OpCodes.Nop)
                                  .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Nop))
                                  .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Nop))
                                  .Advance(1)
                                  .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
                                  .SetInstructionAndAdvance(Transpilers.EmitDelegate <Func <uint, DysonSphereSegmentRenderer, DysonSphereLayer> >((uint index, DysonSphereSegmentRenderer renderer) =>
            {
                if (hideDysonSphereMesh.Value && DysonSphere.renderPlace == ERenderPlace.Universe)
                {
                    return(null);
                }

                return(renderer.dysonSphere.layersIdBased[(int)((UIntPtr)index)]);
            }));

            return(matcher.InstructionEnumeration());
        }
예제 #28
0
        static IEnumerable <CodeInstruction> Transpiler1(IEnumerable <CodeInstruction> instructions)
        {
            var custominstruc = new CodeMatcher(instructions)
                                .MatchForward(false,
                                              new CodeMatch(OpCodes.Ldarg_0),
                                              new CodeMatch(OpCodes.Ldarg_0),
                                              new CodeMatch(l => l.opcode == OpCodes.Call && l.Calls(AccessTools.Method(typeof(SceneEdit), "InitMenuNative"))))
                                .SetAndAdvance(OpCodes.Nop, null)
                                .SetAndAdvance(OpCodes.Nop, null)
                                .SetAndAdvance(OpCodes.Nop, null)
                                .SetAndAdvance(OpCodes.Nop, null)
                                .SetAndAdvance(OpCodes.Nop, null)
                                //.SetAndAdvance(OpCodes.Nop, null)
                                .Insert(
                new CodeInstruction(OpCodes.Ldarg_0),
                Transpilers.EmitDelegate <Action>(() =>
            {
                Debug.Log("Calling your test coroutine.");

                //InitMenuNativeRe();
                //@this2.StartCoroutine(test2());
                //Task.Factory.StartNew(new Action(() => InitialBackgroundWorker()));
                @this2.StartCoroutine(InitialBackgroundWorker());
                //@this2.StartCoroutine(MenuLoaderWorker());
                //test2();
            }),
                new CodeInstruction(OpCodes.Pop)
                )
                                //.Insert(new CodeInstruction (OpCodes.Call, AccessTools.Method(typeof(Main), "InitMenuNativeRe")))
                                .InstructionEnumeration();

            return(custominstruc);
        }
        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());
        }
        static IEnumerable <CodeInstruction> CodeTranspiler(IEnumerable <CodeInstruction> instructions)
        {
            var custominstruc = new CodeMatcher(instructions)
                                .MatchForward(true,
                                              new CodeMatch(OpCodes.Ldarg_0),
                                              new CodeMatch(OpCodes.Ldarg_0),
                                              new CodeMatch(OpCodes.Ldfld),
                                              new CodeMatch(OpCodes.Ldc_I4_0),
                                              new CodeMatch(OpCodes.Ceq),
                                              new CodeMatch(OpCodes.Stfld),
                                              new CodeMatch(OpCodes.Ldarg_0),
                                              new CodeMatch(OpCodes.Ldarg_0),
                                              new CodeMatch(OpCodes.Ldfld),
                                              new CodeMatch(OpCodes.Ldc_I4_0),
                                              new CodeMatch(OpCodes.Ceq),
                                              new CodeMatch(OpCodes.Stfld),
                                              new CodeMatch(OpCodes.Br)
                                              )
                                .Insert(
                new CodeInstruction(OpCodes.Ldarg_0),
                new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PropMyItem), "_isVisible")),
                Transpilers.EmitDelegate <Action <bool> >((vis) => {
                Main.PMIUIStatus = vis;
            })
                )
                                .InstructionEnumeration();

            return(custominstruc);
        }