From 9107409253e0a39870d75e4db50602539d7b8d4c Mon Sep 17 00:00:00 2001 From: Cole Thompson Date: Mon, 14 Dec 2020 14:35:15 -0600 Subject: [PATCH 1/6] Use correct filename case for building on Linux --- source/BattletechPerformanceFix.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/BattletechPerformanceFix.csproj b/source/BattletechPerformanceFix.csproj index 4c46833..2d6cb21 100644 --- a/source/BattletechPerformanceFix.csproj +++ b/source/BattletechPerformanceFix.csproj @@ -67,7 +67,7 @@ - + @@ -120,4 +120,4 @@ yes | cp "$(TargetDir)$(TargetName).dll" "$(SolutionDir)../../Mods/BattletechPerformanceFix/$(TargetName).dll" yes | cp "$(TargetDir)$(TargetName).dll" "$(SolutionDir)../../Mods/BattletechPerformanceFix/$(TargetName).dll" - \ No newline at end of file + From f36a1ab699cc7ef410effa7c5dca0aefaa5243b7 Mon Sep 17 00:00:00 2001 From: Cole Thompson Date: Wed, 16 Dec 2020 12:46:25 -0600 Subject: [PATCH 2/6] Ignore vim .swp files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index aa4950f..4c47a94 100644 --- a/.gitignore +++ b/.gitignore @@ -267,3 +267,4 @@ __pycache__/ libs/ libs.fixed/ +*/*.swp From cf70267f4d41bf113ee912f982ca34ed8ae10df9 Mon Sep 17 00:00:00 2001 From: Cole Thompson Date: Wed, 16 Dec 2020 13:44:57 -0600 Subject: [PATCH 3/6] Add NavigationMapFilterLagFix, which saves a few seconds in modpacks with large maps --- source/BattletechPerformanceFix.csproj | 1 + source/Main.cs | 1 + source/NavigationMapFilterLagFix.cs | 63 ++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 source/NavigationMapFilterLagFix.cs diff --git a/source/BattletechPerformanceFix.csproj b/source/BattletechPerformanceFix.csproj index 2d6cb21..dd24718 100644 --- a/source/BattletechPerformanceFix.csproj +++ b/source/BattletechPerformanceFix.csproj @@ -53,6 +53,7 @@ + diff --git a/source/Main.cs b/source/Main.cs index 0231c9e..8c0785a 100644 --- a/source/Main.cs +++ b/source/Main.cs @@ -91,6 +91,7 @@ public static void Start(string modDirectory, string json) { typeof(DataLoaderGetEntryCheck), true }, { typeof(ShopTabLagFix), true }, { typeof(ContractLagFix), true }, + { typeof(NavigationMapFilterLagFix), true }, { typeof(EnableLoggingDuringLoads), true }, { typeof(ExtraLogging), true }, { typeof(ShaderDependencyOverride), true }, diff --git a/source/NavigationMapFilterLagFix.cs b/source/NavigationMapFilterLagFix.cs new file mode 100644 index 0000000..61c0c32 --- /dev/null +++ b/source/NavigationMapFilterLagFix.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.Linq; +using BattleTech.UI; +using Harmony; +using System.Reflection.Emit; +using HBS; +using static BattletechPerformanceFix.Extensions; + +namespace BattletechPerformanceFix +{ + /* Removes a redundant call for creating difficulty callouts, saves a few seconds per filter selection */ + class NavigationMapFilterLagFix : Feature + { + public void Activate() + { + var method = AccessTools.Method(typeof(SGNavigationScreen), "OnDifficultySelectionChanged"); + var transpiler = new HarmonyMethod(typeof(NavigationMapFilterLagFix), nameof(Transpiler)); + Main.harmony.Patch(method, null, null, transpiler); + + var cdc = nameof(SGNavigationScreen.CreateDifficultyCallouts); + cdc.Pre(); + cdc.Post(); + var rsi = nameof(SGNavigationScreen.RefreshSystemIndicators); + rsi.Pre(); + rsi.Post(); + } + + // FIXME remove + // TODO write a wrapper to make these quickly & easily + public static void CreateDifficultyCallouts_Pre(ref Stopwatch __state) + { __state = new Stopwatch(); __state.Start(); } + public static void CreateDifficultyCallouts_Post(ref Stopwatch __state) + { __state.Stop(); LogDebug("[PROFILE] " + __state.Elapsed + " CreateDifficultyCallouts"); } + public static void RefreshSystemIndicators_Pre(ref Stopwatch __state) + { __state = new Stopwatch(); __state.Start(); } + public static void RefreshSystemIndicators_Post(ref Stopwatch __state) + { __state.Stop(); LogDebug("[PROFILE] " + __state.Elapsed + " RefreshSystemIndicators"); } + + static IEnumerable Transpiler(IEnumerable instructions) + { + // cuts out the if/else block in CreateDifficultyCallouts() because CreateDifficultyCallouts() + // is called later by RefreshSystemIndicators() anyways just after the block + // FIXME? this technique is v fragile but we don't expect: + // - other mods modifying this chunk of IL + // - updates to the game (1.9.1 is supposedly the final release) + // but this is mostly just for test purposes anyway so YOLO + // FIXME? maybe faster to leave instructions in enumerable form & + // not convert it to a list & back + int startIndex = 7; + int endIndex = 15; + + LogInfo("Overwriting instructions in SGNavigationScreen.OnDifficultySelectionChanged()" + + " at indices " + startIndex + " through " + endIndex + " with nops"); + var codes = new List(instructions); + for(int i = startIndex; i <= endIndex; i++) { + LogSpam("overwriting index " + i + " value " + codes[i].opcode + " with nop"); + codes[i].opcode = OpCodes.Nop; + } + + return codes.AsEnumerable(); + } + } +} From a138f0d3c8205154ef8241be798bb792220914fc Mon Sep 17 00:00:00 2001 From: Cole Thompson Date: Wed, 16 Dec 2020 15:47:21 -0600 Subject: [PATCH 4/6] Use a more robust & defensive method of finding the code to remove --- source/NavigationMapFilterLagFix.cs | 52 +++++++++++++++++++---------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/source/NavigationMapFilterLagFix.cs b/source/NavigationMapFilterLagFix.cs index 61c0c32..12ae074 100644 --- a/source/NavigationMapFilterLagFix.cs +++ b/source/NavigationMapFilterLagFix.cs @@ -2,6 +2,7 @@ using System.Linq; using BattleTech.UI; using Harmony; +using System.Reflection; using System.Reflection.Emit; using HBS; using static BattletechPerformanceFix.Extensions; @@ -36,28 +37,45 @@ public static void RefreshSystemIndicators_Pre(ref Stopwatch __state) public static void RefreshSystemIndicators_Post(ref Stopwatch __state) { __state.Stop(); LogDebug("[PROFILE] " + __state.Elapsed + " RefreshSystemIndicators"); } + // cuts out the if/else block in CreateDifficultyCallouts() because CreateDifficultyCallouts() + // is called later by RefreshSystemIndicators() anyways just after the block static IEnumerable Transpiler(IEnumerable instructions) { - // cuts out the if/else block in CreateDifficultyCallouts() because CreateDifficultyCallouts() - // is called later by RefreshSystemIndicators() anyways just after the block - // FIXME? this technique is v fragile but we don't expect: - // - other mods modifying this chunk of IL - // - updates to the game (1.9.1 is supposedly the final release) - // but this is mostly just for test purposes anyway so YOLO - // FIXME? maybe faster to leave instructions in enumerable form & - // not convert it to a list & back - int startIndex = 7; - int endIndex = 15; + int startIndex = -1; + int endIndex = -1; - LogInfo("Overwriting instructions in SGNavigationScreen.OnDifficultySelectionChanged()" + - " at indices " + startIndex + " through " + endIndex + " with nops"); - var codes = new List(instructions); - for(int i = startIndex; i <= endIndex; i++) { - LogSpam("overwriting index " + i + " value " + codes[i].opcode + " with nop"); - codes[i].opcode = OpCodes.Nop; + // searches for the if block start & end points, in case some other mod is modifying this function + // (which is why we don't hardcode the indices) + var code = instructions.ToList(); + for (int i = 0; i < code.Count-1; i++) { + if (startIndex == -1) { + if (code[i].opcode == OpCodes.Ldarg_1 && code[i+1].opcode == OpCodes.Brtrue) { + startIndex = i; + } + } else { + if (code[i].opcode == OpCodes.Ldarg_1 && code[i+1].opcode == OpCodes.Call && + (code[i+1].operand as MethodInfo).Name == "CreateDifficultyCallouts") { + endIndex = i+1; + break; + } + } } - return codes.AsEnumerable(); + if (startIndex != -1 && endIndex != -1) { + LogInfo("Applying code changes for NavigationMapFilterLagFix"); + LogDebug("Overwriting instructions in SGNavigationScreen.OnDifficultySelectionChanged()" + + " at indices " + startIndex + "-" + endIndex + " with nops"); + for (int i = startIndex; i <= endIndex; i++) { + code[i].opcode = OpCodes.Nop; + } + } else { + LogError("Failed to find the code to overwrite in " + + "SGNavigationScreen.OnDifficultySelectionChanged(); no changes were made."); + LogError("NavigationMapFilterLagFix has not been applied, report this as a bug"); + } + + //foreach(CodeInstruction c in code) { LogSpam(c.opcode + " | " + c.operand); } + return code.AsEnumerable(); } } } From 4c48be4bae03cf3cd507248d02329c44a13bf346 Mon Sep 17 00:00:00 2001 From: Cole Thompson Date: Wed, 16 Dec 2020 15:53:59 -0600 Subject: [PATCH 5/6] Update README.md with NavigationMapFilterLagFix --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5ce6626..cb6c27c 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,9 @@ - Make all simgame room transitions instant. - RemovedContractsFix - This fix removes invalid contracts allowing saves to load if a user created contract was removed from the mods in use. +- NavigationMapFilterLagFix + - This fix removes some unnecessary code in the navigation map's difficulty filter selection. + - The performance gain is negligible in vanilla, but in modpacks using the entire IS map such as RT or BTA, this saves a few seconds. # Experimental patches - MDDB_TagsetQueryInChunks From 43baae1e75347f17c82a94ef5cd19287d1510f76 Mon Sep 17 00:00:00 2001 From: Cole Thompson Date: Thu, 17 Dec 2020 09:45:14 -0600 Subject: [PATCH 6/6] Cleanup --- source/NavigationMapFilterLagFix.cs | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/source/NavigationMapFilterLagFix.cs b/source/NavigationMapFilterLagFix.cs index 12ae074..b3d43ab 100644 --- a/source/NavigationMapFilterLagFix.cs +++ b/source/NavigationMapFilterLagFix.cs @@ -4,7 +4,6 @@ using Harmony; using System.Reflection; using System.Reflection.Emit; -using HBS; using static BattletechPerformanceFix.Extensions; namespace BattletechPerformanceFix @@ -17,29 +16,11 @@ public void Activate() var method = AccessTools.Method(typeof(SGNavigationScreen), "OnDifficultySelectionChanged"); var transpiler = new HarmonyMethod(typeof(NavigationMapFilterLagFix), nameof(Transpiler)); Main.harmony.Patch(method, null, null, transpiler); - - var cdc = nameof(SGNavigationScreen.CreateDifficultyCallouts); - cdc.Pre(); - cdc.Post(); - var rsi = nameof(SGNavigationScreen.RefreshSystemIndicators); - rsi.Pre(); - rsi.Post(); } - // FIXME remove - // TODO write a wrapper to make these quickly & easily - public static void CreateDifficultyCallouts_Pre(ref Stopwatch __state) - { __state = new Stopwatch(); __state.Start(); } - public static void CreateDifficultyCallouts_Post(ref Stopwatch __state) - { __state.Stop(); LogDebug("[PROFILE] " + __state.Elapsed + " CreateDifficultyCallouts"); } - public static void RefreshSystemIndicators_Pre(ref Stopwatch __state) - { __state = new Stopwatch(); __state.Start(); } - public static void RefreshSystemIndicators_Post(ref Stopwatch __state) - { __state.Stop(); LogDebug("[PROFILE] " + __state.Elapsed + " RefreshSystemIndicators"); } - - // cuts out the if/else block in CreateDifficultyCallouts() because CreateDifficultyCallouts() + // cuts out the if/else block in OnDifficultySelectionChanged() because CreateDifficultyCallouts() // is called later by RefreshSystemIndicators() anyways just after the block - static IEnumerable Transpiler(IEnumerable instructions) + private static IEnumerable Transpiler(IEnumerable instructions) { int startIndex = -1; int endIndex = -1; @@ -62,7 +43,6 @@ static IEnumerable Transpiler(IEnumerable inst } if (startIndex != -1 && endIndex != -1) { - LogInfo("Applying code changes for NavigationMapFilterLagFix"); LogDebug("Overwriting instructions in SGNavigationScreen.OnDifficultySelectionChanged()" + " at indices " + startIndex + "-" + endIndex + " with nops"); for (int i = startIndex; i <= endIndex; i++) { @@ -74,7 +54,6 @@ static IEnumerable Transpiler(IEnumerable inst LogError("NavigationMapFilterLagFix has not been applied, report this as a bug"); } - //foreach(CodeInstruction c in code) { LogSpam(c.opcode + " | " + c.operand); } return code.AsEnumerable(); } }