Skip to content

Commit

Permalink
Load proc avi part volume manually in OnStartFinished instead of rely…
Browse files Browse the repository at this point in the history
…ing the OnPartVolumeChanged event getting called

(cherry picked from commit 4c1ba03)
  • Loading branch information
NathanKell committed Jun 3, 2023
1 parent 6ef29c6 commit e742b31
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 34 deletions.
71 changes: 38 additions & 33 deletions Source/Avionics/ModuleProceduralAvionics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using RealFuels.Tanks;
using RP0.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -58,6 +57,7 @@ public partial class ModuleProceduralAvionics : ModuleAvionics, IPartMassModifie
private BaseEventDetails _cachedEventData = null;

private PartModule _procPartPM;
private PartModule _procShapePM;
private PartModule _roTankPM;
private ModuleFuelTanks _rfPM;
private System.Collections.ObjectModel.KeyedCollection<string, FuelTank> _tankList = null;
Expand All @@ -66,6 +66,8 @@ public partial class ModuleProceduralAvionics : ModuleAvionics, IPartMassModifie
private MethodInfo _seekVolumeMethod;
private FieldInfo _procPartMinVolumeField;
private PropertyInfo _procPartCurShapeProp;
private PropertyInfo _procPartVolumeProp;
private PropertyInfo _roTankVolumeProp;

public ProceduralAvionicsConfig CurrentProceduralAvionicsConfig { get; private set; }

Expand Down Expand Up @@ -181,12 +183,21 @@ public override void OnStart(StartState state)
SetupGUI();
base.OnStart(state);
massLimit = controllableMass;
_started = true;
if (_cachedEventData != null)
OnPartVolumeChanged(_cachedEventData);
Profiler.EndSample();
}

public override void OnStartFinished(StartState _)
{
base.OnStartFinished(_);

// ProceduralParts and ROTanks will initialize their volume values in OnStart
_cachedVolume = _procPartVolumeProp != null ? (float)_procPartVolumeProp.GetValue(_procPartPM)
: (float)_roTankVolumeProp.GetValue(_roTankPM);
_started = true;
UpdateMassLimitsAndVolume();
RefreshDisplays();
}

