Beispiel #1
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());
        }
Beispiel #2
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());
        }
Beispiel #3
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());
        }
        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());
        }
Beispiel #5
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());
        }
Beispiel #6
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());
        }
Beispiel #7
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .End()
                                  .MatchBack(false,
                                             new CodeMatch(OpCodes.Ldarg_0),
                                             new CodeMatch(OpCodes.Ldflda, AccessTools.Field(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.cursorTarget))));

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

            object previewVariable = matcher2.Operand;

            matcher.Advance(1);

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

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

            return(matcher.InstructionEnumeration());
        }
Beispiel #8
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);
 }
Beispiel #9
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());
        }
Beispiel #10
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());
        }
Beispiel #11
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());
        }
 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);
     }
 }
 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> 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);
     }
 }
        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);
        }
Beispiel #16
0
        static IEnumerable <CodeInstruction> CheckConditions(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldloc_S),
                                                new CodeMatch(i =>
                                                              i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "desc"),
                                                new CodeMatch(i =>
                                                              i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "hasBuildCollider"),
                                                new CodeMatch(OpCodes.Brfalse),
                                                new CodeMatch(OpCodes.Ldloc_S)
                                                ).Advance(1)
                                  .SetAndAdvance(OpCodes.Ldarg_0, null)
                                  .SetInstructionAndAdvance(
                Transpilers.EmitDelegate <Func <BuildPreview, BuildTool_Click, bool> >(
                    (preview, _this) =>
            {
                if (preview.item.ID == 2212)
                {
                    if (_this.handPrefabDesc != null && _this.handPrefabDesc.modelIndex == GroundSubstation.firstSubstationId + 2)
                    {
                        return(false);
                    }
                }

                return(preview.desc.hasBuildCollider);
            }));


            return(matcher.InstructionEnumeration());
        }
Beispiel #17
0
        public static IEnumerable <CodeInstruction> Replace10With1Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false, new CodeMatch(instr => instr.opcode == OpCodes.Ldc_R4 && Mathf.Approximately((float)instr.operand, 10f)))
                                  .SetOperandAndAdvance(1f);

            return(matcher.InstructionEnumeration());
        }
        public static IEnumerable <CodeInstruction> ChangeCastDistance(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldc_R4, 800f)
                                                )
                                  .SetInstruction(Transpilers.EmitDelegate <Func <float> >(() => GameCamera.instance.blueprintPoser.planetRadius * 2.4f));


            return(matcher.InstructionEnumeration());
        }
Beispiel #19
0
        static IEnumerable <CodeInstruction> RedirectSaves(IEnumerable <CodeInstruction> instructions)
        {
            var codeMatch = new CodeMatcher(instructions);

            codeMatch = codeMatch.MatchForward(false, new CodeMatch(OpCodes.Ldstr, "save"));
            codeMatch = codeMatch.Repeat(matcher =>
            {
                matcher.SetOperandAndAdvance(folderRedirect + matcher.Operand);
            });
            return(codeMatch.InstructionEnumeration());
        }
Beispiel #20
0
        public static IEnumerable <CodeInstruction> ColorPatch(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(instr => instr.opcode == OpCodes.Ldc_I4_S && (sbyte)instr.operand == 12)
                                                ).Repeat(matcher2 =>
            {
                matcher2.SetOperandAndAdvance(16);
            });

            return(matcher.InstructionEnumeration());
        }
        public static IEnumerable <CodeInstruction> Update_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator il)
        {
            CodeMatcher matcher = new CodeMatcher(instructions, il)
                                  // find for loop increment and exit condition
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Stloc_0),
                                                new CodeMatch(OpCodes.Ldloc_0),
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LogisticShipRenderer), "transport")),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GalacticTransport), "stationCursor")),
                                                new CodeMatch(OpCodes.Blt))
                                  .Advance(-3)
                                  .CreateLabel(out Label jmpToForCompare)
                                  .Start()
                                  // find stationPool access (which produces IndexOutOfBounds in rare cases)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LogisticShipRenderer), "transport")),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GalacticTransport), "stationPool")),
                                                new CodeMatch(OpCodes.Ldloc_0))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LogisticShipRenderer), "transport")))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(GalacticTransport), "stationPool")))
                                  .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_0))
                                  .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <IsOutOfBounds>((StationComponent[] stationComponent, int index) =>
            {
                if (index >= stationComponent.Length && Multiplayer.IsActive && Multiplayer.Session.LocalPlayer.IsClient)
                {
                    WarningManager.DisplayCriticalWarning("IndexOutOfBounds in LogisticShipRenderer. Consider reconnecting!");
                }
                return(index < stationComponent.Length);
            }))
                                  .Insert(new CodeInstruction(OpCodes.Brfalse, jmpToForCompare))
                                  // find start of our injected code
                                  .MatchBack(false,
                                             new CodeMatch(OpCodes.Ldarg_0),
                                             new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LogisticShipRenderer), "transport")),
                                             new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GalacticTransport), "stationPool")),
                                             new CodeMatch(OpCodes.Ldloc_0))
                                  .CreateLabel(out Label jmpToOverflowCheck)
                                  .Start()
                                  // exchange loop start ptr with our index checking
                                  .MatchForward(true,
                                                new CodeMatch(OpCodes.Stloc_0),
                                                new CodeMatch(OpCodes.Ldloc_0),
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LogisticShipRenderer), "transport")),
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GalacticTransport), "stationCursor")),
                                                new CodeMatch(OpCodes.Blt))
                                  .SetOperandAndAdvance(jmpToOverflowCheck);

            return(matcher.InstructionEnumeration());
        }
