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()); }
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()); }
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()); }
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()); }