public void Start()
{
// Delay SetScienceContainer to Unity.Start() to allow PartModule removal
Expand All @@ -200,30 +211,34 @@ public void Start()

private void LoadPartModulesAndFields()
{
_roTankPM = part.Modules.GetModule("ModuleROTank");
_procPartPM = part.Modules.GetModule("ProceduralPart");
if (_procPartPM != null)
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
if (part.Modules.GetModule("ProceduralPart") is PartModule pm)
{
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
_procPartPM = pm;
_procPartMinVolumeField = _procPartPM.GetType().GetField("volumeMin", flags);
_procPartCurShapeProp = _procPartPM.GetType().GetProperty("CurrentShape", flags);
_procPartVolumeProp = _procPartPM.GetType().GetProperty("Volume", flags);
}

_rfPM = part.Modules.GetModule<ModuleFuelTanks>();
FieldInfo fiDict = typeof(ModuleFuelTanks).GetField("tanksDict", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
if (fiDict != null)
else if (part.Modules.GetModule("ModuleROTank") is PartModule pm2)
{
_tanksDict = (Dictionary<string, FuelTank>)fiDict.GetValue(_rfPM);
_ecTank = _tanksDict["ElectricCharge"];
_roTankPM = pm2;
_roTankVolumeProp = _roTankPM.GetType().GetProperty("Volume", flags);

if (_roTankVolumeProp == null)
{
ShowOutdatedROLibWarning();
}
}
else
{
Debug.Log("[RP-0] Could not find tank dictionary on RF part module, falling back to FuelTankList");
FieldInfo fiTanks = typeof(ModuleFuelTanks).GetField("tankList", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
_tankList = (System.Collections.ObjectModel.KeyedCollection<string, FuelTank>)fiTanks.GetValue(_rfPM);
_ecTank = _tankList["ElectricCharge"];
Debug.LogError("[RP0ProcAvi] Part needs to be procedural");
}

_rfPM = part.Modules.GetModule<ModuleFuelTanks>();
FieldInfo fiDict = typeof(ModuleFuelTanks).GetField("tanksDict", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
_tanksDict = (Dictionary<string, FuelTank>)fiDict.GetValue(_rfPM);
_ecTank = _tanksDict["ElectricCharge"];

_seekVolumeMethod = GetSeekVolumeMethod();
}

Expand All @@ -234,9 +249,6 @@ private MethodInfo GetSeekVolumeMethod()
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
MethodInfo mi = _procPartPM.GetType().GetMethod("SeekVolume", flags);

if (mi.GetParameters().Length == 1)
ShowOutdatedProcPartWarning();

return mi;
}
return null;
Expand Down Expand Up @@ -424,13 +436,6 @@ public void OnPartVolumeChanged(BaseEventDetails eventData)
Profiler.BeginSample("RP0ProcAvi OnPartVolumeChanged");
float volume = (float)eventData.Get<double>("newTotalVolume");
Log($"OnPartVolumeChanged to {volume} from {_cachedVolume}");
if (!_started)
{
Log("Delaying OnPartVolumeChanged until after Start()");
_cachedEventData = eventData;
Profiler.EndSample();
return;
}
_cachedVolume = volume;

UpdateMassLimitsAndVolume();
Expand All @@ -452,8 +457,8 @@ private void SendRemainingVolume()
if (_started && _cachedVolume < float.MaxValue)
{
Events[nameof(OnPartVolumeChanged)].active = false;
InternalTanksVolume = SphericalTankUtilities.GetSphericalTankVolume(GetAvailableVolume());
float availVol = GetAvailableVolume();
InternalTanksVolume = SphericalTankUtilities.GetSphericalTankVolume(availVol);
Log($"SendRemainingVolume(): Cached Volume: {_cachedVolume}. AvionicsVolume: {GetAvionicsVolume()}. AvailableVolume: {availVol}. Internal Tanks: {InternalTanksVolume}");
SendVolumeChangedEvent(InternalTanksVolume);
_rfPM?.CalculateMass();
Expand Down Expand Up @@ -529,13 +534,13 @@ private void SeekVolume(float targetVolume)
Profiler.EndSample();
}

private void ShowOutdatedProcPartWarning()
private void ShowOutdatedROLibWarning()
{
PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f),
"ShowOutdatedProcPartWarning",
"Outdated Procedural Parts version",
"RP-1 has detected an outdated version of the Procedural Parts mod. Some procedural avionics features will now be disabled. For best experience please update to the latest Procedural Parts release.",
"ShowOutdatedROLibWarning",
"Outdated ROLibrary version",
"RP-1 has detected an outdated version of ROLibrary. The probe core part will be broken unless ROLib is updated to the latest release.",
"OK",
false,
HighLogic.UISkin);
Expand Down
6 changes: 6 additions & 0 deletions Source/Tooling/ModuleTooling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public abstract class ModuleTooling : PartModule, IPartCostModifier
protected BaseEvent tEvent;
protected Dictionary<string, float> reducerDict;
protected bool onStartFinished;
protected bool onStartFinishedFinished;

public virtual string ToolingType => toolingType;
public virtual string ToolingTypeTitle => string.IsNullOrEmpty(toolingTypeTitle) ? ToolingType : toolingTypeTitle;
Expand Down Expand Up @@ -121,6 +122,11 @@ public override void OnStart(StartState state)
TryApplyToolingDefinition();
}

public override void OnStartFinished(StartState state)
{
onStartFinishedFinished = true;
}

protected virtual void LoadPartModules()
{
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Tooling/ModuleToolingProcAvionics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private float GetInternalTankDiameter(float externalDiameter, float length)

public override float GetModuleCost(float defaultCost, ModifierStagingSituation sit)
{
if (!onStartFinished || HighLogic.CurrentGame.Mode != Game.Modes.CAREER) return 0f;
if (!onStartFinishedFinished || HighLogic.CurrentGame.Mode != Game.Modes.CAREER) return 0f;

return GetUntooledPenaltyCost() + GetInternalTankModuleCost();
}
Expand Down

0 comments on commit e742b31

Please sign in to comment.