Skip to content

Commit 63de2eb

Browse files
committed
Added TimeWarpThrustFix by @SunSerega
1 parent 9acc6f4 commit 63de2eb

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System.Reflection.Emit;
2+
using HarmonyLib;
3+
using KSP.Sim.impl;
4+
using SpaceWarp.API.Logging;
5+
6+
namespace CommunityFixes.Fix.TimeWarpThrustFix;
7+
8+
[Fix("Fixes time warp thrust rounding error.")]
9+
public class TimeWarpThrustFix : BaseFix
10+
{
11+
private static ILogger _logger;
12+
13+
public override void OnInitialized()
14+
{
15+
_logger = Logger;
16+
HarmonyInstance.PatchAll(typeof(TimeWarpThrustFix));
17+
}
18+
19+
private static bool CheckNeedRoundingError(double positionError, double velocityError)
20+
{
21+
var needError = positionError >= 0.01 || velocityError >= 0.01;
22+
if (needError)
23+
{
24+
_logger.LogDebug($"pos_err={positionError}, vel_err={velocityError}");
25+
}
26+
27+
return false;
28+
}
29+
30+
[HarmonyPatch(typeof(VesselComponent), nameof(VesselComponent.HandleOrbitalPhysicsUnderThrustStart))]
31+
[HarmonyTranspiler]
32+
public static IEnumerable<CodeInstruction> VesselComponent_HandleOrbitalPhysicsUnderThrustStart(
33+
IEnumerable<CodeInstruction> bodyToReplace
34+
)
35+
{
36+
var propGetSqrMagnitude = typeof(Vector3d).GetProperty("sqrMagnitude")!.GetGetMethod();
37+
var res = TranspilerHelper.Replace(
38+
bodyToReplace,
39+
[
40+
new TranspilerHelper.ILLookupKey { OpCode = OpCodes.Ldloca_S },
41+
new TranspilerHelper.ILLookupKey { OpCode = OpCodes.Call, Operand = propGetSqrMagnitude },
42+
new TranspilerHelper.ILLookupKey { OpCode = OpCodes.Ldc_R8 },
43+
new TranspilerHelper.ILLookupKey { OpCode = OpCodes.Bge_Un },
44+
new TranspilerHelper.ILLookupKey { OpCode = OpCodes.Ldloca_S },
45+
new TranspilerHelper.ILLookupKey { OpCode = OpCodes.Call, Operand = propGetSqrMagnitude },
46+
new TranspilerHelper.ILLookupKey { OpCode = OpCodes.Ldc_R8 },
47+
new TranspilerHelper.ILLookupKey { OpCode = OpCodes.Bge_Un },
48+
],
49+
oldBody =>
50+
{
51+
var checkNeedRoundingError = CheckNeedRoundingError;
52+
var instructions = oldBody.ToArray();
53+
return
54+
[
55+
instructions[0], instructions[1],
56+
instructions[4], instructions[5],
57+
new CodeInstruction(OpCodes.Call, checkNeedRoundingError.Method),
58+
new CodeInstruction(OpCodes.Ldc_I4_1),
59+
instructions[7], new CodeInstruction(OpCodes.Nop),
60+
];
61+
},
62+
1..1
63+
);
64+
65+
return res;
66+
}
67+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System.Reflection.Emit;
2+
using HarmonyLib;
3+
using JetBrains.Annotations;
4+
5+
namespace CommunityFixes.Fix.TimeWarpThrustFix;
6+
7+
internal static class TranspilerHelper
8+
{
9+
public sealed class ILLookupKey
10+
{
11+
public OpCode OpCode { get; set; }
12+
[CanBeNull] public object Operand { get; set; }
13+
}
14+
15+
public static IEnumerable<CodeInstruction> Replace(
16+
IEnumerable<CodeInstruction> oldBody,
17+
ILLookupKey[] lookupKeys,
18+
Func<IReadOnlyCollection<CodeInstruction>, IEnumerable<CodeInstruction>> repl,
19+
Range expectedTimes
20+
)
21+
{
22+
var queue = new Queue<CodeInstruction>(lookupKeys.Length);
23+
var foundCount = 0;
24+
25+
foreach (var instruction in oldBody)
26+
{
27+
queue.Enqueue(instruction);
28+
if (queue.Count < lookupKeys.Length) continue;
29+
30+
if (queue.Zip(lookupKeys, (instr, lookup) =>
31+
instr.opcode == lookup.OpCode &&
32+
(lookup.Operand is null || Equals(instr.operand, lookup.Operand))
33+
).All(b => b))
34+
{
35+
foundCount++;
36+
foreach (var modInstr in repl(queue))
37+
{
38+
yield return modInstr;
39+
}
40+
41+
queue.Clear();
42+
continue;
43+
}
44+
45+
yield return queue.Dequeue();
46+
}
47+
48+
foreach (var instr in queue)
49+
{
50+
yield return instr;
51+
}
52+
53+
if (foundCount < expectedTimes.Start.Value || foundCount > expectedTimes.End.Value)
54+
{
55+
throw new InvalidOperationException($"Found expected IL {foundCount} times, instead of {expectedTimes}");
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)