From bb0b4fb4f6014174c93cecc781eb34e8a0fd7393 Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 7 May 2026 11:00:33 -0700 Subject: [PATCH 1/8] Simplify the Loop property --- Source/Modules/ModuleSystemHeat.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Source/Modules/ModuleSystemHeat.cs b/Source/Modules/ModuleSystemHeat.cs index f135e81..2b80ca5 100644 --- a/Source/Modules/ModuleSystemHeat.cs +++ b/Source/Modules/ModuleSystemHeat.cs @@ -82,17 +82,7 @@ public class ModuleSystemHeat : PartModule [KSPField(isPersistant = false, guiActive = true, guiActiveEditor = true, guiName = "#LOC_SystemHeat_ModuleSystemHeat_Field_LoopTemperature", groupName = "sysheatinfo", groupDisplayName = "#LOC_SystemHeat_ModuleSystemHeat_GroupName", groupStartCollapsed = false)] public string LoopTemperatureUI = "-"; - public HeatLoop Loop - { - get - { - if (simulator != null) - { - return simulator.Loop(currentLoopID); - } - else return null; - } - } + public HeatLoop Loop => simulator?.Loop(currentLoopID); public int LoopID { From 1d6315f58b17eac60f1a55c907da4ef7f2a6940f Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 7 May 2026 11:03:09 -0700 Subject: [PATCH 2/8] Immediately initialize fluxes, temperatures, and loopIDs --- Source/Modules/ModuleSystemHeat.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Source/Modules/ModuleSystemHeat.cs b/Source/Modules/ModuleSystemHeat.cs index 2b80ca5..1417656 100644 --- a/Source/Modules/ModuleSystemHeat.cs +++ b/Source/Modules/ModuleSystemHeat.cs @@ -103,9 +103,9 @@ public float LoopFlux } protected SystemHeatSimulator simulator; - protected Dictionary fluxes; - protected Dictionary temperatures; - protected List loopIDs; + protected Dictionary fluxes = []; + protected Dictionary temperatures = []; + protected List loopIDs = []; public override string GetModuleDisplayName() { @@ -119,11 +119,6 @@ public override string GetInfo() public void Start() { - - loopIDs = new List(); - fluxes = new Dictionary(); - temperatures = new Dictionary(); - for (int i = 0; i < SystemHeatSettings.maxLoopCount; i++) loopIDs.Add(i); From 3d84b4644b3fff927b1c205bc4fe97baf170254d Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 7 May 2026 11:04:10 -0700 Subject: [PATCH 3/8] Initialize loop IDs in OnAwake --- Source/Modules/ModuleSystemHeat.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Modules/ModuleSystemHeat.cs b/Source/Modules/ModuleSystemHeat.cs index 1417656..b268ed4 100644 --- a/Source/Modules/ModuleSystemHeat.cs +++ b/Source/Modules/ModuleSystemHeat.cs @@ -117,11 +117,16 @@ public override string GetInfo() return Localizer.Format("#LOC_SystemHeat_ModuleSystemHeat_PartInfo", volume.ToString("F2")); } - public void Start() + public override void OnAwake() { + base.OnAwake(); + for (int i = 0; i < SystemHeatSettings.maxLoopCount; i++) loopIDs.Add(i); + } + public void Start() + { SetupUI(); Fields["totalSystemTemperature"].guiActive = SystemHeatSettings.DebugPartUI; From 533ae4c0d360565dfebff4f5eabaae4c225bef80 Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 7 May 2026 11:12:25 -0700 Subject: [PATCH 4/8] Add a helper for checking whether a log is enabled + cleanup --- Source/Utils.cs | 51 ++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/Source/Utils.cs b/Source/Utils.cs index 020e884..0d0a014 100644 --- a/Source/Utils.cs +++ b/Source/Utils.cs @@ -14,9 +14,30 @@ public enum LogType Simulator, Any } + public static class Utils { - public static string logTag = "SystemHeat"; + public static readonly string logTag = "SystemHeat"; + + /// + /// Is logging enabled for a given subsystem? Use this to avoid formatting + /// calls if the logging wouldn't happen anyway. + /// + /// + /// + public static bool IsLogEnabled(LogType type) + { + return type switch + { + LogType.Settings => SystemHeatSettings.DebugSettings, + LogType.UI => SystemHeatSettings.DebugUI, + LogType.Modules => SystemHeatSettings.DebugModules, + LogType.Overlay => SystemHeatSettings.DebugOverlay, + LogType.Simulator => SystemHeatSettings.DebugSimulation, + LogType.Any => true, + _ => false + }; + } /// /// Log a message with the mod name tag prefixed @@ -25,31 +46,13 @@ public static class Utils /// the subsystem that is emitting this log public static void Log(string str, LogType logType) { - bool doLog = false; - if (logType == LogType.Settings && SystemHeatSettings.DebugSettings) doLog = true; - if (logType == LogType.UI && SystemHeatSettings.DebugUI) doLog = true; - if (logType == LogType.Modules && SystemHeatSettings.DebugModules) doLog = true; - if (logType == LogType.Overlay && SystemHeatSettings.DebugOverlay) doLog = true; - if (logType == LogType.Simulator && SystemHeatSettings.DebugSimulation) doLog = true; - if (logType == LogType.Any) doLog = true; - - if (doLog) - Debug.Log(String.Format("[{0}]{1}", logTag, str)); + if (IsLogEnabled(logType)) + Debug.Log($"[{logTag}]{str}"); } - public static void Log(string str) - { - Debug.Log(String.Format("[{0}]{1}", logTag, str)); - } - - public static void LogWarning(string toLog) - { - Debug.LogWarning(String.Format("[{0}]{1}", logTag, toLog)); - } - public static void LogError(string toLog) - { - Debug.LogError(String.Format("[{0}]{1}", logTag, toLog)); - } + public static void Log(string str) => Debug.Log($"[{logTag}]{str}"); + public static void LogWarning(string toLog) => Debug.LogWarning($"[{logTag}]{toLog}"); + public static void LogError(string toLog) => Debug.LogError($"[{logTag}]{toLog}"); /// From af62b0234fdf753b3433538e58a87158dcfbae58 Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 7 May 2026 11:17:43 -0700 Subject: [PATCH 5/8] Clean up ModuleSystemHeat * Initialize fluxes, temperatures, and loopIDs in the ctor * Switch to using guard clauses * A bunch of minor formatting fixes * Avoid calling string.Format if the relevant LogType is not enabled * Delete ChangeAllLoops since it is dead code --- Source/Modules/ModuleSystemHeat.cs | 141 ++++++++--------------------- 1 file changed, 36 insertions(+), 105 deletions(-) diff --git a/Source/Modules/ModuleSystemHeat.cs b/Source/Modules/ModuleSystemHeat.cs index b268ed4..ae56c8e 100644 --- a/Source/Modules/ModuleSystemHeat.cs +++ b/Source/Modules/ModuleSystemHeat.cs @@ -120,7 +120,7 @@ public override string GetInfo() public override void OnAwake() { base.OnAwake(); - + for (int i = 0; i < SystemHeatSettings.maxLoopCount; i++) loopIDs.Add(i); } @@ -147,90 +147,23 @@ void SetupUI() { BaseField chooseField = Fields["currentLoopID"]; UI_ChooseOption chooseOption = HighLogic.LoadedSceneIsFlight ? chooseField.uiControlFlight as UI_ChooseOption : chooseField.uiControlEditor as UI_ChooseOption; - chooseOption.options = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + chooseOption.options = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; chooseOption.onFieldChanged = ChangeLoop; } private void ChangeLoop(BaseField field, object oldFieldValueObj) { - if (HighLogic.LoadedSceneIsFlight) - { - Utils.Log($"[ModuleSystemHeat] Changing part from loop {(int)oldFieldValueObj} to loop {currentLoopID}", LogType.Modules); - simulator.RemoveHeatModuleFromLoop((int)oldFieldValueObj, this); - simulator.AddHeatModuleToLoop(currentLoopID, this); - } - } - - void ChangeAllLoops(object oldFieldValueObj) - { - if (HighLogic.LoadedSceneIsFlight) - { - Utils.Log($"[ModuleSystemHeat] Changing all loop {(int)oldFieldValueObj} modules to loop {currentLoopID}", LogType.Modules); - List allHeatModules = new List(); - for (int i = 0; i < part.vessel.Parts.Count; i++) - { - if (part.vessel.Parts[i].GetComponent()) - { - allHeatModules.Add(part.vessel.Parts[i].GetComponent()); - } - } - - // Find list of used heat modules - List usedModules = new List(); - for (int i = 0; i < allHeatModules.Count; i++) - { - if (allHeatModules[i] != this) - { - if (!usedModules.Contains(allHeatModules[i].currentLoopID)) - { - usedModules.Add(allHeatModules[i].currentLoopID); - Utils.Log($"[ModuleSystemHeat] {allHeatModules[i].currentLoopID} is in use", LogType.Modules); - } - } - } - - bool unused = false; - - int newID = currentLoopID; - while (!unused) - { - - if (usedModules.Contains(newID)) - { - Utils.Log($"[ModuleSystemHeat] {newID} is in use and cannot be used", LogType.Modules); - newID++; - } - else - { - unused = true; - Utils.Log($"[ModuleSystemHeat] {newID} will be the new ID", LogType.Modules); - } - } - - for (int i = 0; i < allHeatModules.Count; i++) - { - if (allHeatModules[i] == this) - { - allHeatModules[i].currentLoopID = newID; - - UIPartActionWindow window = UIPartActionController.Instance?.GetItem(part, false); - if (window == null) return; - window.displayDirty = true; - } - if (allHeatModules[i].currentLoopID == (int)oldFieldValueObj) - { - - - allHeatModules[i].currentLoopID = newID; - - } - } - Utils.Log($"[ModuleSystemHeat] finished changing loop IDs to new {newID}", LogType.Modules); - simulator.ChangeLoopID((int)oldFieldValueObj, newID); - } + if (!HighLogic.LoadedSceneIsFlight) + return; + + var oldLoopID = (int)oldFieldValueObj; + if (Utils.IsLogEnabled(LogType.Modules)) + Utils.Log($"[ModuleSystemHeat] Changing part from loop {oldLoopID} to loop {currentLoopID}", LogType.Modules); + simulator.RemoveHeatModuleFromLoop(oldLoopID, this); + simulator.AddHeatModuleToLoop(currentLoopID, this); } - static ProfilerMarker x_AddFluxMarker = new ProfilerMarker("ModuleSystemHeat.AddFlux"); + static readonly ProfilerMarker x_AddFluxMarker = new("ModuleSystemHeat.AddFlux"); /// /// Add heat flux at a given temperature to system @@ -244,7 +177,7 @@ void ChangeAllLoops(object oldFieldValueObj) /// public void AddFlux(string id, float sourceTemperature, float flux, bool useForNominal) { - x_AddFluxMarker.Begin(); + using var scope = x_AddFluxMarker.Auto(); if (fluxes != null && temperatures != null) { @@ -292,8 +225,6 @@ public void AddFlux(string id, float sourceTemperature, float flux, bool useForN ignoreTemperature = false; } } - - x_AddFluxMarker.End(); } public float GetFlux(string id) @@ -319,13 +250,12 @@ public void SetSystemHeatModuleEnabled(bool enabled) if (simulator == null) FindSimulator(); - if (enabled && !moduleUsed) { - Utils.Log($"[ModuleSystemHeat] seting module {moduleID} system state from {moduleUsed} to {enabled}", LogType.Modules); + if (Utils.IsLogEnabled(LogType.Modules)) + Utils.Log($"[ModuleSystemHeat] seting module {moduleID} system state from {moduleUsed} to {enabled}", LogType.Modules); moduleUsed = enabled; - if (simulator != null) - simulator.AddHeatModule(this); + simulator?.AddHeatModule(this); // turn things on Fields["SystemTemperatureUI"].guiActive = true; @@ -337,12 +267,13 @@ public void SetSystemHeatModuleEnabled(bool enabled) Fields["currentLoopID"].guiActive = true; Fields["currentLoopID"].guiActiveEditor = true; } + if (!enabled && moduleUsed) { - Utils.Log($"[ModuleSystemHeat] seting module {moduleID} system state from {moduleUsed} to {enabled}", LogType.Modules); + if (Utils.IsLogEnabled(LogType.Modules)) + Utils.Log($"[ModuleSystemHeat] seting module {moduleID} system state from {moduleUsed} to {enabled}", LogType.Modules); moduleUsed = enabled; - if (simulator != null) - simulator.RemoveHeatModule(this); + simulator?.RemoveHeatModule(this); // turn things off Fields["SystemTemperatureUI"].guiActive = false; @@ -366,24 +297,24 @@ protected void FixedUpdate() protected void Update() { - if (HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneIsEditor) + if (!HighLogic.LoadedSceneIsFlight && !HighLogic.LoadedSceneIsEditor) + return; + + if (!moduleUsed || !part.IsPAWVisible()) + return; + + SystemFluxUI = String.Format("{0}W", Utils.ToSI(totalSystemFlux, "F0")); + LoopTemperatureUI = String.Format("{0:F0} / {1:F0} K", currentLoopTemperature, nominalLoopTemperature); + if (totalSystemFlux > 0f) { - if (part.IsPAWVisible() && moduleUsed) - { - SystemFluxUI = String.Format("{0}W", Utils.ToSI(totalSystemFlux, "F0")); - LoopTemperatureUI = String.Format("{0:F0} / {1:F0} K", currentLoopTemperature, nominalLoopTemperature); - if (totalSystemFlux > 0f) - { - Fields["SystemTemperatureUI"].guiActive = true; - Fields["SystemTemperatureUI"].guiActiveEditor = true; - SystemTemperatureUI = String.Format("{0:F0} K", totalSystemTemperature); - } - else - { - Fields["SystemTemperatureUI"].guiActive = false; - Fields["SystemTemperatureUI"].guiActiveEditor = false; - } - } + Fields["SystemTemperatureUI"].guiActive = true; + Fields["SystemTemperatureUI"].guiActiveEditor = true; + SystemTemperatureUI = String.Format("{0:F0} K", totalSystemTemperature); + } + else + { + Fields["SystemTemperatureUI"].guiActive = false; + Fields["SystemTemperatureUI"].guiActiveEditor = false; } } From 6f5beb650d9c4e7486a0c33446987fc1712c1816 Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 7 May 2026 11:29:02 -0700 Subject: [PATCH 6/8] Make fluxes, temperatures, loopIDs readonly --- Source/Modules/ModuleSystemHeat.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Modules/ModuleSystemHeat.cs b/Source/Modules/ModuleSystemHeat.cs index ae56c8e..76d38a5 100644 --- a/Source/Modules/ModuleSystemHeat.cs +++ b/Source/Modules/ModuleSystemHeat.cs @@ -103,9 +103,9 @@ public float LoopFlux } protected SystemHeatSimulator simulator; - protected Dictionary fluxes = []; - protected Dictionary temperatures = []; - protected List loopIDs = []; + protected readonly Dictionary fluxes = []; + protected readonly Dictionary temperatures = []; + protected readonly List loopIDs = []; public override string GetModuleDisplayName() { From a2e341f263f003f1caa63cff685f5e92a117f584 Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 7 May 2026 11:31:23 -0700 Subject: [PATCH 7/8] Remove now-unnecessary null guards --- Source/Modules/ModuleSystemHeat.cs | 84 +++++++++++++----------------- 1 file changed, 36 insertions(+), 48 deletions(-) diff --git a/Source/Modules/ModuleSystemHeat.cs b/Source/Modules/ModuleSystemHeat.cs index 76d38a5..4bd712a 100644 --- a/Source/Modules/ModuleSystemHeat.cs +++ b/Source/Modules/ModuleSystemHeat.cs @@ -105,7 +105,6 @@ public float LoopFlux protected SystemHeatSimulator simulator; protected readonly Dictionary fluxes = []; protected readonly Dictionary temperatures = []; - protected readonly List loopIDs = []; public override string GetModuleDisplayName() { @@ -117,14 +116,6 @@ public override string GetInfo() return Localizer.Format("#LOC_SystemHeat_ModuleSystemHeat_PartInfo", volume.ToString("F2")); } - public override void OnAwake() - { - base.OnAwake(); - - for (int i = 0; i < SystemHeatSettings.maxLoopCount; i++) - loopIDs.Add(i); - } - public void Start() { SetupUI(); @@ -179,51 +170,48 @@ public void AddFlux(string id, float sourceTemperature, float flux, bool useForN { using var scope = x_AddFluxMarker.Auto(); - if (fluxes != null && temperatures != null) - { - fluxes[id] = flux; + fluxes[id] = flux; - // Add if used for nominal - if (useForNominal) - { - temperatures[id] = sourceTemperature; - } - else - { - temperatures[id] = 0f; - } + // Add if used for nominal + if (useForNominal) + { + temperatures[id] = sourceTemperature; + } + else + { + temperatures[id] = 0f; + } - totalSystemFlux = 0; - foreach (var f in fluxes.Values) - { - totalSystemFlux += f; - } - totalSystemFlux *= (float)(PhysicsGlobals.InternalHeatProductionFactor / 0.025d); - totalSystemTemperature = 0; - float denom = 0; - foreach (var temp in temperatures.Values) + totalSystemFlux = 0; + foreach (var f in fluxes.Values) + { + totalSystemFlux += f; + } + totalSystemFlux *= (float)(PhysicsGlobals.InternalHeatProductionFactor / 0.025d); + totalSystemTemperature = 0; + float denom = 0; + foreach (var temp in temperatures.Values) + { + if (temp > 0f) { - if (temp > 0f) - { - totalSystemTemperature += temp; - denom++; - } + totalSystemTemperature += temp; + denom++; } + } - if (denom > 0) - systemNominalTemperature = totalSystemTemperature / denom; - else - systemNominalTemperature = 0f; + if (denom > 0) + systemNominalTemperature = totalSystemTemperature / denom; + else + systemNominalTemperature = 0f; - totalSystemTemperature = systemNominalTemperature; - if (totalSystemTemperature == 0f) - { - ignoreTemperature = true; - } - else - { - ignoreTemperature = false; - } + totalSystemTemperature = systemNominalTemperature; + if (totalSystemTemperature == 0f) + { + ignoreTemperature = true; + } + else + { + ignoreTemperature = false; } } From 78e90d61762a2864523816b71052a7421303a4d0 Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 7 May 2026 13:03:17 -0700 Subject: [PATCH 8/8] Add a ConditionalAuto helper that only traces on ENABLE_PROFILER --- Source/Modules/ModuleSystemHeat.cs | 2 +- Source/Utils.cs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Source/Modules/ModuleSystemHeat.cs b/Source/Modules/ModuleSystemHeat.cs index 4bd712a..600032b 100644 --- a/Source/Modules/ModuleSystemHeat.cs +++ b/Source/Modules/ModuleSystemHeat.cs @@ -168,7 +168,7 @@ private void ChangeLoop(BaseField field, object oldFieldValueObj) /// public void AddFlux(string id, float sourceTemperature, float flux, bool useForNominal) { - using var scope = x_AddFluxMarker.Auto(); + using var scope = x_AddFluxMarker.ConditionalAuto(); fluxes[id] = flux; diff --git a/Source/Utils.cs b/Source/Utils.cs index 0d0a014..49ca20c 100644 --- a/Source/Utils.cs +++ b/Source/Utils.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; +using Unity.Profiling; using UnityEngine; @@ -137,4 +139,28 @@ public static Transform FindDeepChild(this Transform aParent, string aName) return null; } } + + internal static class ProfilingExt + { +#if ENABLE_PROFILER + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + internal struct Scope(ProfilerMarker.AutoScope scope) : IDisposable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly void Dispose() => scope.Dispose(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Scope ConditionalAuto(this ProfilerMarker marker) => new(marker.Auto()); +#else + internal struct Scope : IDisposable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly void Dispose() { } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Scope ConditionalAuto(this ProfilerMarker _) => default; +#endif + } }