diff --git a/GameData/KSPCommunityFixes/Settings.cfg b/GameData/KSPCommunityFixes/Settings.cfg index d5ceb7d..9ce767e 100644 --- a/GameData/KSPCommunityFixes/Settings.cfg +++ b/GameData/KSPCommunityFixes/Settings.cfg @@ -222,6 +222,9 @@ KSP_COMMUNITY_FIXES // cargo bays, wrong vessel size being reported, etc... PartBoundsIgnoreDisabledTransforms = true + // Fix loading of drag cubes without a name failing with an IndexOutOfRangeException + DragCubeLoadException = true + // ########################## // Obsolete bugfixes // ########################## diff --git a/KSPCommunityFixes/BugFixes/DragCubeLoadException.cs b/KSPCommunityFixes/BugFixes/DragCubeLoadException.cs new file mode 100644 index 0000000..12d4c02 --- /dev/null +++ b/KSPCommunityFixes/BugFixes/DragCubeLoadException.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Reflection.Emit; +using HarmonyLib; + +namespace KSPCommunityFixes.BugFixes +{ +class DragCubeLoadException : BasePatch +{ + // The name field in a DRAG_CUBE config node is supposed to be optional. However, when the name is not included in + // the list of values, an IndexOutOfRangeException is thrown. + // + // Even when not loaded from a config file, when the name field on a DragCube object is the empty string (for + // example, when it is default-constructed in code) it is not included in the string returned by + // DragCube.SaveToString(); this causes a problem when the FlightIntegrator.Setup() method uses this string to + // create a clone of a drag cube. + + protected override Version VersionMin => new Version(1, 8, 0); + + protected override void ApplyPatches(List patches) + { + patches.Add( + new PatchInfo( + PatchMethodType.Transpiler, + AccessTools.Method(typeof(DragCube), nameof(DragCube.Load)), + this)); + } + + static IEnumerable DragCube_Load_Transpiler(IEnumerable instructions) + { + // The first instructions in DragCube.Load(string[] data) are: + // - Check if it has the correct length (24 or 25), logging an error and returning if this is not the case + // - Check if the length is 12; if it is not, take the first field as the name and skip it. + // That last check should have been against a length of 24 instead; this patch replaces the first occurrence of + // ldc.i4.s 12 in the code by ldc.i4.s 24. + + bool found = false; + foreach (var instruction in instructions) + { + if (!found && instruction.Is(OpCodes.Ldc_I4_S, (sbyte)12)) + { + found = true; + instruction.operand = (sbyte)24; + } + yield return instruction; + } + } +} +} diff --git a/KSPCommunityFixes/KSPCommunityFixes.csproj b/KSPCommunityFixes/KSPCommunityFixes.csproj index 5ccec49..1d962f8 100644 --- a/KSPCommunityFixes/KSPCommunityFixes.csproj +++ b/KSPCommunityFixes/KSPCommunityFixes.csproj @@ -104,6 +104,7 @@ + diff --git a/README.md b/README.md index f6d141d..5d5de08 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ User options are available from the "ESC" in-game settings menu :