Skip to content

Commit

Permalink
New KSP bugfix patch : [**TimeWarpOrbitShift**](#170) [KSP 1.8.0 - 1.…
Browse files Browse the repository at this point in the history
…12.5] Fix active vessel orbit moving randomly when engaging timewarp while under heavy CPU load.
  • Loading branch information
gotmachine committed Dec 6, 2023
1 parent 0640f7e commit 564d5f9
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
3 changes: 3 additions & 0 deletions GameData/KSPCommunityFixes/Settings.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ KSP_COMMUNITY_FIXES
// change the part crew capacity. Notably affect the stock inflatable airlock.
ModuleAnimateGenericCrewModSpawnIVA = true

// Fix active vessel orbit moving randomly when engaging timewarp while under heavy CPU load.
TimeWarpOrbitShift = true

// ##########################
// Obsolete bugfixes
// ##########################
Expand Down
106 changes: 106 additions & 0 deletions KSPCommunityFixes/BugFixes/TimeWarpOrbitShift.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// See https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/170
// When engaging non-physical timewarp, if the game is lagging, and the max dt per frame main menu setting is set
// to high values, the active vessel orbit will shift significantely. The root cause isn't identified, but this
// heavily suggest that some KSP components rely implicitly on Update and FixedUpdate to be called exactely once
// per frame, which isn't true in such a laggy situation (there will usually be multiple FixedUpdate calls back to
// to back followed by an Update call). We can fix this by forcing the the max dt per frame to 0.02 for a single
// frame after timewarp has been engaged, which will temporarily force a 1:1 call ratio between Update and FixedUpdate.

// debug tool : induce simulated lag in order to have multiple FixedUpdate calls per Update
// (works better by also setting max dt per frame to high value in the KSP main menu settings)
// #define LAGMACHINETEST

using System;
using HarmonyLib;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;

