Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 74 additions & 165 deletions Source/Modules/ModuleSystemHeat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -113,9 +103,8 @@ public float LoopFlux
}

protected SystemHeatSimulator simulator;
protected Dictionary<string, float> fluxes;
protected Dictionary<string, float> temperatures;
protected List<int> loopIDs;
protected readonly Dictionary<string, float> fluxes = [];
protected readonly Dictionary<string, float> temperatures = [];

public override string GetModuleDisplayName()
{
Expand All @@ -129,14 +118,6 @@ public override string GetInfo()

public void Start()
{

loopIDs = new List<int>();
fluxes = new Dictionary<string, float>();
temperatures = new Dictionary<string, float>();

for (int i = 0; i < SystemHeatSettings.maxLoopCount; i++)
loopIDs.Add(i);

SetupUI();

Fields["totalSystemTemperature"].guiActive = SystemHeatSettings.DebugPartUI;
Expand All @@ -157,90 +138,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<ModuleSystemHeat> allHeatModules = new List<ModuleSystemHeat>();
for (int i = 0; i < part.vessel.Parts.Count; i++)
{
if (part.vessel.Parts[i].GetComponent<ModuleSystemHeat>())
{
allHeatModules.Add(part.vessel.Parts[i].GetComponent<ModuleSystemHeat>());
}
}

// Find list of used heat modules
List<int> usedModules = new List<int>();
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");

/// <summary>
/// Add heat flux at a given temperature to system
Expand All @@ -254,56 +168,51 @@ void ChangeAllLoops(object oldFieldValueObj)
/// </param>
public void AddFlux(string id, float sourceTemperature, float flux, bool useForNominal)
{
x_AddFluxMarker.Begin();
using var scope = x_AddFluxMarker.Auto();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC "auto" markers like this do not properly get removed when profiling is not enabled.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In most cases I actually consider this a benefit, though this method is probably called too often for that to be true. Let me whip up a helper that fixes this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, the code that was there before was perfectly fine...

Copy link
Copy Markdown
Contributor Author

@Phantomical Phantomical May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would break if an early return ever gets added or an exception is thrown. That's my main objection, especially if I'm going to be adding more of these throughout.


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;
}

x_AddFluxMarker.End();
}

public float GetFlux(string id)
Expand All @@ -329,13 +238,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;
Expand All @@ -347,12 +255,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;
Expand All @@ -376,24 +285,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;
}
}

Expand Down
51 changes: 27 additions & 24 deletions Source/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,30 @@ public enum LogType
Simulator,
Any
}

public static class Utils
{
public static string logTag = "SystemHeat";
public static readonly string logTag = "SystemHeat";

/// <summary>
/// Is logging enabled for a given subsystem? Use this to avoid formatting
/// calls if the logging wouldn't happen anyway.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
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
};
}

/// <summary>
/// Log a message with the mod name tag prefixed
Expand All @@ -25,31 +46,13 @@ public static class Utils
/// <param name="logType">the subsystem that is emitting this log</param>
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}");


/// <summary>
Expand Down
Loading