Beispiel #22
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());
        }
Beispiel #23
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());
        }
Beispiel #24
0
        static IEnumerable <CodeInstruction> FixMovement(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(true,
                                                new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerController), nameof(PlayerController.actionBuild))),
                                                new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(PlayerAction_Build), "get_blueprintMode")),
                                                new CodeMatch(OpCodes.Ldc_I4_0),
                                                new CodeMatch(OpCodes.Cgt_Un)
                                                ).Advance(1)
                                  .InsertAndAdvance(Transpilers.EmitDelegate <Func <bool, bool> >(isBp => isBp && mode));

            return(matcher.InstructionEnumeration());
        }
Beispiel #25
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());
        }
        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());
        }
Beispiel #27
0
        public static IEnumerable <CodeInstruction> Replace10With1Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false, new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(StationComponent), nameof(StationComponent.deliveryDrones))))
                                  .MatchBack(false, new CodeMatch(instr => instr.opcode == OpCodes.Ldc_R4 && Mathf.Approximately((float)instr.operand, 10f)))
                                  .SetOperandAndAdvance(1f);

            matcher
            .MatchForward(false, new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(StationComponent), nameof(StationComponent.deliveryShips))))
            .MatchBack(false, new CodeMatch(instr => instr.opcode == OpCodes.Ldc_R4 && Mathf.Approximately((float)instr.operand, 10f)))
            .SetOperandAndAdvance(1f);

            return(matcher.InstructionEnumeration());
        }
Beispiel #28
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldc_I4_S, (sbyte)122),
                                                new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(Input), nameof(Input.GetKeyDown), new [] { typeof(KeyCode) })))
                                  .RemoveInstruction()
                                  .SetInstruction(Transpilers.EmitDelegate <Func <bool> >(() =>
            {
                return(CustomKeyBindSystem.GetKeyBind("DSPTrashButton").keyValue);
            }));

            return(matcher.InstructionEnumeration());
        }
Beispiel #29
0
        public static IEnumerable <CodeInstruction> DontClearOpenPath(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false,
                                                new CodeMatch(OpCodes.Ldarg_0),
                                                new CodeMatch(OpCodes.Ldstr),
                                                new CodeMatch(OpCodes.Stfld)
                                                )
                                  .SetOpcodeAndAdvance(OpCodes.Nop)
                                  .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Nop))
                                  .SetInstructionAndAdvance(new CodeInstruction(OpCodes.Nop));

            return(matcher.InstructionEnumeration());
        }
Beispiel #30
0
        public static IEnumerable <CodeInstruction> DontClearOpenPath(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher matcher = new CodeMatcher(instructions)
                                  .MatchForward(false, new CodeMatch(OpCodes.Ldstr))

                                  .SetInstruction(Transpilers.EmitDelegate <Func <string> >(() =>
            {
                string currentPath = UIRoot.instance.uiGame.blueprintBrowser.openPath;

                return(BlueprintData.GenerateNewFileName(currentPath));
            }));

            return(matcher.InstructionEnumeration());
        }