namespace KSPCommunityFixes.BugFixes
{
public class TimeWarpOrbitShift : BasePatch
{
protected override Version VersionMin => new Version(1, 8, 0);

protected override void ApplyPatches(List<PatchInfo> patches)
{
patches.Add(new PatchInfo(
PatchMethodType.Prefix,
AccessTools.Method(typeof(TimeWarp), nameof(TimeWarp.setRate)),
this));
}

static void TimeWarp_setRate_Prefix(TimeWarp __instance, int rateIdx)
{
if (HighLogic.LoadedSceneIsFlight
&& __instance.Mode == TimeWarp.Modes.HIGH
&& rateIdx > __instance.maxPhysicsRate_index
&& __instance.current_rate_index <= __instance.maxPhysicsRate_index)
{
__instance.StartCoroutine(FixMaxDTPerFrameOnEngageHighWarpCoroutine());
}
}

static IEnumerator FixMaxDTPerFrameOnEngageHighWarpCoroutine()
{
Time.maximumDeltaTime = 0.02f;
yield return null;
Time.maximumDeltaTime = GameSettings.PHYSICS_FRAME_DT_LIMIT;
}
}

#if LAGMACHINETEST
[KSPAddon(KSPAddon.Startup.Flight, false)]
public class TimeWarpOrbitShiftTest : MonoBehaviour
{
private int updateLag = 30;
private int fixedUpdateLag = 15;
private string updateLagTxt;
private string fixedUpdateLagTxt;
private float maximumDeltaTime;
private string maximumDeltaTimeTxt;

void Start()
{
updateLagTxt = updateLag.ToString();
fixedUpdateLagTxt = fixedUpdateLag.ToString();
maximumDeltaTime = Time.maximumDeltaTime;
maximumDeltaTimeTxt = maximumDeltaTime.ToString();
}

void Update() => Thread.Sleep(updateLag);
void FixedUpdate() => Thread.Sleep(fixedUpdateLag);

void OnGUI()
{
updateLagTxt = GUI.TextField(new Rect(20, 100, 50, 20), updateLagTxt);
if (GUI.Button(new Rect(80, 100, 100, 20), "updateLag"))
updateLag = int.Parse(updateLagTxt);

fixedUpdateLagTxt = GUI.TextField(new Rect(20, 120, 50, 20), fixedUpdateLagTxt);
if (GUI.Button(new Rect(80, 120, 100, 20), "fixedUpdateLag"))
fixedUpdateLag = int.Parse(fixedUpdateLagTxt);

if (maximumDeltaTime != Time.maximumDeltaTime)
{
maximumDeltaTime = Time.maximumDeltaTime;
maximumDeltaTimeTxt = maximumDeltaTime.ToString();
}

maximumDeltaTimeTxt = GUI.TextField(new Rect(20, 140, 50, 20), maximumDeltaTimeTxt);
if (GUI.Button(new Rect(80, 140, 100, 20), "maxDT"))
{
maximumDeltaTime = float.Parse(maximumDeltaTimeTxt);
Time.maximumDeltaTime = maximumDeltaTime;
}

if (GUI.Button(new Rect(20, 160, 100, 20), "start warp"))
TimeWarp.SetRate(TimeWarp.fetch.warpRates.Length - 1, false);

if (GUI.Button(new Rect(20, 180, 100, 20), "stop warp"))
TimeWarp.SetRate(0, true);
}
}
#endif
}
1 change: 1 addition & 0 deletions KSPCommunityFixes/KSPCommunityFixes.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
<Compile Include="BugFixes\ModuleAnimateGenericCrewModSpawnIVA.cs" />
<Compile Include="BugFixes\ReRootPreserveSurfaceAttach.cs" />
<Compile Include="BugFixes\ThumbnailSpotlight.cs" />
<Compile Include="BugFixes\TimeWarpOrbitShift.cs" />
<Compile Include="BugFixes\UpgradeBugs.cs" />
<Compile Include="BugFixes\PartTooltipUpgradesApplyToSubstituteParts.cs" />
<Compile Include="BugFixes\CometMiningNotRemovingMass.cs" />
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ User options are available from the "ESC" in-game settings menu :<br/><img src="
- [**FixGetUnivseralTime**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/155) [KSP 1.8.0 - 1.12.5]<br/>Fix Planetarium.GetUniversalTime returning bad values in the editor.
- [**DockingPortConserveMomentum**](https://github.com/KSPModdingLibs/KSPCommunityFixes/pull/160) [KSP 1.12.3 - 1.12.5]<br/>Make docking ports conserve momentum by averaging the acquire force between the two ports. Notably, docking port Kraken drives will no longer work.
- [**ModuleAnimateGenericCrewModSpawnIVA**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/169) [KSP 1.8.0 - 1.12.5]<br/>Fix IVA & crew portrait not spawning/despawning when ModuleAnimateGeneric is used to change the part crew capacity. Notably affect the stock inflatable airlock.
- [**TimeWarpOrbitShift**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/170) [KSP 1.8.0 - 1.12.5]<br/>Fix active vessel orbit moving randomly when engaging timewarp while under heavy CPU load.

#### Quality of Life tweaks

Expand Down Expand Up @@ -177,8 +178,9 @@ If doing so in the `Debug` configuration and if your KSP install is modified to
### Changelog

##### 1.32.0
- **ConfigNodePerf** : fixed [issue #167](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/167), incorrect parsing of config files using `cr` only (old MacOs style) line endings.
- **ConfigNodePerf** : fixed [issue #167](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/167), incorrect parsing of config files using `cr` only (old Mac style) line endings.
- New KSP bugfix : [**ModuleAnimateGenericCrewModSpawnIVA**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/169) [KSP 1.8.0 - 1.12.5], fix IVA & crew portrait not spawning/despawning when ModuleAnimateGeneric is used to change the part crew capacity. Notably affect the stock inflatable airlock.
- New KSP bugfix : [**TimeWarpOrbitShift**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/170) [KSP 1.8.0 - 1.12.5], fix active vessel orbit moving randomly when engaging timewarp while under heavy CPU load.

##### 1.31.1
- **DragCubeGeneration** : Actually enable patch by default, I somehow failed to push that change in the last release (Thanks @dok_377 for reporting)
Expand Down

0 comments on commit 564d5f9

Please sign in to comment.