Пример #1
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());
        }
        public static IEnumerable <CodeInstruction> GameTick_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            // Send PlayerUseWarper(bool) whenever warpCommand is toggled between true or false
            var codeMatcher = new CodeMatcher(instructions)
                              .MatchForward(true,
                                            new CodeMatch(i => i.opcode == OpCodes.Stfld && ((FieldInfo)i.operand).Name == "warpCommand")
                                            );

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

            return(codeMatcher
                   .Repeat(matcher =>
            {
                var warpCommand = matcher.InstructionAt(-1).opcode == OpCodes.Ldc_I4_1;
                matcher
                .Advance(1)
                .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Action>(() =>
                {
                    // send to host / clients
                    if (!SimulatedWorld.Initialized)
                    {
                        return;
                    }

                    if (LocalPlayer.IsMasterClient)
                    {
                        PlayerUseWarper packet = new PlayerUseWarper(warpCommand)
                        {
                            PlayerId = LocalPlayer.PlayerId
                        };
                        LocalPlayer.SendPacket(packet);
                    }
                    else
                    {
                        LocalPlayer.SendPacket(new PlayerUseWarper(warpCommand));
                    }

                    return;
                }));
            })
                   .InstructionEnumeration());
        }
Пример #3
0
        private static IEnumerable <CodeInstruction> UpdateDrones_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iLGenerator)
        {
            CodeMatcher codeMatcher = new CodeMatcher(instructions, iLGenerator)
                                      .MatchForward(true,
                                                    new CodeMatch(i => i.IsLdloc()),
                                                    new CodeMatch(i => i.IsLdloc()),
                                                    new CodeMatch(OpCodes.Ldelema, typeof(MechaDrone)),
                                                    new CodeMatch(i => i.opcode == OpCodes.Ldc_I4_2 || i.opcode == OpCodes.Ldc_I4_3),
                                                    new CodeMatch(i => i.opcode == OpCodes.Stfld && ((FieldInfo)i.operand).Name == "stage")
                                                    );

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

            return(codeMatcher
                   .Repeat(matcher =>
            {
                matcher = matcher.Advance(1);

                CodeInstruction droneIdInst = matcher.InstructionAt(1);       // [i]
                CodeInstruction entityIdInst = matcher.InstructionAt(3);      // drones[i].targetObject
                CodeInstruction stageInst = matcher.InstructionAt(-2);        // drones[i].stage

                matcher = matcher
                          .InsertAndAdvance(droneIdInst)
                          .InsertAndAdvance(entityIdInst)
                          .InsertAndAdvance(stageInst)
                          .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Action <int, int, int> >((droneId, entityId, stage) =>
                {
                    if (Multiplayer.IsActive)
                    {
                        Multiplayer.Session.Drones.BroadcastDroneOrder(droneId, entityId, stage);
                    }
                }))
                          .Advance(1);
            })
                   .InstructionEnumeration());
        }
Пример #4
0
        public static IEnumerable <CodeInstruction> GameTick_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            // Send PlayerUseWarper(bool) whenever warpCommand is toggled between true or false
            CodeMatcher codeMatcher = new CodeMatcher(instructions)
                                      .MatchForward(true,
                                                    new CodeMatch(i => i.opcode == OpCodes.Stfld && ((FieldInfo)i.operand).Name == "warpCommand")
                                                    );

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

            return(codeMatcher
                   .Repeat(matcher =>
            {
                bool warpCommand = matcher.InstructionAt(-1).opcode == OpCodes.Ldc_I4_1;
                matcher
                .Advance(1)
                .InsertAndAdvance(HarmonyLib.Transpilers.EmitDelegate <Action>(() =>
                {
                    if (Multiplayer.IsActive)
                    {
                        if (Multiplayer.Session.LocalPlayer.IsHost)
                        {
                            PlayerUseWarper packet = new PlayerUseWarper(warpCommand)
                            {
                                PlayerId = Multiplayer.Session.LocalPlayer.Id
                            };
                            Multiplayer.Session.Network.SendPacket(packet);
                        }
                        else
                        {
                            Multiplayer.Session.Network.SendPacket(new PlayerUseWarper(warpCommand));
                        }
                    }
                }));
            })
                   .InstructionEnumeration());
        }
