From a2fdef4c38b6aeb066b7f23c212e357eedeacb3d Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Sun, 5 Jul 2020 23:22:43 -0700 Subject: [PATCH 01/22] Don't overwrite other fatal messages --- ModuleManager/MMPatchRunner.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ModuleManager/MMPatchRunner.cs b/ModuleManager/MMPatchRunner.cs index 739ecd82..b812ceed 100644 --- a/ModuleManager/MMPatchRunner.cs +++ b/ModuleManager/MMPatchRunner.cs @@ -80,12 +80,14 @@ public IEnumerator Run() { kspLogger.Exception("The patching thread threw an exception", patchingThreadStatus.Exception); FatalErrorHandler.HandleFatalError("The patching thread threw an exception"); + yield break; } if (loggingThreadStatus.IsExitedWithError) { kspLogger.Exception("The logging thread threw an exception", loggingThreadStatus.Exception); FatalErrorHandler.HandleFatalError("The logging thread threw an exception"); + yield break; } if (databaseConfigs == null) From c4ad2c3dd5defcdd37154831be4fa7040d3d1616 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Sun, 5 Jul 2020 23:23:45 -0700 Subject: [PATCH 02/22] Fix :LAST when mod doesn't exist Per the original feature design (#96) it should still run --- ModuleManager/PatchList.cs | 13 +++++++++---- ModuleManagerTests/PatchListTest.cs | 16 +++++++++++----- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/ModuleManager/PatchList.cs b/ModuleManager/PatchList.cs index 9716de22..e9193f74 100644 --- a/ModuleManager/PatchList.cs +++ b/ModuleManager/PatchList.cs @@ -76,6 +76,7 @@ public ModPassCollection(IEnumerable modList) private readonly Pass finalPatches = new Pass(":FINAL"); private readonly ModPassCollection modPasses; + private readonly SortedDictionary lastPasses = new SortedDictionary(StringComparer.InvariantCultureIgnoreCase); public PatchList(IEnumerable modList, IEnumerable patches, IPatchProgress progress) { @@ -114,8 +115,12 @@ public PatchList(IEnumerable modList, IEnumerable patches, IPatc } else if (patch.PassSpecifier is LastPassSpecifier lastPassSpecifier) { - EnsureMod(lastPassSpecifier.mod); - modPasses[lastPassSpecifier.mod].AddLastPatch(patch); + if (!lastPasses.TryGetValue(lastPassSpecifier.mod, out Pass thisPass)) + { + thisPass = new Pass($":LAST[{lastPassSpecifier.mod.ToUpperInvariant()}]"); + lastPasses.Add(lastPassSpecifier.mod.ToLowerInvariant(), thisPass); + } + thisPass.Add(patch); } else if (patch.PassSpecifier is FinalPassSpecifier) { @@ -143,9 +148,9 @@ public IEnumerator GetEnumerator() yield return modPass.afterPass; } - foreach (ModPass modPass in modPasses) + foreach (Pass lastPass in lastPasses.Values) { - yield return modPass.lastPass; + yield return lastPass; } yield return finalPatches; diff --git a/ModuleManagerTests/PatchListTest.cs b/ModuleManagerTests/PatchListTest.cs index 09b1c1dc..4dc5c751 100644 --- a/ModuleManagerTests/PatchListTest.cs +++ b/ModuleManagerTests/PatchListTest.cs @@ -113,6 +113,7 @@ public void Test__Lifecycle() Substitute.For(), Substitute.For(), Substitute.For(), + Substitute.For(), }; UrlDir.UrlConfig urlConfig = UrlBuilder.CreateConfig("abc/def", new ConfigNode("NODE")); @@ -139,8 +140,9 @@ public void Test__Lifecycle() patches[19].PassSpecifier.Returns(new AfterPassSpecifier("MOD2", urlConfig)); patches[20].PassSpecifier.Returns(new LastPassSpecifier("mod2")); patches[21].PassSpecifier.Returns(new LastPassSpecifier("MOD2")); - patches[22].PassSpecifier.Returns(new FinalPassSpecifier()); + patches[22].PassSpecifier.Returns(new LastPassSpecifier("mod3")); patches[23].PassSpecifier.Returns(new FinalPassSpecifier()); + patches[24].PassSpecifier.Returns(new FinalPassSpecifier()); patches[00].CountsAsPatch.Returns(false); patches[01].CountsAsPatch.Returns(false); @@ -166,6 +168,7 @@ public void Test__Lifecycle() patches[21].CountsAsPatch.Returns(true); patches[22].CountsAsPatch.Returns(true); patches[23].CountsAsPatch.Returns(true); + patches[24].CountsAsPatch.Returns(true); IPatchProgress progress = Substitute.For(); @@ -173,7 +176,7 @@ public void Test__Lifecycle() IPass[] passes = patchList.ToArray(); - Assert.Equal(12, passes.Length); + Assert.Equal(13, passes.Length); Assert.Equal(":INSERT (initial)", passes[0].Name); Assert.Equal(new[] { patches[0], patches[1] }, passes[0]); @@ -208,10 +211,13 @@ public void Test__Lifecycle() Assert.Equal(":LAST[MOD2]", passes[10].Name); Assert.Equal(new[] { patches[20], patches[21] }, passes[10]); - Assert.Equal(":FINAL", passes[11].Name); - Assert.Equal(new[] { patches[22], patches[23] }, passes[11]); + Assert.Equal(":LAST[MOD3]", passes[11].Name); + Assert.Equal(new[] { patches[22] }, passes[11]); + + Assert.Equal(":FINAL", passes[12].Name); + Assert.Equal(new[] { patches[23], patches[24] }, passes[12]); - progress.Received(22).PatchAdded(); + progress.Received(23).PatchAdded(); } } } From 8a95d3709f0dd651deb1fc8294007b847e562045 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Mon, 6 Jul 2020 22:55:39 -0700 Subject: [PATCH 03/22] PatchList handles sorting consistently eliminates private class that mostly just passed methods through --- ModuleManager/PatchList.cs | 46 ++++++++------------------------------ 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/ModuleManager/PatchList.cs b/ModuleManager/PatchList.cs index e9193f74..f97c8b49 100644 --- a/ModuleManager/PatchList.cs +++ b/ModuleManager/PatchList.cs @@ -37,53 +37,25 @@ public ModPass(string name) public void AddLastPatch(IPatch patch) => lastPass.Add(patch ?? throw new ArgumentNullException(nameof(patch))); } - private class ModPassCollection : IEnumerable - { - private readonly ModPass[] passesArray; - private readonly Dictionary passesDict; - - public ModPassCollection(IEnumerable modList) - { - int count = modList.Count(); - passesArray = new ModPass[count]; - passesDict = new Dictionary(count); - - int i = 0; - foreach (string mod in modList) - { - ModPass pass = new ModPass(mod); - passesArray[i] = pass; - passesDict.Add(mod.ToLowerInvariant(), pass); - i++; - } - } - - public ModPass this[string name] => passesDict[name.ToLowerInvariant()]; - public ModPass this[int index] => passesArray[index]; - - public bool HasMod(string name) => passesDict.ContainsKey(name.ToLowerInvariant()); - - public int Count => passesArray.Length; - - public ArrayEnumerator GetEnumerator() => new ArrayEnumerator(passesArray); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - private readonly Pass insertPatches = new Pass(":INSERT (initial)"); private readonly Pass firstPatches = new Pass(":FIRST"); private readonly Pass legacyPatches = new Pass(":LEGACY (default)"); private readonly Pass finalPatches = new Pass(":FINAL"); - private readonly ModPassCollection modPasses; + private readonly SortedDictionary modPasses = new SortedDictionary(StringComparer.InvariantCultureIgnoreCase); private readonly SortedDictionary lastPasses = new SortedDictionary(StringComparer.InvariantCultureIgnoreCase); public PatchList(IEnumerable modList, IEnumerable patches, IPatchProgress progress) { - modPasses = new ModPassCollection(modList ?? throw new ArgumentNullException(nameof(modList))); + if (modList == null) throw new ArgumentNullException(nameof(modList)); if (patches == null) throw new ArgumentNullException(nameof(patches)); if (progress == null) throw new ArgumentNullException(nameof(progress)); + foreach (string mod in modList) + { + modPasses.Add(mod, new ModPass(mod)); + } + foreach (IPatch patch in patches) { if (patch.PassSpecifier is InsertPassSpecifier) @@ -141,7 +113,7 @@ public IEnumerator GetEnumerator() yield return firstPatches; yield return legacyPatches; - foreach (ModPass modPass in modPasses) + foreach (ModPass modPass in modPasses.Values) { yield return modPass.beforePass; yield return modPass.forPass; @@ -162,7 +134,7 @@ private void EnsureMod(string mod) { if (mod == null) throw new ArgumentNullException(nameof(mod)); if (mod == string.Empty) throw new ArgumentException("can't be empty", nameof(mod)); - if (!modPasses.HasMod(mod)) throw new KeyNotFoundException($"Mod '{mod}' not found"); + if (!modPasses.ContainsKey(mod)) throw new KeyNotFoundException($"Mod '{mod}' not found"); } } } From 5168b5c743371838de869745081fda8849c86eb0 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Mon, 6 Jul 2020 23:52:39 -0700 Subject: [PATCH 04/22] Address some messages Do some dependency in jection on InterceptLogHandler, no need to hold onto a reference to it as Unity will Remove paramter checks in StreamLogger as StreamWriter does the same checks Ibut keep basic tests for them) --- ModuleManager/Cats/CatAnimator.cs | 4 +++- ModuleManager/Cats/CatManager.cs | 2 +- ModuleManager/Cats/CatMover.cs | 8 ++++--- ModuleManager/Cats/CatOrbiter.cs | 8 ++++--- ModuleManager/Collections/ImmutableStack.cs | 2 +- .../ExceptionIntercept/InterceptLogHandler.cs | 5 ++-- ModuleManager/Extensions/StringExtensions.cs | 2 +- ModuleManager/Fix16.cs | 2 ++ ModuleManager/Logging/StreamLogger.cs | 3 --- ModuleManager/Logging/UnityLogger.cs | 2 +- ModuleManager/MMPatchLoader.cs | 2 -- ModuleManager/MMPatchRunner.cs | 13 ++++------- ModuleManager/ModuleManager.cs | 6 ++--- ModuleManager/NeedsChecker.cs | 2 ++ ModuleManager/NodeMatcher.cs | 8 +++---- ModuleManager/PatchExtractor.cs | 2 ++ ModuleManager/PatchList.cs | 2 -- ModuleManager/Patches/PatchCompiler.cs | 23 ++++++------------- ModuleManager/PostPatchLoader.cs | 2 ++ ModuleManager/Progress/PatchProgress.cs | 2 +- ModuleManager/Threading/TaskStatus.cs | 22 ++++++++---------- ModuleManager/Threading/TaskStatusWrapper.cs | 2 +- ModuleManager/Utils/FileUtils.cs | 12 +++------- .../Collections/MessageQueueTest.cs | 2 +- .../Extensions/IBasicLoggerExtensionsTest.cs | 8 +------ .../Logging/PrefixLoggerTest.cs | 5 ++-- ModuleManagerTests/Logging/QueueLoggerTest.cs | 5 ++-- .../Logging/StreamLoggerTest.cs | 9 ++------ ModuleManagerTests/Logging/UnityLoggerTest.cs | 5 ++-- ModuleManagerTests/NeedsCheckerTest.cs | 11 +++------ ModuleManagerTests/PassTest.cs | 8 ------- ModuleManagerTests/PatchExtractorTest.cs | 6 ----- .../Progress/PatchProgressTest.cs | 6 ++--- 33 files changed, 73 insertions(+), 128 deletions(-) diff --git a/ModuleManager/Cats/CatAnimator.cs b/ModuleManager/Cats/CatAnimator.cs index ed5b2c70..7806d4aa 100644 --- a/ModuleManager/Cats/CatAnimator.cs +++ b/ModuleManager/Cats/CatAnimator.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Diagnostics.CodeAnalysis; using UnityEngine; namespace ModuleManager.Cats @@ -12,9 +13,10 @@ class CatAnimator : MonoBehaviour private SpriteRenderer spriteRenderer; private int spriteIdx; + [SuppressMessage("CodeQuality", "IDE0051", Justification = "Called by Unity")] void Start() { - spriteRenderer = this.GetComponent(); + spriteRenderer = GetComponent(); spriteRenderer.sortingOrder = 3; StartCoroutine(Animate()); } diff --git a/ModuleManager/Cats/CatManager.cs b/ModuleManager/Cats/CatManager.cs index 744a0ca8..05f671d6 100644 --- a/ModuleManager/Cats/CatManager.cs +++ b/ModuleManager/Cats/CatManager.cs @@ -14,7 +14,7 @@ public static void LaunchCat() InitCats(); GameObject cat = LaunchCat(scale); - CatMover catMover = cat.AddComponent(); + cat.AddComponent(); } public static void LaunchCats() diff --git a/ModuleManager/Cats/CatMover.cs b/ModuleManager/Cats/CatMover.cs index 2e37ac9a..d97a3f7c 100644 --- a/ModuleManager/Cats/CatMover.cs +++ b/ModuleManager/Cats/CatMover.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Diagnostics.CodeAnalysis; using UnityEngine; namespace ModuleManager.Cats @@ -24,12 +24,13 @@ public class CatMover : MonoBehaviour private bool clearTrail = false; // Use this for initialization + [SuppressMessage("CodeQuality", "IDE0051", Justification = "Called by Unity")] void Start() { - trail = this.GetComponent(); + trail = GetComponent(); trail.sortingOrder = 2; - spriteRenderer = this.GetComponent(); + spriteRenderer = GetComponent(); offsetY = Mathf.FloorToInt(0.2f * Screen.height); @@ -41,6 +42,7 @@ void Start() clearTrail = true; } + [SuppressMessage("CodeQuality", "IDE0051", Justification = "Called by Unity")] void Update() { if (trail.time <= 0f) diff --git a/ModuleManager/Cats/CatOrbiter.cs b/ModuleManager/Cats/CatOrbiter.cs index 17621c6f..34b1f6e8 100644 --- a/ModuleManager/Cats/CatOrbiter.cs +++ b/ModuleManager/Cats/CatOrbiter.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using KSP.UI; using UnityEngine; using Random = UnityEngine.Random; @@ -8,7 +9,7 @@ namespace ModuleManager.Cats { class CatOrbiter : MonoBehaviour { - private static List orbiters = new List(); + private static readonly List orbiters = new List(); private static CatOrbiter sun; @@ -20,7 +21,7 @@ class CatOrbiter : MonoBehaviour private Vector2d force; private float scale = 1; - private double G = 6.67408E-11; + private const double G = 6.67408E-11; public double Mass { @@ -113,13 +114,14 @@ private void DoForces() } } - + [SuppressMessage("CodeQuality", "IDE0051", Justification = "Called by Unity")] void OnDestroy() { orbiters.Remove(this); TimingManager.FixedUpdateRemove(TimingManager.TimingStage.Earlyish, DoForces); } + [SuppressMessage("CodeQuality", "IDE0051", Justification = "Called by Unity")] void FixedUpdate() { //if (this == sun) diff --git a/ModuleManager/Collections/ImmutableStack.cs b/ModuleManager/Collections/ImmutableStack.cs index 5d181567..d710c423 100644 --- a/ModuleManager/Collections/ImmutableStack.cs +++ b/ModuleManager/Collections/ImmutableStack.cs @@ -8,7 +8,7 @@ public class ImmutableStack : IEnumerable { public struct Enumerator : IEnumerator { - private ImmutableStack head; + private readonly ImmutableStack head; private ImmutableStack currentStack; public Enumerator(ImmutableStack stack) diff --git a/ModuleManager/ExceptionIntercept/InterceptLogHandler.cs b/ModuleManager/ExceptionIntercept/InterceptLogHandler.cs index 6cd3dcd0..471b1fa8 100644 --- a/ModuleManager/ExceptionIntercept/InterceptLogHandler.cs +++ b/ModuleManager/ExceptionIntercept/InterceptLogHandler.cs @@ -16,10 +16,9 @@ class InterceptLogHandler : ILogHandler public static string Warnings { get; private set; } = ""; - public InterceptLogHandler() + public InterceptLogHandler(ILogHandler baseLogHandler) { - baseLogHandler = Debug.unityLogger.logHandler; - Debug.unityLogger.logHandler = this; + this.baseLogHandler = baseLogHandler ?? throw new ArgumentNullException(nameof(baseLogHandler)); gamePathLength = Path.GetFullPath(KSPUtil.ApplicationRootPath).Length; } diff --git a/ModuleManager/Extensions/StringExtensions.cs b/ModuleManager/Extensions/StringExtensions.cs index c4190045..b9136e30 100644 --- a/ModuleManager/Extensions/StringExtensions.cs +++ b/ModuleManager/Extensions/StringExtensions.cs @@ -18,7 +18,7 @@ public static bool IsBracketBalanced(this string s) return level == 0; } - private static Regex whitespaceRegex = new Regex(@"\s+"); + private static readonly Regex whitespaceRegex = new Regex(@"\s+"); public static string RemoveWS(this string withWhite) { diff --git a/ModuleManager/Fix16.cs b/ModuleManager/Fix16.cs index ab20e6ae..b567eb56 100644 --- a/ModuleManager/Fix16.cs +++ b/ModuleManager/Fix16.cs @@ -1,9 +1,11 @@ using System.Collections; +using System.Diagnostics.CodeAnalysis; namespace ModuleManager { class Fix16 : LoadingSystem { + [SuppressMessage("CodeQuality", "IDE0051", Justification = "Called by Unity")] private void Awake() { if (Instance != null) diff --git a/ModuleManager/Logging/StreamLogger.cs b/ModuleManager/Logging/StreamLogger.cs index 74115d3e..d020f64c 100644 --- a/ModuleManager/Logging/StreamLogger.cs +++ b/ModuleManager/Logging/StreamLogger.cs @@ -5,14 +5,11 @@ namespace ModuleManager.Logging { public sealed class StreamLogger : IBasicLogger, IDisposable { - private readonly Stream stream; private readonly StreamWriter streamWriter; private bool disposed = false; public StreamLogger(Stream stream) { - this.stream = stream ?? throw new ArgumentNullException(nameof(stream)); - if (!stream.CanWrite) throw new ArgumentException("must be writable", nameof(stream)); streamWriter = new StreamWriter(stream); } diff --git a/ModuleManager/Logging/UnityLogger.cs b/ModuleManager/Logging/UnityLogger.cs index b31c1003..d51063c4 100644 --- a/ModuleManager/Logging/UnityLogger.cs +++ b/ModuleManager/Logging/UnityLogger.cs @@ -5,7 +5,7 @@ namespace ModuleManager.Logging { public class UnityLogger : IBasicLogger { - private ILogger logger; + private readonly ILogger logger; public UnityLogger(ILogger logger) { diff --git a/ModuleManager/MMPatchLoader.cs b/ModuleManager/MMPatchLoader.cs index 1cffe055..d90e29a1 100644 --- a/ModuleManager/MMPatchLoader.cs +++ b/ModuleManager/MMPatchLoader.cs @@ -8,8 +8,6 @@ using System.Reflection; using System.Text; using System.Text.RegularExpressions; -using UnityEngine; -using Debug = UnityEngine.Debug; using ModuleManager.Collections; using ModuleManager.Logging; diff --git a/ModuleManager/MMPatchRunner.cs b/ModuleManager/MMPatchRunner.cs index b812ceed..6c3d63a0 100644 --- a/ModuleManager/MMPatchRunner.cs +++ b/ModuleManager/MMPatchRunner.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.Generic; using System.IO; -using UnityEngine; using ModuleManager.Collections; using ModuleManager.Extensions; using ModuleManager.Logging; @@ -14,8 +13,6 @@ namespace ModuleManager { public class MMPatchRunner { - private const float TIME_TO_WAIT_FOR_LOGS = 0.05f; - private readonly IBasicLogger kspLogger; public string Status { get; private set; } = ""; @@ -38,12 +35,10 @@ public IEnumerator Run() QueueLogRunner logRunner = new QueueLogRunner(mmLogQueue); ITaskStatus loggingThreadStatus = BackgroundTask.Start(delegate { - using (StreamLogger streamLogger = new StreamLogger(new FileStream(logPath, FileMode.Create))) - { - streamLogger.Info("Log started at " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); - logRunner.Run(streamLogger); - streamLogger.Info("Done!"); - } + using StreamLogger streamLogger = new StreamLogger(new FileStream(logPath, FileMode.Create)); + streamLogger.Info("Log started at " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); + logRunner.Run(streamLogger); + streamLogger.Info("Done!"); }); // Wait for game database to be initialized for the 2nd time and wait for any plugins to initialize diff --git a/ModuleManager/ModuleManager.cs b/ModuleManager/ModuleManager.cs index 361cb540..dd5e04e5 100644 --- a/ModuleManager/ModuleManager.cs +++ b/ModuleManager/ModuleManager.cs @@ -38,8 +38,6 @@ public class ModuleManager : MonoBehaviour private MMPatchRunner patchRunner; - private InterceptLogHandler interceptLogHandler; - #endregion state private static bool loadedInScene; @@ -80,8 +78,8 @@ internal void Awake() } totalTime.Start(); - - interceptLogHandler = new InterceptLogHandler(); + + Debug.unityLogger.logHandler = new InterceptLogHandler(Debug.unityLogger.logHandler); // Allow loading the background in the loading screen Application.runInBackground = true; diff --git a/ModuleManager/NeedsChecker.cs b/ModuleManager/NeedsChecker.cs index 7e452642..94f2ad29 100644 --- a/ModuleManager/NeedsChecker.cs +++ b/ModuleManager/NeedsChecker.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using ModuleManager.Extensions; using ModuleManager.Logging; @@ -20,6 +21,7 @@ public class NeedsChecker : INeedsChecker private readonly IEnumerable mods; private readonly UrlDir gameData; private readonly IPatchProgress progress; + [SuppressMessage("CodeQuality", "IDE0052", Justification = "Reserved for future use")] private readonly IBasicLogger logger; public NeedsChecker(IEnumerable mods, UrlDir gameData, IPatchProgress progress, IBasicLogger logger) diff --git a/ModuleManager/NodeMatcher.cs b/ModuleManager/NodeMatcher.cs index 5c3a59ca..8777de97 100644 --- a/ModuleManager/NodeMatcher.cs +++ b/ModuleManager/NodeMatcher.cs @@ -10,11 +10,9 @@ public interface INodeMatcher public class NodeMatcher : INodeMatcher { - private static readonly char[] sep = { '[', ']' }; - - private string type; - private string[] namePatterns = null; - private string constraints = ""; + private readonly string type; + private readonly string[] namePatterns = null; + private readonly string constraints = ""; public NodeMatcher(string type, string name, string constraints) { diff --git a/ModuleManager/PatchExtractor.cs b/ModuleManager/PatchExtractor.cs index cf476a64..6c8765f4 100644 --- a/ModuleManager/PatchExtractor.cs +++ b/ModuleManager/PatchExtractor.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using ModuleManager.Extensions; using ModuleManager.Logging; using ModuleManager.Patches; @@ -10,6 +11,7 @@ namespace ModuleManager public class PatchExtractor { private readonly IPatchProgress progress; + [SuppressMessage("CodeQuality", "IDE0052", Justification = "Reserved for future use")] private readonly IBasicLogger logger; private readonly INeedsChecker needsChecker; private readonly ITagListParser tagListParser; diff --git a/ModuleManager/PatchList.cs b/ModuleManager/PatchList.cs index f97c8b49..d3990540 100644 --- a/ModuleManager/PatchList.cs +++ b/ModuleManager/PatchList.cs @@ -1,8 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; -using ModuleManager.Collections; using ModuleManager.Patches; using ModuleManager.Patches.PassSpecifiers; using ModuleManager.Progress; diff --git a/ModuleManager/Patches/PatchCompiler.cs b/ModuleManager/Patches/PatchCompiler.cs index 67387372..6c7e7f30 100644 --- a/ModuleManager/Patches/PatchCompiler.cs +++ b/ModuleManager/Patches/PatchCompiler.cs @@ -13,23 +13,14 @@ public IPatch CompilePatch(ProtoPatch protoPatch) { if (protoPatch == null) throw new ArgumentNullException(nameof(protoPatch)); - switch (protoPatch.command) + return protoPatch.command switch { - case Command.Insert: - return new InsertPatch(protoPatch.urlConfig, protoPatch.nodeType, protoPatch.passSpecifier); - - case Command.Edit: - return new EditPatch(protoPatch.urlConfig, new NodeMatcher(protoPatch.nodeType, protoPatch.nodeName, protoPatch.has), protoPatch.passSpecifier); - - case Command.Copy: - return new CopyPatch(protoPatch.urlConfig, new NodeMatcher(protoPatch.nodeType, protoPatch.nodeName, protoPatch.has), protoPatch.passSpecifier); - - case Command.Delete: - return new DeletePatch(protoPatch.urlConfig, new NodeMatcher(protoPatch.nodeType, protoPatch.nodeName, protoPatch.has), protoPatch.passSpecifier); - - default: - throw new ArgumentException("has an invalid command for a root node: " + protoPatch.command, nameof(protoPatch)); - } + Command.Insert => new InsertPatch(protoPatch.urlConfig, protoPatch.nodeType, protoPatch.passSpecifier), + Command.Edit => new EditPatch(protoPatch.urlConfig, new NodeMatcher(protoPatch.nodeType, protoPatch.nodeName, protoPatch.has), protoPatch.passSpecifier), + Command.Copy => new CopyPatch(protoPatch.urlConfig, new NodeMatcher(protoPatch.nodeType, protoPatch.nodeName, protoPatch.has), protoPatch.passSpecifier), + Command.Delete => new DeletePatch(protoPatch.urlConfig, new NodeMatcher(protoPatch.nodeType, protoPatch.nodeName, protoPatch.has), protoPatch.passSpecifier), + _ => throw new ArgumentException("has an invalid command for a root node: " + protoPatch.command, nameof(protoPatch)), + }; } } } diff --git a/ModuleManager/PostPatchLoader.cs b/ModuleManager/PostPatchLoader.cs index f92f1fad..619f09d0 100644 --- a/ModuleManager/PostPatchLoader.cs +++ b/ModuleManager/PostPatchLoader.cs @@ -9,6 +9,7 @@ using ModuleManager.Logging; using static ModuleManager.FilePathRepository; +using System.Diagnostics.CodeAnalysis; namespace ModuleManager { @@ -34,6 +35,7 @@ public static void AddPostPatchCallback(ModuleManagerPostPatchCallback callback) postPatchCallbacks.Add(callback); } + [SuppressMessage("CodeQuality", "IDE0051", Justification = "Called by Unity")] private void Awake() { if (Instance != null) diff --git a/ModuleManager/Progress/PatchProgress.cs b/ModuleManager/Progress/PatchProgress.cs index 3cebf994..61fd0d33 100644 --- a/ModuleManager/Progress/PatchProgress.cs +++ b/ModuleManager/Progress/PatchProgress.cs @@ -8,7 +8,7 @@ public class PatchProgress : IPatchProgress { public ProgressCounter Counter { get; private set; } - private IBasicLogger logger; + private readonly IBasicLogger logger; public float ProgressFraction { diff --git a/ModuleManager/Threading/TaskStatus.cs b/ModuleManager/Threading/TaskStatus.cs index 92f8c237..1d2c6b67 100644 --- a/ModuleManager/Threading/TaskStatus.cs +++ b/ModuleManager/Threading/TaskStatus.cs @@ -4,12 +4,10 @@ namespace ModuleManager.Threading { public class TaskStatus : ITaskStatus { - private bool isRunning = true; - private Exception exception = null; - private object lockObject = new object(); + private readonly object lockObject = new object(); - public bool IsRunning => isRunning; - public Exception Exception => exception; + public bool IsRunning { get; private set; } = true; + public Exception Exception { get; private set; } = null; public bool IsFinished { @@ -17,7 +15,7 @@ public bool IsFinished { lock (lockObject) { - return !isRunning && exception == null; + return !IsRunning && Exception == null; } } } @@ -28,7 +26,7 @@ public bool IsExitedWithError { lock (lockObject) { - return !isRunning && exception != null; + return !IsRunning && Exception != null; } } } @@ -37,8 +35,8 @@ public void Finished() { lock (lockObject) { - if (!isRunning) throw new InvalidOperationException("Task is not running"); - isRunning = false; + if (!IsRunning) throw new InvalidOperationException("Task is not running"); + IsRunning = false; } } @@ -46,9 +44,9 @@ public void Error(Exception exception) { lock(lockObject) { - if (!isRunning) throw new InvalidOperationException("Task is not running"); - this.exception = exception ?? throw new ArgumentNullException(nameof(exception)); - isRunning = false; + if (!IsRunning) throw new InvalidOperationException("Task is not running"); + this.Exception = exception ?? throw new ArgumentNullException(nameof(exception)); + IsRunning = false; } } } diff --git a/ModuleManager/Threading/TaskStatusWrapper.cs b/ModuleManager/Threading/TaskStatusWrapper.cs index eff24f78..1750633c 100644 --- a/ModuleManager/Threading/TaskStatusWrapper.cs +++ b/ModuleManager/Threading/TaskStatusWrapper.cs @@ -4,7 +4,7 @@ namespace ModuleManager.Threading { public class TaskStatusWrapper : ITaskStatus { - private ITaskStatus inner; + private readonly ITaskStatus inner; public TaskStatusWrapper(ITaskStatus inner) { diff --git a/ModuleManager/Utils/FileUtils.cs b/ModuleManager/Utils/FileUtils.cs index e069e14c..818d3cc6 100644 --- a/ModuleManager/Utils/FileUtils.cs +++ b/ModuleManager/Utils/FileUtils.cs @@ -11,15 +11,9 @@ public static string FileSHA(string filename) { if (!File.Exists(filename)) throw new FileNotFoundException("File does not exist", filename); - byte[] data = null; - - using (SHA256 sha = SHA256.Create()) - { - using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read)) - { - data = sha.ComputeHash(fs); - } - } + using SHA256 sha = SHA256.Create(); + using FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read); + byte[] data = sha.ComputeHash(fs); return data.ToHex(); } diff --git a/ModuleManagerTests/Collections/MessageQueueTest.cs b/ModuleManagerTests/Collections/MessageQueueTest.cs index 83bf1217..baf35d20 100644 --- a/ModuleManagerTests/Collections/MessageQueueTest.cs +++ b/ModuleManagerTests/Collections/MessageQueueTest.cs @@ -8,7 +8,7 @@ public class MessageQueueTest { private class TestClass { } - private MessageQueue queue = new MessageQueue(); + private readonly MessageQueue queue = new MessageQueue(); [Fact] public void Test__Empty() diff --git a/ModuleManagerTests/Extensions/IBasicLoggerExtensionsTest.cs b/ModuleManagerTests/Extensions/IBasicLoggerExtensionsTest.cs index f6c1fad7..74e82d88 100644 --- a/ModuleManagerTests/Extensions/IBasicLoggerExtensionsTest.cs +++ b/ModuleManagerTests/Extensions/IBasicLoggerExtensionsTest.cs @@ -1,7 +1,6 @@ using System; using Xunit; using NSubstitute; -using UnityEngine; using ModuleManager.Logging; using ModuleManager.Extensions; @@ -9,12 +8,7 @@ namespace ModuleManagerTests.Extensions { public class IBasicLoggerExtensionsTest { - private IBasicLogger logger; - - public IBasicLoggerExtensionsTest() - { - logger = Substitute.For(); - } + private readonly IBasicLogger logger = Substitute.For(); [Fact] public void TestInfo() diff --git a/ModuleManagerTests/Logging/PrefixLoggerTest.cs b/ModuleManagerTests/Logging/PrefixLoggerTest.cs index 28a82edc..5aaf0113 100644 --- a/ModuleManagerTests/Logging/PrefixLoggerTest.cs +++ b/ModuleManagerTests/Logging/PrefixLoggerTest.cs @@ -8,12 +8,11 @@ namespace ModuleManagerTests.Logging { public class PrefixLoggerTest { - private IBasicLogger innerLogger; - private PrefixLogger logger; + private readonly IBasicLogger innerLogger = Substitute.For(); + private readonly PrefixLogger logger; public PrefixLoggerTest() { - innerLogger = Substitute.For(); logger = new PrefixLogger("MyMod", innerLogger); } diff --git a/ModuleManagerTests/Logging/QueueLoggerTest.cs b/ModuleManagerTests/Logging/QueueLoggerTest.cs index dc8a1dfd..25e1abbe 100644 --- a/ModuleManagerTests/Logging/QueueLoggerTest.cs +++ b/ModuleManagerTests/Logging/QueueLoggerTest.cs @@ -8,12 +8,11 @@ namespace ModuleManagerTests.Logging { public class QueueLoggerTest { - private IMessageQueue queue; - private QueueLogger logger; + private readonly IMessageQueue queue = Substitute.For>(); + private readonly QueueLogger logger; public QueueLoggerTest() { - queue = Substitute.For>(); logger = new QueueLogger(queue); } diff --git a/ModuleManagerTests/Logging/StreamLoggerTest.cs b/ModuleManagerTests/Logging/StreamLoggerTest.cs index bc613038..296eeac2 100644 --- a/ModuleManagerTests/Logging/StreamLoggerTest.cs +++ b/ModuleManagerTests/Logging/StreamLoggerTest.cs @@ -11,12 +11,10 @@ public class StreamLoggerTest [Fact] public void TestConstructor__StreamNull() { - ArgumentNullException ex = Assert.Throws(delegate + Assert.Throws(delegate { new StreamLogger(null); }); - - Assert.Equal("stream", ex.ParamName); } [Fact] @@ -24,13 +22,10 @@ public void TestConstructor__CantWrite() { using (MemoryStream stream = new MemoryStream(new byte[0], false)) { - ArgumentException ex = Assert.Throws(delegate + Assert.Throws(delegate { new StreamLogger(stream); }); - - Assert.Equal("stream", ex.ParamName); - Assert.Contains("must be writable", ex.Message); } } diff --git a/ModuleManagerTests/Logging/UnityLoggerTest.cs b/ModuleManagerTests/Logging/UnityLoggerTest.cs index 5d820c25..7c4dc4a1 100644 --- a/ModuleManagerTests/Logging/UnityLoggerTest.cs +++ b/ModuleManagerTests/Logging/UnityLoggerTest.cs @@ -9,12 +9,11 @@ namespace ModuleManagerTests.Logging { public class UnityLoggerTest { - private ILogger innerLogger; - private UnityLogger logger; + private readonly ILogger innerLogger = Substitute.For(); + private readonly UnityLogger logger; public UnityLoggerTest() { - innerLogger = Substitute.For(); logger = new UnityLogger(innerLogger); } diff --git a/ModuleManagerTests/NeedsCheckerTest.cs b/ModuleManagerTests/NeedsCheckerTest.cs index d0414a0b..4d3540b9 100644 --- a/ModuleManagerTests/NeedsCheckerTest.cs +++ b/ModuleManagerTests/NeedsCheckerTest.cs @@ -5,7 +5,6 @@ using ModuleManager; using ModuleManager.Logging; using ModuleManager.Progress; -using NodeStack = ModuleManager.Collections.ImmutableStack; namespace ModuleManagerTests { @@ -13,17 +12,13 @@ public class NeedsCheckerTest { private readonly UrlDir gameData; - private readonly IPatchProgress progress; - private readonly IBasicLogger logger; - private NeedsChecker needsChecker; + private readonly IPatchProgress progress = Substitute.For(); + private readonly IBasicLogger logger = Substitute.For(); + private readonly NeedsChecker needsChecker; public NeedsCheckerTest() { gameData = UrlBuilder.CreateGameData(); - - progress = Substitute.For(); - logger = Substitute.For(); - needsChecker = new NeedsChecker(new[] { "mod1", "mod2", "mod/2" }, gameData, progress, logger); } diff --git a/ModuleManagerTests/PassTest.cs b/ModuleManagerTests/PassTest.cs index d2cce882..bc829816 100644 --- a/ModuleManagerTests/PassTest.cs +++ b/ModuleManagerTests/PassTest.cs @@ -2,7 +2,6 @@ using System.Linq; using Xunit; using NSubstitute; -using TestUtils; using ModuleManager; using ModuleManager.Patches; @@ -10,13 +9,6 @@ namespace ModuleManagerTests { public class PassTest { - private UrlDir.UrlFile file; - - public PassTest() - { - file = UrlBuilder.CreateFile("abc/def.cfg"); - } - [Fact] public void TestConstructor__NameNull() { diff --git a/ModuleManagerTests/PatchExtractorTest.cs b/ModuleManagerTests/PatchExtractorTest.cs index 4106486e..49a12583 100644 --- a/ModuleManagerTests/PatchExtractorTest.cs +++ b/ModuleManagerTests/PatchExtractorTest.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using Xunit; using NSubstitute; using TestUtils; @@ -386,10 +385,5 @@ private void AssertNoErrors() progress.DidNotReceiveWithAnyArgs().Exception(null, null); progress.DidNotReceiveWithAnyArgs().Exception(null, null, null); } - - private void AssertConfigNodesEqual(ConfigNode expected, ConfigNode observed) - { - Assert.Equal(expected.ToString(), observed.ToString()); - } } } diff --git a/ModuleManagerTests/Progress/PatchProgressTest.cs b/ModuleManagerTests/Progress/PatchProgressTest.cs index 8cde86c2..c78964e3 100644 --- a/ModuleManagerTests/Progress/PatchProgressTest.cs +++ b/ModuleManagerTests/Progress/PatchProgressTest.cs @@ -1,7 +1,6 @@ using System; using Xunit; using NSubstitute; -using UnityEngine; using TestUtils; using ModuleManager; using ModuleManager.Logging; @@ -11,12 +10,11 @@ namespace ModuleManagerTests { public class PatchProgressTest { - private IBasicLogger logger; - private PatchProgress progress; + private readonly IBasicLogger logger = Substitute.For(); + private readonly PatchProgress progress; public PatchProgressTest() { - logger = Substitute.For(); progress = new PatchProgress(logger); } From e0da6ba13bca4dea7181cd009b49691d9fd47df0 Mon Sep 17 00:00:00 2001 From: sarbian Date: Tue, 7 Jul 2020 11:42:00 +0200 Subject: [PATCH 05/22] v4.1.4 --- ModuleManager/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModuleManager/Properties/AssemblyInfo.cs b/ModuleManager/Properties/AssemblyInfo.cs index cf5d1a0c..fba8c4bf 100644 --- a/ModuleManager/Properties/AssemblyInfo.cs +++ b/ModuleManager/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion("4.1.3")] +[assembly: AssemblyVersion("4.1.4")] [assembly: KSPAssembly("ModuleManager", 2, 5)] // The following attributes are used to specify the signing key for the assembly, From 0261dc6dac6b3340357a02c8322d21770be9c09c Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Wed, 30 Sep 2020 22:15:15 -0700 Subject: [PATCH 06/22] Normalize KSP root path KSP makes it weird Addresses confusion in #164 --- ModuleManager/FilePathRepository.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ModuleManager/FilePathRepository.cs b/ModuleManager/FilePathRepository.cs index db15419e..0d1448d7 100644 --- a/ModuleManager/FilePathRepository.cs +++ b/ModuleManager/FilePathRepository.cs @@ -5,20 +5,21 @@ namespace ModuleManager { internal static class FilePathRepository { - internal static readonly string cachePath = Path.Combine(KSPUtil.ApplicationRootPath, "GameData", "ModuleManager.ConfigCache"); + internal static readonly string normalizedRootPath = Path.GetFullPath(KSPUtil.ApplicationRootPath); + internal static readonly string cachePath = Path.Combine(normalizedRootPath, "GameData", "ModuleManager.ConfigCache"); internal static readonly string techTreeFile = Path.Combine("GameData", "ModuleManager.TechTree"); - internal static readonly string techTreePath = Path.Combine(KSPUtil.ApplicationRootPath, techTreeFile); + internal static readonly string techTreePath = Path.Combine(normalizedRootPath, techTreeFile); internal static readonly string physicsFile = Path.Combine("GameData", "ModuleManager.Physics"); - internal static readonly string physicsPath = Path.Combine(KSPUtil.ApplicationRootPath, physicsFile); - internal static readonly string defaultPhysicsPath = Path.Combine(KSPUtil.ApplicationRootPath, "Physics.cfg"); + internal static readonly string physicsPath = Path.Combine(normalizedRootPath, physicsFile); + internal static readonly string defaultPhysicsPath = Path.Combine(normalizedRootPath, "Physics.cfg"); - internal static readonly string partDatabasePath = Path.Combine(KSPUtil.ApplicationRootPath, "PartDatabase.cfg"); + internal static readonly string partDatabasePath = Path.Combine(normalizedRootPath, "PartDatabase.cfg"); - internal static readonly string shaPath = Path.Combine(KSPUtil.ApplicationRootPath, "GameData", "ModuleManager.ConfigSHA"); + internal static readonly string shaPath = Path.Combine(normalizedRootPath, "GameData", "ModuleManager.ConfigSHA"); - internal static readonly string logsDirPath = Path.Combine(KSPUtil.ApplicationRootPath, "Logs", "ModuleManager"); + internal static readonly string logsDirPath = Path.Combine(normalizedRootPath, "Logs", "ModuleManager"); internal static readonly string logPath = Path.Combine(logsDirPath, "ModuleManager.log"); internal static readonly string patchLogPath = Path.Combine(logsDirPath, "MMPatch.log"); } From f6669bf7b7a9a2f0cb818ee757b3d2ed870898bb Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Thu, 14 Jan 2021 23:41:11 -0800 Subject: [PATCH 07/22] Set modded physics and reload earlier Do it in post patch, this allows the part loader to pick up changes (e.g. rigidbody min mass) --- ModuleManager/CustomConfigsManager.cs | 10 ---------- ModuleManager/PostPatchLoader.cs | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/ModuleManager/CustomConfigsManager.cs b/ModuleManager/CustomConfigsManager.cs index e2b8689c..d7444363 100644 --- a/ModuleManager/CustomConfigsManager.cs +++ b/ModuleManager/CustomConfigsManager.cs @@ -16,16 +16,6 @@ internal void Start() Log("Setting modded tech tree as the active one"); HighLogic.CurrentGame.Parameters.Career.TechTreeUrl = techTreeFile; } - - if (PhysicsGlobals.PhysicsDatabaseFilename != physicsFile && File.Exists(physicsPath)) - { - Log("Setting modded physics as the active one"); - - PhysicsGlobals.PhysicsDatabaseFilename = physicsFile; - - if (!PhysicsGlobals.Instance.LoadDatabase()) - Log("Something went wrong while setting the active physics config."); - } } public static void Log(String s) diff --git a/ModuleManager/PostPatchLoader.cs b/ModuleManager/PostPatchLoader.cs index 619f09d0..fa1b9df6 100644 --- a/ModuleManager/PostPatchLoader.cs +++ b/ModuleManager/PostPatchLoader.cs @@ -130,6 +130,8 @@ private IEnumerator Run() logger.Info("Reloading Part Upgrades"); PartUpgradeManager.Handler.FillUpgrades(); + LoadModdedPhysics(); + yield return null; progressTitle = "ModuleManager: Running post patch callbacks"; @@ -209,5 +211,23 @@ private IEnumerator Run() ready = true; } + + private void LoadModdedPhysics() + { + if (PhysicsGlobals.PhysicsDatabaseFilename == physicsFile) return; + + if (!File.Exists(physicsPath)) + { + logger.Error("Physics file not found"); + return; + } + + logger.Info("Setting modded physics as the active one"); + + PhysicsGlobals.PhysicsDatabaseFilename = physicsFile; + + if (!PhysicsGlobals.Instance.LoadDatabase()) + logger.Error("Something went wrong while setting the active physics config."); + } } } From 983b330b259547f05d1ff2ff10bc5828153c7883 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Thu, 14 Jan 2021 23:52:56 -0800 Subject: [PATCH 08/22] mark dependencies as copy local false prevents them from showing up in the target directory --- ModuleManager/ModuleManager.csproj | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ModuleManager/ModuleManager.csproj b/ModuleManager/ModuleManager.csproj index d58d8d14..4556194b 100644 --- a/ModuleManager/ModuleManager.csproj +++ b/ModuleManager/ModuleManager.csproj @@ -121,33 +121,42 @@ False + False False + False False + False False + False False + False False + False False + False False + False False + False From b3d5ad47526c43b6d175c775cec77b967055cae7 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Thu, 14 Jan 2021 23:56:16 -0800 Subject: [PATCH 09/22] fix remaining .NET 3.5 nuget packages upgrade visual studio runner --- ModuleManagerTests/ModuleManagerTests.csproj | 8 ++++---- ModuleManagerTests/packages.config | 4 ++-- TestUtilsTests/TestUtilsTests.csproj | 8 ++++---- TestUtilsTests/packages.config | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ModuleManagerTests/ModuleManagerTests.csproj b/ModuleManagerTests/ModuleManagerTests.csproj index b4fafe96..7e311b3b 100644 --- a/ModuleManagerTests/ModuleManagerTests.csproj +++ b/ModuleManagerTests/ModuleManagerTests.csproj @@ -1,8 +1,8 @@  - + - + Debug @@ -156,10 +156,10 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + \ No newline at end of file diff --git a/ModuleManagerTests/packages.config b/ModuleManagerTests/packages.config index dc5635be..63061ffe 100644 --- a/ModuleManagerTests/packages.config +++ b/ModuleManagerTests/packages.config @@ -11,6 +11,6 @@ - - + + \ No newline at end of file diff --git a/TestUtilsTests/TestUtilsTests.csproj b/TestUtilsTests/TestUtilsTests.csproj index 619e6bb4..1d3ff25e 100644 --- a/TestUtilsTests/TestUtilsTests.csproj +++ b/TestUtilsTests/TestUtilsTests.csproj @@ -1,8 +1,8 @@  - + - + Debug @@ -86,10 +86,10 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + \ No newline at end of file diff --git a/TestUtilsTests/packages.config b/TestUtilsTests/packages.config index bbb4cb82..8cf69e4f 100644 --- a/TestUtilsTests/packages.config +++ b/TestUtilsTests/packages.config @@ -7,6 +7,6 @@ - - + + \ No newline at end of file From 6a32ebb8213c2d7f8bca1d3532b15dcced12a598 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Thu, 14 Jan 2021 23:57:18 -0800 Subject: [PATCH 10/22] Update remaining NuGet packages --- ModuleManagerTests/ModuleManagerTests.csproj | 14 +++++++------- ModuleManagerTests/app.config | 4 ++-- ModuleManagerTests/packages.config | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ModuleManagerTests/ModuleManagerTests.csproj b/ModuleManagerTests/ModuleManagerTests.csproj index 7e311b3b..1a82db26 100644 --- a/ModuleManagerTests/ModuleManagerTests.csproj +++ b/ModuleManagerTests/ModuleManagerTests.csproj @@ -40,20 +40,20 @@ - ..\packages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll + ..\packages\Castle.Core.4.4.1\lib\net45\Castle.Core.dll - - ..\packages\NSubstitute.3.1.0\lib\net46\NSubstitute.dll + + ..\packages\NSubstitute.4.2.2\lib\net46\NSubstitute.dll - - ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll - - ..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll diff --git a/ModuleManagerTests/app.config b/ModuleManagerTests/app.config index 1d152980..fe205877 100644 --- a/ModuleManagerTests/app.config +++ b/ModuleManagerTests/app.config @@ -4,11 +4,11 @@ - + - + diff --git a/ModuleManagerTests/packages.config b/ModuleManagerTests/packages.config index 63061ffe..b159434d 100644 --- a/ModuleManagerTests/packages.config +++ b/ModuleManagerTests/packages.config @@ -1,9 +1,9 @@  - - - - + + + + From da38958f48b34bff2052169e5f84885ec2b7daa1 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Fri, 15 Jan 2021 00:04:06 -0800 Subject: [PATCH 11/22] Add specific language markers to all project files seems to get confused otherwise --- ModuleManager/ModuleManager.csproj | 3 +++ ModuleManagerTests/ModuleManagerTests.csproj | 3 +++ TestUtils/TestUtils.csproj | 3 +++ TestUtilsTests/TestUtilsTests.csproj | 3 +++ 4 files changed, 12 insertions(+) diff --git a/ModuleManager/ModuleManager.csproj b/ModuleManager/ModuleManager.csproj index 4556194b..20fe0da1 100644 --- a/ModuleManager/ModuleManager.csproj +++ b/ModuleManager/ModuleManager.csproj @@ -33,6 +33,9 @@ False false + + 8.0 + diff --git a/ModuleManagerTests/ModuleManagerTests.csproj b/ModuleManagerTests/ModuleManagerTests.csproj index 1a82db26..f3afbbf5 100644 --- a/ModuleManagerTests/ModuleManagerTests.csproj +++ b/ModuleManagerTests/ModuleManagerTests.csproj @@ -37,6 +37,9 @@ 4 false + + 8.0 + diff --git a/TestUtils/TestUtils.csproj b/TestUtils/TestUtils.csproj index 10073bd0..5c53b27c 100644 --- a/TestUtils/TestUtils.csproj +++ b/TestUtils/TestUtils.csproj @@ -32,6 +32,9 @@ 4 false + + 8.0 + diff --git a/TestUtilsTests/TestUtilsTests.csproj b/TestUtilsTests/TestUtilsTests.csproj index 1d3ff25e..cfe71bf2 100644 --- a/TestUtilsTests/TestUtilsTests.csproj +++ b/TestUtilsTests/TestUtilsTests.csproj @@ -37,6 +37,9 @@ 4 false + + 8.0 + From 838677db5f2d2c17c1ce653489a3caa974110009 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Fri, 22 Jan 2021 22:34:18 -0800 Subject: [PATCH 12/22] Ensure string comparison is culture invariant And get rid of message suppresions related to it --- ModuleManager/Extensions/StringExtensions.cs | 9 +++++ ModuleManager/MMPatchLoader.cs | 35 ++++++++----------- .../Extensions/StringExtensionsTest.cs | 30 ++++++++++++++++ 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/ModuleManager/Extensions/StringExtensions.cs b/ModuleManager/Extensions/StringExtensions.cs index b9136e30..634fab7a 100644 --- a/ModuleManager/Extensions/StringExtensions.cs +++ b/ModuleManager/Extensions/StringExtensions.cs @@ -24,5 +24,14 @@ public static string RemoveWS(this string withWhite) { return whitespaceRegex.Replace(withWhite, ""); } + + public static bool Contains(this string str, string value, out int index) + { + if (str == null) throw new ArgumentNullException(nameof(str)); + if (value == null) throw new ArgumentNullException(nameof(value)); + + index = str.IndexOf(value, StringComparison.CurrentCultureIgnoreCase); + return index != -1; + } } } diff --git a/ModuleManager/MMPatchLoader.cs b/ModuleManager/MMPatchLoader.cs index d90e29a1..61d993a3 100644 --- a/ModuleManager/MMPatchLoader.cs +++ b/ModuleManager/MMPatchLoader.cs @@ -22,8 +22,6 @@ namespace ModuleManager { - [SuppressMessage("ReSharper", "StringLastIndexOfIsCultureSpecific.1")] - [SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")] public class MMPatchLoader { private const string PHYSICS_NODE_NAME = "PHYSICSGLOBALS"; @@ -922,7 +920,7 @@ public static ConfigNode ModifyNode(NodeStack original, ConfigNode mod, PatchCon ConfigNode newSubMod = new ConfigNode(toPaste.name); newSubMod = ModifyNode(nodeStack.Push(newSubMod), toPaste, context); - if (subName.LastIndexOf(",") > 0 && int.TryParse(subName.Substring(subName.LastIndexOf(",") + 1), out int index)) + if (subName.LastIndexOf(',') > 0 && int.TryParse(subName.Substring(subName.LastIndexOf(',') + 1), out int index)) { // In this case insert the node at position index InsertNode(newNode, newSubMod, index); @@ -945,11 +943,10 @@ public static ConfigNode ModifyNode(NodeStack original, ConfigNode mod, PatchCon // NODE,n will match the nth node (NODE is the same as NODE,0) // NODE,* will match ALL nodes // NODE:HAS[condition] will match ALL nodes with condition - if (subName.Contains(":HAS[")) + if (subName.Contains(":HAS[", out int hasStart)) { - int start = subName.IndexOf(":HAS["); - constraints = subName.Substring(start + 5, subName.LastIndexOf(']') - start - 5); - subName = subName.Substring(0, start); + constraints = subName.Substring(hasStart + 5, subName.LastIndexOf(']') - hasStart - 5); + subName = subName.Substring(0, hasStart); } if (subName.Contains(",")) @@ -1117,11 +1114,10 @@ private static ConfigNode RecurseNodeSearch(string path, NodeStack nodeStack, Pa string constraint = ""; int index = 0; - if (subName.Contains(":HAS[")) + if (subName.Contains(":HAS[", out int hasStart)) { - int start = subName.IndexOf(":HAS["); - constraint = subName.Substring(start + 5, subName.LastIndexOf(']') - start - 5); - subName = subName.Substring(0, start); + constraint = subName.Substring(hasStart + 5, subName.LastIndexOf(']') - hasStart - 5); + subName = subName.Substring(0, hasStart); } else if (subName.Contains(",")) { @@ -1290,13 +1286,12 @@ private static ConfigNode.Value RecurseVariableSearch(string path, NodeStack nod string constraint = ""; string nodeType, nodeName; int index = 0; - if (subName.Contains(":HAS[")) + if (subName.Contains(":HAS[", out int hasStart)) { - int start = subName.IndexOf(":HAS["); - constraint = subName.Substring(start + 5, subName.LastIndexOf(']') - start - 5); - subName = subName.Substring(0, start); + constraint = subName.Substring(hasStart + 5, subName.LastIndexOf(']') - hasStart - 5); + subName = subName.Substring(0, hasStart); } - else if (subName.Contains(",")) + else if (subName.Contains(',')) { string tag = subName.Split(',')[1]; subName = subName.Split(',')[0]; @@ -1551,11 +1546,11 @@ public static bool CheckConstraints(ConfigNode node, string constraints) constraints = constraintList[0]; string remainingConstraints = ""; - if (constraints.Contains("HAS[")) + if (constraints.Contains(":HAS[", out int hasStart)) { - int start = constraints.IndexOf("HAS[") + 4; - remainingConstraints = constraints.Substring(start, constraintList[0].LastIndexOf(']') - start); - constraints = constraints.Substring(0, start - 5); + hasStart += 4; + remainingConstraints = constraints.Substring(hasStart, constraintList[0].LastIndexOf(']') - hasStart); + constraints = constraints.Substring(0, hasStart - 5); } string[] splits = constraints.Split(contraintSeparators, 3); diff --git a/ModuleManagerTests/Extensions/StringExtensionsTest.cs b/ModuleManagerTests/Extensions/StringExtensionsTest.cs index fdf3b33f..acf9274e 100644 --- a/ModuleManagerTests/Extensions/StringExtensionsTest.cs +++ b/ModuleManagerTests/Extensions/StringExtensionsTest.cs @@ -39,5 +39,35 @@ public void TestRemoveWS() { Assert.Equal("abcdef", " abc \tdef\r\n\t ".RemoveWS()); } + + + [InlineData("abc", "b", true, 1)] + [InlineData("abc", "x", false, -1)] + [Theory] + public void TestContains(string str, string test, bool expectedResult, int expectedIndex) + { + bool result = str.Contains(test, out int index); + Assert.Equal(expectedResult, result); + Assert.Equal(expectedIndex, index); + } + + [Fact] + public void TestContains__NullStr() + { + string s = null; + Assert.Throws(delegate + { + s.Contains("x", out int _x); + }); + } + + [Fact] + public void TestContains__NullValue() + { + Assert.Throws(delegate + { + "abc".Contains(null, out int _x); + }); + } } } From c6163a2e495628e59822d2074da027e70aa85136 Mon Sep 17 00:00:00 2001 From: blowfishpro Date: Fri, 22 Jan 2021 22:36:24 -0800 Subject: [PATCH 13/22] Always replace physics On a database reload this will already be true but we still want physics reloading to happen --- ModuleManager/PostPatchLoader.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/ModuleManager/PostPatchLoader.cs b/ModuleManager/PostPatchLoader.cs index fa1b9df6..d850e4e1 100644 --- a/ModuleManager/PostPatchLoader.cs +++ b/ModuleManager/PostPatchLoader.cs @@ -214,8 +214,6 @@ private IEnumerator Run() private void LoadModdedPhysics() { - if (PhysicsGlobals.PhysicsDatabaseFilename == physicsFile) return; - if (!File.Exists(physicsPath)) { logger.Error("Physics file not found"); From 3894ce10ac129611594f2524bf87fef27aafbd85 Mon Sep 17 00:00:00 2001 From: sarbian Date: Sun, 1 Aug 2021 10:42:05 +0200 Subject: [PATCH 14/22] v4.2.0 --- ModuleManager/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModuleManager/Properties/AssemblyInfo.cs b/ModuleManager/Properties/AssemblyInfo.cs index fba8c4bf..0cd2c63f 100644 --- a/ModuleManager/Properties/AssemblyInfo.cs +++ b/ModuleManager/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion("4.1.4")] +[assembly: AssemblyVersion("4.2.0")] [assembly: KSPAssembly("ModuleManager", 2, 5)] // The following attributes are used to specify the signing key for the assembly, From d9e9264fb2f04bb3e4f0026133bf5b110bd4296d Mon Sep 17 00:00:00 2001 From: Alvin Meng Date: Sun, 1 Aug 2021 11:51:32 -0400 Subject: [PATCH 15/22] Fix off-by-one string indexing in constraint checking Also change string comparison type to `StringComparison.Ordinal`, which should be the correct type according to https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings. --- ModuleManager/Extensions/StringExtensions.cs | 2 +- ModuleManager/MMPatchLoader.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ModuleManager/Extensions/StringExtensions.cs b/ModuleManager/Extensions/StringExtensions.cs index 634fab7a..55720367 100644 --- a/ModuleManager/Extensions/StringExtensions.cs +++ b/ModuleManager/Extensions/StringExtensions.cs @@ -30,7 +30,7 @@ public static bool Contains(this string str, string value, out int index) if (str == null) throw new ArgumentNullException(nameof(str)); if (value == null) throw new ArgumentNullException(nameof(value)); - index = str.IndexOf(value, StringComparison.CurrentCultureIgnoreCase); + index = str.IndexOf(value, StringComparison.Ordinal); return index != -1; } } diff --git a/ModuleManager/MMPatchLoader.cs b/ModuleManager/MMPatchLoader.cs index 61d993a3..cf3418c3 100644 --- a/ModuleManager/MMPatchLoader.cs +++ b/ModuleManager/MMPatchLoader.cs @@ -1548,7 +1548,7 @@ public static bool CheckConstraints(ConfigNode node, string constraints) string remainingConstraints = ""; if (constraints.Contains(":HAS[", out int hasStart)) { - hasStart += 4; + hasStart += 5; remainingConstraints = constraints.Substring(hasStart, constraintList[0].LastIndexOf(']') - hasStart); constraints = constraints.Substring(0, hasStart - 5); } From c60e3c537a352de35b02d5fa79a1a6c712a83e9a Mon Sep 17 00:00:00 2001 From: Alvin Meng Date: Sun, 1 Aug 2021 15:08:13 -0400 Subject: [PATCH 16/22] Undo string comparison change. --- ModuleManager/Extensions/StringExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModuleManager/Extensions/StringExtensions.cs b/ModuleManager/Extensions/StringExtensions.cs index 55720367..634fab7a 100644 --- a/ModuleManager/Extensions/StringExtensions.cs +++ b/ModuleManager/Extensions/StringExtensions.cs @@ -30,7 +30,7 @@ public static bool Contains(this string str, string value, out int index) if (str == null) throw new ArgumentNullException(nameof(str)); if (value == null) throw new ArgumentNullException(nameof(value)); - index = str.IndexOf(value, StringComparison.Ordinal); + index = str.IndexOf(value, StringComparison.CurrentCultureIgnoreCase); return index != -1; } } From 86e60c36036c9fa6cd24d9abdc679f452059a8b2 Mon Sep 17 00:00:00 2001 From: sarbian Date: Sun, 1 Aug 2021 21:52:17 +0200 Subject: [PATCH 17/22] v4.2.1 --- ModuleManager/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModuleManager/Properties/AssemblyInfo.cs b/ModuleManager/Properties/AssemblyInfo.cs index 0cd2c63f..ef0b7100 100644 --- a/ModuleManager/Properties/AssemblyInfo.cs +++ b/ModuleManager/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion("4.2.0")] +[assembly: AssemblyVersion("4.2.1")] [assembly: KSPAssembly("ModuleManager", 2, 5)] // The following attributes are used to specify the signing key for the assembly, From ebe2895e3a55384fc8c39c9e0f964a5e39d3ede9 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Thu, 16 Jun 2022 21:35:54 -0700 Subject: [PATCH 18/22] Support patching Localization tokens. * Support wildcards in nodetype matching so you can do @*,* {} * Support # in value names since loc names start with # * Tell Localizer to reload the language after MM finishes --- ModuleManager/MMPatchLoader.cs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/ModuleManager/MMPatchLoader.cs b/ModuleManager/MMPatchLoader.cs index cf3418c3..5278758b 100644 --- a/ModuleManager/MMPatchLoader.cs +++ b/ModuleManager/MMPatchLoader.cs @@ -231,6 +231,9 @@ public IEnumerable Run() } } + if (KSP.Localization.Localizer.Instance != null) + KSP.Localization.Localizer.SwitchToLanguage(KSP.Localization.Localizer.CurrentLanguage); + logger.Info(status + "\n" + errors); patchSw.Stop(); @@ -564,7 +567,7 @@ private void StatusUpdate(IPatchProgress progress, string activity = null) #region Applying Patches // Name is group 1, index is group 2, vector related filed is group 3, vector separator is group 4, operator is group 5 - private static readonly Regex parseValue = new Regex(@"([\w\&\-\.\?\*+/^!\(\) ]+(?:,[^*\d][\w\&\-\.\?\*\(\) ]*)*)(?:,(-?[0-9\*]+))?(?:\[((?:[0-9\*]+)+)(?:,(.))?\])?"); + private static readonly Regex parseValue = new Regex(@"([\w\&\-\.\?\*\#+/^!\(\) ]+(?:,[^*\d][\w\&\-\.\?\*\(\) ]*)*)(?:,(-?[0-9\*]+))?(?:\[((?:[0-9\*]+)+)(?:,(.))?\])?"); // ModifyNode applies the ConfigNode mod as a 'patch' to ConfigNode original, then returns the patched ConfigNode. // it uses FindConfigNodeIn(src, nodeType, nodeName, nodeTag) to recurse. @@ -1712,19 +1715,26 @@ public static ConfigNode FindConfigNodeIn( string nodeName = null, int index = 0) { - ConfigNode[] nodes = src.GetNodes(nodeType); - if (nodes.Length == 0) + List nodes = new List(); + int c = src.nodes.Count; + for(int i = 0; i < c; ++i) + { + if (WildcardMatch(src.nodes[i].name, nodeType)) + nodes.Add(src.nodes[i]); + } + int nodeCount = nodes.Count; + if (nodeCount == 0) return null; if (nodeName == null) { if (index >= 0) - return nodes[Math.Min(index, nodes.Length - 1)]; - return nodes[Math.Max(0, nodes.Length + index)]; + return nodes[Math.Min(index, nodeCount - 1)]; + return nodes[Math.Max(0, nodeCount + index)]; } ConfigNode last = null; if (index >= 0) { - for (int i = 0; i < nodes.Length; ++i) + for (int i = 0; i < nodeCount; ++i) { if (nodes[i].HasValue("name") && WildcardMatch(nodes[i].GetValue("name"), nodeName)) { @@ -1735,7 +1745,7 @@ public static ConfigNode FindConfigNodeIn( } return last; } - for (int i = nodes.Length - 1; i >= 0; --i) + for (int i = nodeCount - 1; i >= 0; --i) { if (nodes[i].HasValue("name") && WildcardMatch(nodes[i].GetValue("name"), nodeName)) { From a303e0a7118f3506cc1546b70b03acc04263a6b7 Mon Sep 17 00:00:00 2001 From: sarbian Date: Sat, 18 Jun 2022 20:22:56 +0200 Subject: [PATCH 19/22] v4.2.2 --- ModuleManager/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModuleManager/Properties/AssemblyInfo.cs b/ModuleManager/Properties/AssemblyInfo.cs index ef0b7100..e4e038f0 100644 --- a/ModuleManager/Properties/AssemblyInfo.cs +++ b/ModuleManager/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion("4.2.1")] +[assembly: AssemblyVersion("4.2.2")] [assembly: KSPAssembly("ModuleManager", 2, 5)] // The following attributes are used to specify the signing key for the assembly, From 2ba651e41aebba1758e57b679f01bb8592b2d536 Mon Sep 17 00:00:00 2001 From: Jonathan Bayer Date: Sun, 14 May 2023 18:19:50 -0400 Subject: [PATCH 20/22] Added , FileShare.ReadWrite to the File.Open, to allow MM to read files which are already opened by KSP --- ModuleManager/Utils/FileUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModuleManager/Utils/FileUtils.cs b/ModuleManager/Utils/FileUtils.cs index 818d3cc6..fcf04482 100644 --- a/ModuleManager/Utils/FileUtils.cs +++ b/ModuleManager/Utils/FileUtils.cs @@ -12,7 +12,7 @@ public static string FileSHA(string filename) if (!File.Exists(filename)) throw new FileNotFoundException("File does not exist", filename); using SHA256 sha = SHA256.Create(); - using FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read); + using FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); byte[] data = sha.ComputeHash(fs); return data.ToHex(); From b22136a8302b592626533f864413cb7b37a32126 Mon Sep 17 00:00:00 2001 From: siimav Date: Fri, 19 May 2023 23:51:58 +0300 Subject: [PATCH 21/22] Fix invalid modded physics cfg path being fed to KSP when using the faulty PDLauncher workaround --- ModuleManager/PostPatchLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModuleManager/PostPatchLoader.cs b/ModuleManager/PostPatchLoader.cs index d850e4e1..1bccce78 100644 --- a/ModuleManager/PostPatchLoader.cs +++ b/ModuleManager/PostPatchLoader.cs @@ -222,7 +222,7 @@ private void LoadModdedPhysics() logger.Info("Setting modded physics as the active one"); - PhysicsGlobals.PhysicsDatabaseFilename = physicsFile; + PhysicsGlobals.PhysicsDatabaseFilename = physicsPath; if (!PhysicsGlobals.Instance.LoadDatabase()) logger.Error("Something went wrong while setting the active physics config."); From c4561925f983e7ae81d9dfd4d11356a35cb6b9b6 Mon Sep 17 00:00:00 2001 From: sarbian Date: Mon, 3 Jul 2023 20:01:38 +0200 Subject: [PATCH 22/22] v4.2.3 --- ModuleManager/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModuleManager/Properties/AssemblyInfo.cs b/ModuleManager/Properties/AssemblyInfo.cs index e4e038f0..12a660e1 100644 --- a/ModuleManager/Properties/AssemblyInfo.cs +++ b/ModuleManager/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion("4.2.2")] +[assembly: AssemblyVersion("4.2.3")] [assembly: KSPAssembly("ModuleManager", 2, 5)] // The following attributes are used to specify the signing key for the assembly,