From af21c1acdf82cf63081683223b2c146dc7cfe44a Mon Sep 17 00:00:00 2001 From: siimav Date: Sat, 6 Jul 2024 16:18:49 +0300 Subject: [PATCH 1/2] Toggle ground station state based on selected launch site --- .../RP0/ModIntegrations/KSCSwitcherInterop.cs | 40 ++++++++++++------ Source/RP0/RP0.csproj | 3 ++ .../LaunchComplex/LCSpaceCenter.cs | 3 +- .../RP0/SpaceCenter/SpaceCenterManagement.cs | 14 ++++++- Source/RP0/Utilities/KCTUtilities.cs | 42 +++++++++++++++++++ 5 files changed, 87 insertions(+), 15 deletions(-) diff --git a/Source/RP0/ModIntegrations/KSCSwitcherInterop.cs b/Source/RP0/ModIntegrations/KSCSwitcherInterop.cs index ebe26e7c7af..d428d3a0816 100644 --- a/Source/RP0/ModIntegrations/KSCSwitcherInterop.cs +++ b/Source/RP0/ModIntegrations/KSCSwitcherInterop.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -7,10 +8,12 @@ namespace RP0 public static class KSCSwitcherInterop { private static bool? _isKSCSwitcherInstalled = null; - private static FieldInfo _fiKSCSwInstance; - private static FieldInfo _fiKSCSwSites; private static FieldInfo _fiKSCSwLastSite; private static FieldInfo _fiKSCSwDefaultSite; + private static MethodInfo _miKSCSwGetSiteByName; + private static object _kscLoaderInstance; // this is a static singleton + private static object _sites; // instance field in KSCLoader instance but in practice is never changed after parent object creation + private static Dictionary _groundStationNameDict = new Dictionary(); public const string LegacyDefaultKscId = "Stock"; public const string DefaultKscId = "us_cape_canaveral"; @@ -26,14 +29,17 @@ public static bool IsKSCSwitcherInstalled if (_isKSCSwitcherInstalled.Value) { Type t = a.GetType("regexKSP.KSCLoader"); - _fiKSCSwInstance = t?.GetField("instance", BindingFlags.Public | BindingFlags.Static); - _fiKSCSwSites = t?.GetField("Sites", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); + var fiKSCSwInstance = t?.GetField("instance", BindingFlags.Public | BindingFlags.Static); + _kscLoaderInstance = fiKSCSwInstance?.GetValue(null); + var fiKSCSwSites = t?.GetField("Sites", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); + _sites = fiKSCSwSites.GetValue(_kscLoaderInstance); t = a.GetType("regexKSP.KSCSiteManager"); _fiKSCSwLastSite = t?.GetField("lastSite", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); _fiKSCSwDefaultSite = t?.GetField("defaultSite", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); + _miKSCSwGetSiteByName = t?.GetMethod("GetSiteByName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - if (_fiKSCSwInstance == null || _fiKSCSwSites == null || _fiKSCSwLastSite == null || _fiKSCSwDefaultSite == null) + if (_kscLoaderInstance == null || _sites == null || _fiKSCSwLastSite == null || _fiKSCSwDefaultSite == null || _miKSCSwGetSiteByName == null) { RP0Debug.LogError("Failed to bind to KSCSwitcher"); _isKSCSwitcherInstalled = false; @@ -48,18 +54,26 @@ public static string GetActiveRSSKSC() { if (!IsKSCSwitcherInstalled) return null; - // get the LastKSC.KSCLoader.instance object // check the Sites object (KSCSiteManager) for the lastSite, if "" then get defaultSite - - object loaderInstance = _fiKSCSwInstance.GetValue(null); - if (loaderInstance == null) - return null; - object sites = _fiKSCSwSites.GetValue(loaderInstance); - string lastSite = _fiKSCSwLastSite.GetValue(sites) as string; + string lastSite = _fiKSCSwLastSite.GetValue(_sites) as string; if (lastSite == string.Empty) - lastSite = _fiKSCSwDefaultSite.GetValue(sites) as string; + lastSite = _fiKSCSwDefaultSite.GetValue(_sites) as string; return lastSite; } + + public static string GetGroundStationForKSC(string kscName) + { + if (!IsKSCSwitcherInstalled) return null; + + if (!_groundStationNameDict.TryGetValue(kscName, out string groundStationName)) + { + var cn = _miKSCSwGetSiteByName.Invoke(_sites, new object[] { kscName }) as ConfigNode; + groundStationName = cn?.GetValue("groundStation"); + _groundStationNameDict[kscName] = groundStationName; + } + + return groundStationName; + } } } diff --git a/Source/RP0/RP0.csproj b/Source/RP0/RP0.csproj index fe27920834d..554d7a5e81e 100644 --- a/Source/RP0/RP0.csproj +++ b/Source/RP0/RP0.csproj @@ -314,6 +314,9 @@ False + + False + False diff --git a/Source/RP0/SpaceCenter/LaunchComplex/LCSpaceCenter.cs b/Source/RP0/SpaceCenter/LaunchComplex/LCSpaceCenter.cs index 35f5e0d0fb2..f9c59e358fb 100644 --- a/Source/RP0/SpaceCenter/LaunchComplex/LCSpaceCenter.cs +++ b/Source/RP0/SpaceCenter/LaunchComplex/LCSpaceCenter.cs @@ -20,7 +20,6 @@ public class LCSpaceCenter : IConfigNode public PersistentObservableList LCConstructions = new PersistentObservableList(); [Persistent] public PersistentObservableList FacilityUpgrades = new PersistentObservableList(); - public List Constructions = new List(); @@ -29,6 +28,8 @@ public class LCSpaceCenter : IConfigNode public const int HangarIndex = 0; public LaunchComplex Hangar => LaunchComplexes[HangarIndex]; + public string AssociatedGroundStation => KSCSwitcherInterop.GetGroundStationForKSC(KSCName); + void added(int idx, ConstructionProject item) { Constructions.Add(item); } void removed(int idx, ConstructionProject item) { Constructions.Remove(item); } void updated() diff --git a/Source/RP0/SpaceCenter/SpaceCenterManagement.cs b/Source/RP0/SpaceCenter/SpaceCenterManagement.cs index e7e894782bd..a2cbade5bff 100644 --- a/Source/RP0/SpaceCenter/SpaceCenterManagement.cs +++ b/Source/RP0/SpaceCenter/SpaceCenterManagement.cs @@ -96,7 +96,7 @@ public static void ClearVesselEditMode() [KSPField(isPersistant = true)] public bool DontShowFirstRunAgain = false; #endregion - public const int VERSION = 8; + public const int VERSION = 9; [KSPField(isPersistant = true)] public int LoadedSaveVersion = VERSION; [KSPField(isPersistant = true)] public bool IsFirstStart = true; @@ -539,9 +539,15 @@ public override void OnLoad(ConfigNode node) // Prune bad or inactive KSCs. for (int i = KSCs.Count; i-- > 0;) { + bool any = false; LCSpaceCenter ksc = KSCs[i]; if (ksc.KSCName == null || ksc.KSCName.Length == 0 || (ksc.IsEmpty && ksc != ActiveSC)) + { KSCs.RemoveAt(i); + any = true; + } + + if (any) KCTUtilities.RefreshGroundStationActiveState(); } foreach (var vp in BuildPlans.Values) @@ -555,6 +561,11 @@ public override void OnLoad(ConfigNode node) if (LoadedSaveVersion < VERSION) { + if (LoadedSaveVersion < 9) + { + KCTUtilities.RefreshGroundStationActiveState(); + } + // This upgrades to new payloads // NOTE this upgrade has to come before other upgrades // that touch ship nodes, because they will do the UpgradePipeline @@ -887,6 +898,7 @@ public void SetActiveKSC(string site) newKsc = new LCSpaceCenter(site); newKsc.EnsureStartingLaunchComplexes(); KSCs.Add(newKsc); + KCTUtilities.RefreshGroundStationActiveState(); } SetActiveKSC(newKsc); diff --git a/Source/RP0/Utilities/KCTUtilities.cs b/Source/RP0/Utilities/KCTUtilities.cs index 1d60c6a7888..b99b67b1f61 100644 --- a/Source/RP0/Utilities/KCTUtilities.cs +++ b/Source/RP0/Utilities/KCTUtilities.cs @@ -3,6 +3,7 @@ using KSP.UI.Screens; using ROUtils; using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; @@ -1517,6 +1518,47 @@ public static void SetFacilityLevel(SpaceCenterFacility scf, int level) } } + public static void RefreshGroundStationActiveState() + { + var scInstance = SpaceCenterManagement.Instance; + if (scInstance == null) + { + RP0Debug.LogError("SpaceCenterManagement.Instance is null"); + return; + } + + if (!RealAntennas.HomeNodeTypes.initialized) + { + static IEnumerator DelayedRefreshRoutine() + { + yield return new WaitForEndOfFrame(); + RefreshGroundStationActiveState_Internal(); + } + scInstance.StartCoroutine(DelayedRefreshRoutine()); + } + else + { + RefreshGroundStationActiveState_Internal(); + } + } + + private static void RefreshGroundStationActiveState_Internal() + { + if (RealAntennas.HomeNodeTypes.HomeDict.TryGetValue("LaunchSite", out List lsHomes)) + { + RP0Debug.Log("RefreshGroundStationActiveState"); + var allActiveKSCStations = SpaceCenterManagement.Instance.KSCs.Select(ksc => ksc.AssociatedGroundStation).ToList(); + foreach (RealAntennas.Network.RACommNetHome home in lsHomes) + { + home.enabled = allActiveKSCStations.Contains(home.nodeName); + } + } + else + { + RP0Debug.LogError("Failed to update RA LaunchSite active state"); + } + } + private static void ClobberRACommnet() { var mInf = CommNetScenario.Instance?.GetType().GetMethod("ApplyTSLevelChange", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); From e595d3172b173a5a259fed72679347498cac9630 Mon Sep 17 00:00:00 2001 From: siimav Date: Sat, 13 Jul 2024 15:30:01 +0300 Subject: [PATCH 2/2] Add KSPAssemblyDependency for RA --- Source/RP0/Properties/AssemblyInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/RP0/Properties/AssemblyInfo.cs b/Source/RP0/Properties/AssemblyInfo.cs index 88312e76221..ef8fdc5a63d 100644 --- a/Source/RP0/Properties/AssemblyInfo.cs +++ b/Source/RP0/Properties/AssemblyInfo.cs @@ -45,6 +45,7 @@ [assembly: KSPAssemblyDependency("ModularFlightIntegrator", 1, 0)] [assembly: KSPAssemblyDependency("RealFuels", 15, 7)] +[assembly: KSPAssemblyDependency("RealAntennas", 2, 4)] [assembly: KSPAssemblyDependency("ROUtils", 1, 0, 1)] [assembly: KSPAssemblyDependency("ClickThroughBlocker", 1, 8)] [assembly: KSPAssemblyDependency("ContractConfigurator", 2, 6)]