diff --git a/UXAssist/DysonSpherePatch.cs b/UXAssist/DysonSpherePatch.cs index 3590397..06da949 100644 --- a/UXAssist/DysonSpherePatch.cs +++ b/UXAssist/DysonSpherePatch.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.IO; using System.Reflection.Emit; using BepInEx.Configuration; using HarmonyLib; @@ -301,6 +302,141 @@ public static class DysonSpherePatch } } + [HarmonyTranspiler] + [HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool))] + [HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool), typeof(int), typeof(int), typeof(int))] + private static IEnumerable FactorySystem_GameTick_Transpiler(IEnumerable instructions, ILGenerator generator) + { + /* for (int m = min; m < max; m++) + * => + * for (int m = min + (gameTick % 9); m < max; m += 9) + */ + var matcher = new CodeMatcher(instructions, generator); + matcher.MatchForward(false, + new CodeMatch(OpCodes.Ldarg_0), + new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.ejectorPool))), + new CodeMatch(instr => instr.opcode == OpCodes.Ldloc || instr.opcode == OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Ldelema, typeof(EjectorComponent)), + new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.id))), + new CodeMatch(instr => instr.opcode == OpCodes.Ldloc || instr.opcode == OpCodes.Ldloc_S), + new CodeMatch(instr => instr.opcode == OpCodes.Bne_Un || instr.opcode == OpCodes.Bne_Un_S) + ).Advance(-2).InsertAndAdvance( + new CodeInstruction(OpCodes.Ldarg_1), + new CodeInstruction(OpCodes.Ldc_I8, 9L), + new CodeInstruction(OpCodes.Rem), + new CodeInstruction(OpCodes.Conv_I4), + new CodeInstruction(OpCodes.Add) + ).Advance(9).MatchForward(false, + new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(SignData), nameof(SignData.signType))), + new CodeMatch(instr => instr.opcode == OpCodes.Ldloc || instr.opcode == OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Ldc_I4_1) + ).Advance(2).Set(OpCodes.Ldc_I4_S, 9); + return matcher.InstructionEnumeration(); + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))] + private static IEnumerable EjectorComponent_InternalUpdate_Transpiler(IEnumerable instructions, ILGenerator generator) + { + /* int num3 = (int)(power * 10000f * (1f + num2) + 0.1f); + * => + * int num3 = (int)(power * 90000f * (1f + num2) + 0.1f); + */ + var matcher = new CodeMatcher(instructions, generator); + matcher.MatchForward(false, + new CodeMatch(instr => instr.opcode == OpCodes.Ldc_R4 && instr.OperandIs(10000f)) + ).Operand = 90000f; + return matcher.InstructionEnumeration(); + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.NewEjectorComponent))] + private static IEnumerable FactorySystem_NewEjectorComponent_Transpiler(IEnumerable instructions, ILGenerator generator) + { + /* this.ejectorPool[num2].chargeSpend = desc.ejectorChargeFrame * 10000; + * this.ejectorPool[num2].coldSpend = desc.ejectorColdFrame * 10000; + * => + * this.ejectorPool[num2].chargeSpend = (desc.ejectorChargeFrame + desc.ejectorColdFrame) * 10000; + * this.ejectorPool[num2].coldSpend = 0; + */ + var matcher = new CodeMatcher(instructions, generator); + matcher.MatchForward(false, + new CodeMatch(OpCodes.Ldarg_0), + new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.ejectorPool))), + new CodeMatch(OpCodes.Ldloc_0), + new CodeMatch(OpCodes.Ldelema, typeof(EjectorComponent)), + new CodeMatch(OpCodes.Ldarg_2), + new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PrefabDesc), nameof(PrefabDesc.ejectorChargeFrame))), + new CodeMatch(OpCodes.Ldc_I4, 10000), + new CodeMatch(OpCodes.Mul), + new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.chargeSpend))), + new CodeMatch(OpCodes.Ldarg_0), + new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.ejectorPool))), + new CodeMatch(OpCodes.Ldloc_0), + new CodeMatch(OpCodes.Ldelema, typeof(EjectorComponent)), + new CodeMatch(OpCodes.Ldarg_2), + new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PrefabDesc), nameof(PrefabDesc.ejectorColdFrame))), + new CodeMatch(OpCodes.Ldc_I4, 10000), + new CodeMatch(OpCodes.Mul), + new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.coldSpend))) + ).RemoveInstructions(18).Insert( + new CodeInstruction(OpCodes.Ldarg_0), + new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.ejectorPool))), + new CodeInstruction(OpCodes.Ldloc_0), + new CodeInstruction(OpCodes.Ldelema, typeof(EjectorComponent)), + new CodeInstruction(OpCodes.Ldarg_2), + new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PrefabDesc), nameof(PrefabDesc.ejectorChargeFrame))), + new CodeInstruction(OpCodes.Ldarg_2), + new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PrefabDesc), nameof(PrefabDesc.ejectorColdFrame))), + new CodeInstruction(OpCodes.Add), + new CodeInstruction(OpCodes.Ldc_I4, 10000), + new CodeInstruction(OpCodes.Mul), + new CodeInstruction(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.chargeSpend))), + new CodeInstruction(OpCodes.Ldarg_0), + new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.ejectorPool))), + new CodeInstruction(OpCodes.Ldloc_0), + new CodeInstruction(OpCodes.Ldelema, typeof(EjectorComponent)), + new CodeInstruction(OpCodes.Ldc_I4_0), + new CodeInstruction(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.coldSpend))) + ); + return matcher.InstructionEnumeration(); + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.Import))] + private static IEnumerable EjectorComponent_Import_Transpiler(IEnumerable instructions, ILGenerator generator) + { + /* this.chargeSpend = r.ReadInt32(); + * this.coldSpend = r.ReadInt32(); + * => + * this.chargeSpend = r.ReadInt32() + r.ReadInt32(); + * this.coldSpend = 0; + */ + var matcher = new CodeMatcher(instructions, generator); + matcher.MatchForward(false, + new CodeMatch(OpCodes.Ldarg_0), + new CodeMatch(OpCodes.Ldarg_1), + new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryReader), nameof(BinaryReader.ReadInt32))), + new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.chargeSpend))), + new CodeMatch(OpCodes.Ldarg_0), + new CodeMatch(OpCodes.Ldarg_1), + new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryReader), nameof(BinaryReader.ReadInt32))), + new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.coldSpend))) + ).RemoveInstructions(8).Insert( + new CodeInstruction(OpCodes.Ldarg_0), + new CodeInstruction(OpCodes.Ldarg_1), + new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryReader), nameof(BinaryReader.ReadInt32))), + new CodeInstruction(OpCodes.Ldarg_1), + new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryReader), nameof(BinaryReader.ReadInt32))), + new CodeInstruction(OpCodes.Add), + new CodeInstruction(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.chargeSpend))), + new CodeInstruction(OpCodes.Ldarg_0), + new CodeInstruction(OpCodes.Ldc_I4_0), + new CodeInstruction(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.coldSpend))) + ); + return matcher.InstructionEnumeration(); + } + [HarmonyTranspiler] [HarmonyPatch(typeof(DysonNode), nameof(DysonNode.spReqOrder), MethodType.Getter)] private static IEnumerable DysonNode_spReqOrder_Getter_Transpiler(IEnumerable instructions, ILGenerator generator)