Пример #5
0
        public static IEnumerable <CodeInstruction> PowerSystem_GameTick_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            CodeMatcher codeMatcher = new CodeMatcher(instructions)
                                      .MatchForward(true,
                                                    new CodeMatch(OpCodes.Ldarg_0),
                                                    new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))),
                                                    new CodeMatch(OpCodes.Ldloc_S),
                                                    new CodeMatch(OpCodes.Ldelema),
                                                    new CodeMatch(OpCodes.Ldarg_0),
                                                    new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))),
                                                    new CodeMatch(OpCodes.Ldloc_S),
                                                    new CodeMatch(OpCodes.Ldelema),
                                                    new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.workEnergyPerTick))),
                                                    new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.requiredEnergy))));

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

            codeMatcher = codeMatcher
                          .Advance(1)
                          .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
                          .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 59))
                          .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 22))
                          .Insert(HarmonyLib.Transpilers.EmitDelegate <PlayerChargesAtTower>((PowerSystem _this, int powerNodeId, int powerNetId) =>
            {
                if (Multiplayer.IsActive)
                {
                    if (!Multiplayer.Session.LocalPlayer.IsHost)
                    {
                        _this.nodePool[powerNodeId].requiredEnergy = _this.nodePool[powerNodeId].idleEnergyPerTick;     // this gets added onto the known required energy by Multiplayer.Session.PowerTowers. and PowerSystem_Patch
                        if (Multiplayer.Session.PowerTowers.AddRequested(_this.planet.id, powerNetId, powerNodeId, true, false))
                        {
                            Multiplayer.Session.Network.SendPacket(new PowerTowerUserLoadingRequest(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick, true));
                        }
                    }
                    else
                    {
                        PowerNetwork pNet = _this.netPool[powerNetId];
                        if (Multiplayer.Session.PowerTowers.AddRequested(_this.planet.id, powerNetId, powerNodeId, true, false))
                        {
                            Multiplayer.Session.PowerTowers.AddExtraDemand(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick);
                            Multiplayer.Session.Network.SendPacketToLocalStar(new PowerTowerUserLoadingResponse(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick,
                                                                                                                pNet.energyCapacity,
                                                                                                                pNet.energyRequired,
                                                                                                                pNet.energyServed,
                                                                                                                pNet.energyAccumulated,
                                                                                                                pNet.energyExchanged,
                                                                                                                true));
                        }
                    }
                }
            }))
                          // now search for where its set back to idle after player leaves radius / has charged fully
                          .MatchForward(true,
                                        new CodeMatch(OpCodes.Ldarg_0),
                                        new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))),
                                        new CodeMatch(OpCodes.Ldloc_S),
                                        new CodeMatch(OpCodes.Ldelema),
                                        new CodeMatch(OpCodes.Ldarg_0),
                                        new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))),
                                        new CodeMatch(OpCodes.Ldloc_S),
                                        new CodeMatch(OpCodes.Ldelema),
                                        new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.idleEnergyPerTick))),
                                        new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.requiredEnergy))));

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

            return(codeMatcher
                   .Repeat(matcher =>
            {
                matcher
                .Advance(1)
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 59))
                .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 22))
                .Insert(HarmonyLib.Transpilers.EmitDelegate <PlayerChargesAtTower>((PowerSystem _this, int powerNodeId, int powerNetId) =>
                {
                    if (Multiplayer.IsActive)
                    {
                        if (!Multiplayer.Session.LocalPlayer.IsHost)
                        {
                            if (Multiplayer.Session.PowerTowers.AddRequested(_this.planet.id, powerNetId, powerNodeId, false, false))
                            {
                                Multiplayer.Session.Network.SendPacket(new PowerTowerUserLoadingRequest(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick, false));
                            }
                        }
                        else
                        {
                            PowerNetwork pNet = _this.netPool[powerNetId];
                            if (Multiplayer.Session.PowerTowers.AddRequested(_this.planet.id, powerNetId, powerNodeId, false, false))
                            {
                                Multiplayer.Session.PowerTowers.RemExtraDemand(_this.planet.id, powerNetId, powerNodeId);
                                Multiplayer.Session.Network.SendPacketToLocalStar(new PowerTowerUserLoadingResponse(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick,
                                                                                                                    pNet.energyCapacity,
                                                                                                                    pNet.energyRequired,
                                                                                                                    pNet.energyServed,
                                                                                                                    pNet.energyAccumulated,
                                                                                                                    pNet.energyExchanged,
                                                                                                                    false));
                            }
                        }
                    }
                }));
            })
                   .InstructionEnumeration());
        }