public void ProcessActionGroup() { var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null) { return; } if (!VesselCommon.DoVesselChecks(VesselId)) { return; } //Ignore SAS if we are spectating as it will fight with the FI if (ActionGroup == KSPActionGroup.SAS && VesselCommon.IsSpectating && FlightGlobals.ActiveVessel && FlightGlobals.ActiveVessel.id == vessel.id) { return; } if (vessel.ActionGroups != null) { var currentValue = vessel.ActionGroups[ActionGroup]; if (currentValue != Value) { vessel.ActionGroups.ToggleGroup(ActionGroup); } } vessel.protoVessel?.actionGroups.SetValue(ActionGroup.ToString(), $"{Value.ToString(CultureInfo.InvariantCulture)}, 0"); }
private void RunCheck(Guid vesselId, string experimentId, ExperimentState state) { if (experimentId == this.experimentId) { CheckVessel(FlightGlobals.FindVessel(vesselId)); } }
/// <summary> /// Get the vessels that are in a past subspace and kill them /// </summary> private IEnumerator RemoveVesselsInPastSubspace() { var seconds = new WaitForSeconds((float)TimeSpan.FromMilliseconds(SettingsSystem.ServerSettings.VesselKillCheckMsInterval).TotalSeconds); while (true) { try { if (!Enabled) { break; } if (MainSystem.Singleton.GameRunning) { var vesselsToUnload = VesselProtoSystem.Singleton.AllPlayerVessels .Where(v => v.Loaded && VesselCommon.VesselIsControlledAndInPastSubspace(v.VesselId)) .Select(v => FlightGlobals.FindVessel(v.VesselId)) .ToArray(); if (vesselsToUnload.Any()) { Debug.Log($"[LMP]: Unloading {vesselsToUnload.Length} vessels that are in a past subspace"); UnloadVessels(vesselsToUnload); } } } catch (Exception e) { Debug.LogError($"[LMP]: Coroutine error in CheckVesselsToKill {e}"); } yield return(seconds); } }
/// <summary> /// Here we wait until we fully switched to the dominant vessel and THEN we send the vessel dock information. /// We wait 5 seconds before sending the data to give time to the dominant vessel to detect the dock /// </summary> private static IEnumerator WaitUntilWeSwitchedThenSendDockInfo(Guid weakId, Guid dominantId, int secondsToWait = 5) { var start = LunaComputerTime.UtcNow; var currentSubspaceId = WarpSystem.Singleton.CurrentSubspace; var waitInterval = new WaitForSeconds(0.5f); while (FlightGlobals.ActiveVessel?.id != dominantId && LunaComputerTime.UtcNow - start < TimeSpan.FromSeconds(30)) { yield return(waitInterval); } if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == dominantId) { /* We are NOT the dominant vessel so wait 5 seconds so the dominant vessel detects the docking. * If we send the vessel definition BEFORE the dominant detects it, then the dominant won't be able * to undock properly as he will think that he is the weak vessel. */ yield return(new WaitForSeconds(secondsToWait)); FlightGlobals.ActiveVessel.BackupVessel(); LunaLog.Log($"[LMP]: Sending dock info to the server! Final dominant vessel parts {FlightGlobals.ActiveVessel.protoVessel.protoPartSnapshots.Count}"); System.MessageSender.SendDockInformation(weakId, FlightGlobals.FindVessel(dominantId), currentSubspaceId, FlightGlobals.ActiveVessel.protoVessel); } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselFairingMsgData msgData) || !System.FairingSystemReady) { return; } //Vessel might exist in the store but not in game (if the vessel is in safety bubble for example) VesselsProtoStore.UpdateVesselProtoPartFairing(msgData); var vessel = FlightGlobals.FindVessel(msgData.VesselId); if (vessel == null) { return; } var part = VesselCommon.FindProtoPartInProtovessel(vessel.protoVessel, msgData.PartFlightId); if (part != null) { var module = VesselCommon.FindProtoPartModuleInProtoPart(part, "ModuleProceduralFairing"); module?.moduleValues.SetValue("fsm", "st_flight_deployed"); module?.moduleValues.RemoveNodesStartWith("XSECTION"); (module?.moduleRef as ModuleProceduralFairing)?.DeployFairing(); } }
public void HandleMessage(IMessageData messageData) { var msgData = messageData as VesselDockMsgData; if (msgData == null) { return; } LunaLog.Log("[LMP]: Docking message received!"); if (FlightGlobals.ActiveVessel?.id == msgData.WeakVesselId) { LunaLog.Log("[LMP]: Docking NOT detected. We DON'T OWN the dominant vessel"); SystemsContainer.Get <VesselRemoveSystem>().AddToKillList(FlightGlobals.ActiveVessel, true); SystemsContainer.Get <VesselSwitcherSystem>().SwitchToVessel(msgData.DominantVesselId); } if (FlightGlobals.ActiveVessel?.id == msgData.DominantVesselId && !VesselCommon.IsSpectating) { var newProto = VesselSerializer.DeserializeVessel(msgData.FinalVesselData); if (VesselCommon.ProtoVesselHasChanges(FlightGlobals.ActiveVessel.protoVessel, newProto)) { LunaLog.Log("[LMP]: Docking NOT detected. We OWN the dominant vessel"); //We own the dominant vessel and dind't detected the docking event so we need to reload our OWN vessel //so if we send our own protovessel later, we send the updated definition SystemsContainer.Get <VesselProtoSystem>().VesselLoader.ReloadVessel(newProto); } } //Some other 2 players docked so just remove the weak vessel. SystemsContainer.Get <VesselRemoveSystem>().AddToKillList(FlightGlobals.FindVessel(msgData.WeakVesselId), true); SystemsContainer.Get <VesselProtoSystem>().HandleVesselProtoData(msgData.FinalVesselData, msgData.DominantVesselId); }
/// <summary> /// When a stage of ANY vessel is separated, try to get the update lock of that debris /// </summary> /// <param name="data"></param> public void OnStageSeparation(EventReport data) { if (!VesselCommon.IsSpectating) { var debrisVessel = FlightGlobals.FindVessel(data.origin.vessel.id); var missionId = data.origin.missionID; if (!SystemsContainer.Get <LockSystem>().LockWithPrefixExists($"debris-{missionId}")) { SystemsContainer.Get <LockSystem>().AcquireLock($"debris-{missionId}_{debrisVessel.id}"); SystemsContainer.Get <VesselPositionSystem>().MessageSender.SendVesselPositionUpdate(new VesselPositionUpdate(debrisVessel)); } else { var debrisLocks = SystemsContainer.Get <LockSystem>().ServerLocks.Where(l => l.Key.StartsWith($"debris-{missionId}")) .Select(l => l.Key.Substring(l.Key.IndexOf('_') + 1)).ToArray(); var otherVesselsWIthSameMissionId = FlightGlobals.Vessels .Where(v => v.Parts.Any() && v.Parts.First().missionID == missionId && v.id != debrisVessel.id) .Select(v => v.id.ToString()).ToArray(); if (debrisLocks.Length == otherVesselsWIthSameMissionId.Length) { debrisVessel.id = new Guid(debrisLocks.Except(otherVesselsWIthSameMissionId).First()); } else { SystemsContainer.Get <LockSystem>().AcquireLock($"debris-{missionId}_{debrisVessel.id}"); SystemsContainer.Get <VesselPositionSystem>().MessageSender.SendVesselPositionUpdate(new VesselPositionUpdate(debrisVessel)); } } } }
public void ProcessPartMethodCallSync() { var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null || !vessel.loaded) { return; } if (!VesselCommon.DoVesselChecks(VesselId)) { return; } var part = vessel.protoVessel.GetProtoPart(PartFlightId); if (part != null) { var module = part.FindProtoPartModuleInProtoPart(ModuleName); if (module != null) { if (module.moduleRef != null) { module.moduleRef.GetType().GetMethod(MethodName, AccessTools.all)?.Invoke(module.moduleRef, null); PartModuleEvent.onPartModuleMethodProcessed.Fire(module, MethodName); } } } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselEvaMsgData msgData) || !System.EvaSystemReady) { return; } //We received a msg for our own controlled vessel so ignore it if (LockSystem.LockQuery.ControlLockBelongsToPlayer(msgData.VesselId, SettingsSystem.CurrentSettings.PlayerName)) { return; } //Vessel might exist in the store but not in game (if the vessel is in safety bubble for example) VesselsProtoStore.UpdateVesselProtoEvaFsm(msgData); var vessel = FlightGlobals.FindVessel(msgData.VesselId); if (vessel == null || !vessel.isEVA) { return; } try { System.RunEvent(vessel, msgData.NewState, msgData.EventToRun); } catch (Exception) { //Ignore the eva animation errors } }
public void HandleDocking(Guid from, Guid to) { var fromVessel = FlightGlobals.FindVessel(from); var toVessel = FlightGlobals.FindVessel(to); var finalVessel = fromVessel != null && toVessel != null ? Vessel.GetDominantVessel(fromVessel, toVessel) : fromVessel ?? toVessel; if (finalVessel != null) { var vesselIdToRemove = finalVessel.id == from ? to : from; if (finalVessel == FlightGlobals.ActiveVessel) { LunaLog.Log($"[LMP]: Docking: We own the dominant vessel {finalVessel.id}"); } else { LunaLog.Log($"[LMP]: Docking: We DON'T own the dominant vessel {finalVessel.id}. Switching"); FlightGlobals.SetActiveVessel(finalVessel); } SystemsContainer.Get <VesselProtoSystem>().RemoveVesselFromLoadingSystem(vesselIdToRemove); SystemsContainer.Get <VesselRemoveSystem>().MessageSender.SendVesselRemove(vesselIdToRemove, true); LunaLog.Log("[LMP]: Docking event over!"); } }
IEnumerator <YieldInstruction> CompleteVesselLoad(string key, Guid id) { if (FlightGlobals.Vessels.Count == 0) { yield return(new WaitForEndOfFrame()); } if (!vessels.ContainsKey(key)) { yield break; } VesselInfo vi = vessels[key]; Vessel vessel = FlightGlobals.FindVessel(id); if (vessel == null || vessel.state == Vessel.State.DEAD) { id = Guid.Empty; vessels.Remove(key); } else if (vi.hash == 0 && HighLogic.LoadedScene == GameScenes.FLIGHT) { vi.hash = vessel.GetHashes().FirstOrDefault(); LoggingUtil.LogVerbose(this, "Setting hash for " + id + " on load to: " + vi.hash); } }
public static InterestedVessel Load(ConfigNode node) { if (node.HasValue("VesselGuid")) { Guid id = new Guid(node.GetValue("VesselGuid")); if (FlightGlobals.fetch) { Vessel vsl = FlightGlobals.FindVessel(id); if (vsl != null) { if (vsl.protoVessel != null) { ProtoVessel protovsl = vsl.protoVessel; InterestedVessel interestedVessel = new InterestedVessel(vsl, protovsl); node.TryGetValue("timeLastRefresh", ref interestedVessel.TimeLastRefresh); ConfigNode[] cacheResourcesNodes = node.GetNodes("CACHERESOURCE"); for (int crI = 0; crI < cacheResourcesNodes.Length; crI++) { CacheResources.CacheResource cacheResource = CacheResources.CacheResource.Load(cacheResourcesNodes[crI], protovsl); if (cacheResource != null) { interestedVessel.CachedResources.Add(cacheResource); } } return(interestedVessel); } } } } return(null); }
/// <summary> /// If short_strings parameter is true then the strings used for display of the data will be shorter when inflight. /// </summary> public static void Fileman(this Panel p, Vessel v, bool short_strings = false) { // avoid corner-case when this is called in a lambda after scene changes v = FlightGlobals.FindVessel(v.id); // if vessel doesn't exist anymore, leave the panel empty if (v == null) { return; } // get info from the cache Vessel_info vi = Cache.VesselInfo(v); // if not a valid vessel, leave the panel empty if (!vi.is_valid) { return; } // set metadata p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(40)), " <color=#cccccc>FILE MANAGER</color>")); p.Width(Styles.ScaleWidthFloat(465.0f)); p.paneltype = Panel.PanelType.data; // time-out simulation if (p.Timeout(vi)) { return; } // get vessel drive Drive drive = DB.Vessel(v).drive; // draw data section p.AddSection("DATA"); foreach (var pair in drive.files) { string filename = pair.Key; File file = pair.Value; Render_file(p, filename, file, drive, short_strings && Lib.IsFlight(), Cache.VesselInfo(v).connection.rate); } if (drive.files.Count == 0) { p.AddContent("<i>no files</i>", string.Empty); } // draw samples section p.AddSection("SAMPLES"); foreach (var pair in drive.samples) { string filename = pair.Key; Sample sample = pair.Value; Render_sample(p, filename, sample, drive, short_strings && Lib.IsFlight()); } if (drive.samples.Count == 0) { p.AddContent("<i>no samples</i>", string.Empty); } }
public void update() { // reset panel panel.clear(); // get vessel selected_v = selected_id == Guid.Empty ? null : FlightGlobals.FindVessel(selected_id); // if nothing is selected, or if the selected vessel doesn't exist // anymore, or if it has become invalid for whatever reason if (selected_v == null || !Cache.VesselInfo(selected_v).is_valid) { // forget the selected vessel, if any selected_id = Guid.Empty; // filter flag is updated on render_vessel show_filter = false; // used to detect when no vessels are in list bool setup = false; // draw active vessel if any if (FlightGlobals.ActiveVessel != null) { setup |= render_vessel(panel, FlightGlobals.ActiveVessel); } // for each vessel foreach (Vessel v in FlightGlobals.Vessels) { // skip active vessel if (v == FlightGlobals.ActiveVessel) continue; // draw the vessel setup |= render_vessel(panel, v); } // empty vessel case if (!setup) { panel.header("<i>no vessels</i>"); } } // if a vessel is selected else { // header act as title render_vessel(panel, selected_v); // update page content switch (page) { case MonitorPage.telemetry: panel.telemetry(selected_v); break; case MonitorPage.data: panel.fileman(selected_v, true); break; // Using short_strings parameter to stop overlapping when inflight. case MonitorPage.scripts: panel.devman(selected_v); break; case MonitorPage.config: panel.config(selected_v); break; case MonitorPage.log: panel.logman(selected_v); break; } } }
/// <summary> /// Make the other player vessels inmortal /// </summary> private void MakeOtherPlayerVesselsImmortal() { if (Enabled && VesselImmortalSystemReady) { var ownedVessels = SystemsContainer.Get <LockSystem>().GetOwnedLocksPrefix("control-").Select(LockSystem.TrimLock) .Union(SystemsContainer.Get <LockSystem>().GetLocksWithPrefix("update-").Select(LockSystem.TrimLock)) .Select(i => FlightGlobals.FindVessel(new Guid(i))) .Where(v => v != null) .ToArray(); var othersPeopleVessels = SystemsContainer.Get <LockSystem>().GetLocksWithPrefix("control-").Select(LockSystem.TrimLock) .Union(SystemsContainer.Get <LockSystem>().GetLocksWithPrefix("update-").Select(LockSystem.TrimLock)) .Except(ownedVessels.Select(v => v.id.ToString())) .Select(i => FlightGlobals.FindVessel(new Guid(i))) //Select the vessels and filter out the nulls .Where(v => v != null).ToArray(); foreach (var vessel in ownedVessels) { SetVesselImmortalState(vessel, false); } foreach (var vessel in othersPeopleVessels) { SetVesselImmortalState(vessel, true); } } }
protected override void PrintDisplay() { GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.Label(VesselName); GUILayout.FlexibleSpace(); if (GUILayout.Button("Reload")) { var vessel = FlightGlobals.FindVessel(VesselId); //Do not call BackupVessel() as that would overwrite the proto with the actual vessel values and mess up part syncs VesselLoader.LoadVessel(vessel.protoVessel, true); } GUILayout.EndHorizontal(); Data.Display = GUILayout.Toggle(Data.Display, nameof(Data), ButtonStyle); Data.Print(); Locks.Display = GUILayout.Toggle(Locks.Display, nameof(Locks), ButtonStyle); Locks.Print(); Orbit.Display = GUILayout.Toggle(Orbit.Display, nameof(Orbit), ButtonStyle); Orbit.Print(); Interpolation.Display = GUILayout.Toggle(Interpolation.Display, nameof(Interpolation), ButtonStyle); Interpolation.Print(); Position.Display = GUILayout.Toggle(Position.Display, nameof(Position), ButtonStyle); Position.Print(); Vectors.Display = GUILayout.Toggle(Vectors.Display, nameof(Vectors), ButtonStyle); Vectors.Print(); GUILayout.EndVertical(); }
/// <summary> /// Kills and unloads a vessel. /// </summary> public void KillVessel(Guid vesselId, string reason, bool switchVessel = true, bool removeFromStore = true) { //ALWAYS remove it from the proto store as this dictionary is maintained even if we are in the KSC //This means that while in KSC if we receive a vessel remove msg, our FlightGlobals.Vessels will be empty //But our VesselsProtoStore probably contains that vessel that must be removed. if (removeFromStore) { VesselsProtoStore.RemoveVessel(vesselId); VesselPositionSystem.Singleton.RemoveVessel(vesselId); VesselFlightStateSystem.Singleton.RemoveVessel(vesselId); } var killVessel = FlightGlobals.FindVessel(vesselId); if (killVessel == null || killVessel.state == Vessel.State.DEAD) { return; } LunaLog.Log($"[LMP]: Killing vessel {killVessel.id}. Reason: {reason}"); if (switchVessel) { SwitchVesselIfSpectating(killVessel); } UnloadVesselFromGame(killVessel); KillGivenVessel(killVessel); UnloadVesselFromScenario(killVessel); //When vessel.Die() is called, KSP calls RefreshMarkers() so no need to call it ourselves }
/// <summary> /// When a stage of ANY vessel is separated, try to get the update lock of that debris /// </summary> /// <param name="data"></param> public void OnStageSeparation(EventReport data) { if (!VesselCommon.IsSpectating && !VesselCommon.ActiveVesselIsInSafetyBubble()) { var debrisVessel = FlightGlobals.FindVessel(data.origin.vessel.id); var missionId = data.origin.missionID; if (!LockSystem.Singleton.LockWithPrefixExists("debris-" + missionId)) { LockSystem.Singleton.AcquireLock("debris-" + missionId + "_" + debrisVessel.id); VesselPositionSystem.Singleton.MessageSender.SendVesselPositionUpdate(new VesselPositionUpdate(debrisVessel)); } else { var debrisLocks = LockSystem.Singleton.ServerLocks.Where(l => l.Key.StartsWith("debris-" + missionId)) .Select(l => l.Key.Substring(l.Key.IndexOf('_') + 1)).ToArray(); var otherVesselsWIthSameMissionId = FlightGlobals.Vessels .Where(v => v.Parts.Any() && v.Parts.First().missionID == missionId && v.id != debrisVessel.id) .Select(v => v.id.ToString()).ToArray(); if (debrisLocks.Length == otherVesselsWIthSameMissionId.Length) { debrisVessel.id = new Guid(debrisLocks.Except(otherVesselsWIthSameMissionId).First()); } else { LockSystem.Singleton.AcquireLock("debris-" + missionId + "_" + debrisVessel.id); VesselPositionSystem.Singleton.MessageSender.SendVesselPositionUpdate(new VesselPositionUpdate(debrisVessel)); } } } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselUpdateMsgData msgData) || !System.UpdateSystemReady) { return; } //We received a msg for our own controlled/updated vessel so ignore it if (!VesselCommon.DoVesselChecks(msgData.VesselId)) { return; } //Vessel might exist in the store but not in game (if the vessel is in safety bubble for example) VesselsProtoStore.UpdateVesselProtoValues(msgData); var vessel = FlightGlobals.FindVessel(msgData.VesselId); if (vessel == null) { return; } UpdateVesselFields(vessel, msgData); UpdateActionGroups(vessel, msgData); UpdateProtoVesselValues(vessel.protoVessel, msgData); }
private void Init(Vessel v, bool powered, bool storm) { // are we connected if (RemoteTech.Connected(v.id)) { linked = RemoteTech.ConnectedToKSC(v.id); status = RemoteTech.TargetsKSC(v.id) ? (int)LinkStatus.direct_link : (int)LinkStatus.indirect_link; target_name = status == (int)LinkStatus.direct_link ? Lib.Ellipsis("DSN: " + (RemoteTech.NameTargetsKSC(v.id) ?? ""), 20) : Lib.Ellipsis(RemoteTech.NameFirstHopToKSC(v.id) ?? "", 20); Guid[] controlPath = null; if (linked) { controlPath = RemoteTech.GetCommsControlPath(v.id); } // Get the lowest rate in ControlPath if (controlPath != null) { // Get rate from the firstHop, each Hop will do the same logic, then we will have the lowest rate for the path if (controlPath.Length > 0) { double dist = RemoteTech.GetCommsDistance(v.id, controlPath[0]); strength = 1 - (dist / Math.Max(RemoteTech.GetCommsMaxDistance(v.id, controlPath[0]), 1)); strength = Math.Pow(strength, Settings.DataRateDampingExponentRT); // If using relay, get the lowest rate if (status != (int)LinkStatus.direct_link) { Vessel target = FlightGlobals.FindVessel(controlPath[0]); ConnectionInfo ci = target.KerbalismData().Connection; strength *= ci.strength; rate = Math.Min(ci.rate, rate * strength); } else { rate *= strength; } } control_path = new List <string[]>(); Guid i = v.id; foreach (Guid id in controlPath) { var name = Lib.Ellipsis(RemoteTech.GetSatelliteName(i) + " \\ " + RemoteTech.GetSatelliteName(id), 35); var value = Lib.HumanReadablePerc(Math.Ceiling((1 - (RemoteTech.GetCommsDistance(i, id) / RemoteTech.GetCommsMaxDistance(i, id))) * 10000) / 10000, "F2"); var tooltip = "Distance: " + Lib.HumanReadableDistance(RemoteTech.GetCommsDistance(i, id)) + "\nMax Distance: " + Lib.HumanReadableDistance(RemoteTech.GetCommsMaxDistance(i, id)); control_path.Add(new string[] { name, value, tooltip }); i = id; } } } // is loss of connection due to a blackout else if (RemoteTech.GetCommsBlackout(v.id)) { status = storm ? (int)LinkStatus.storm : (int)LinkStatus.plasma; } }
public static void FileMan(this Panel p, Vessel v) { // avoid corner-case when this is called in a lambda after scene changes v = FlightGlobals.FindVessel(v.id); // if vessel doesn't exist anymore, leave the panel empty if (v == null) { return; } // get info from the cache Vessel_Info vi = Cache.VesselInfo(v); // if not a valid vessel, leave the panel empty if (!vi.is_valid) { return; } // set metadata p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, 20), " <color=#cccccc>FILE MANAGER</color>")); p.Width(320.0f); // time-out simulation if (p.Timeout(vi)) { return; } // get vessel drive Drive drive = DB.Vessel(v).drive; // draw data section p.SetSection("DATA"); foreach (var pair in drive.files) { string filename = pair.Key; File file = pair.Value; Render_File(p, filename, file, drive); } if (drive.files.Count == 0) { p.SetContent("<i>no files</i>", string.Empty); } // draw samples section p.SetSection("SAMPLES"); foreach (var pair in drive.samples) { string filename = pair.Key; Sample sample = pair.Value; Render_Sample(p, filename, sample, drive); } if (drive.samples.Count == 0) { p.SetContent("<i>no samples</i>", string.Empty); } }
/// <summary> /// Gets the vessel associated with the given key. /// </summary> /// <param name="key">The key to find an associated vessel for.</param> /// <returns>The vessel that is associated to the given key or null if none.</returns> public Vessel GetAssociatedVessel(string key) { if (vessels.ContainsKey(key)) { return(FlightGlobals.FindVessel(vessels[key].id)); } return(null); }
/// <summary> /// Specifies the vessel that we should switch to /// </summary> public void SwitchToVessel(Guid vesselId) { VesselToSwitchTo = FlightGlobals.FindVessel(vesselId); if (VesselToSwitchTo != null) { LunaLog.Log($"[LMP]: Switching to vessel {vesselId}"); } }
private void Init(Vessel v, bool powered, bool storm) { if (!powered || v.connection == null) { linked = false; status = (int)LinkStatus.no_link; return; } // force CommNet update of unloaded vessels if (!v.loaded) { Lib.ReflectionValue(v.connection, "unloadedDoOnce", true); } // are we connected to DSN if (v.connection.IsConnected) { linked = true; var link = v.connection.ControlPath.First; status = link.hopType == CommNet.HopType.Home ? (int)LinkStatus.direct_link : (int)LinkStatus.indirect_link; strength = link.signalStrength; rate *= Math.Pow(link.signalStrength, Settings.DataRateDampingExponent); target_name = Lib.Ellipsis(Localizer.Format(v.connection.ControlPath.First.end.displayName).Replace("Kerbin", "DSN"), 20); if (status != (int)LinkStatus.direct_link) { Vessel firstHop = Lib.CommNodeToVessel(v.Connection.ControlPath.First.end); // Get rate from the firstHop, each Hop will do the same logic, then we will have the min rate for whole path rate = Math.Min(Cache.VesselInfo(FlightGlobals.FindVessel(firstHop.id)).connection.rate, rate); } } // is loss of connection due to plasma blackout else if (Lib.ReflectionValue <bool>(v.connection, "inPlasma")) // calling InPlasma causes a StackOverflow :( { status = (int)LinkStatus.plasma; } control_path = new List <string[]>(); foreach (CommLink link in v.connection.ControlPath) { double antennaPower = link.end.isHome ? link.start.antennaTransmit.power + link.start.antennaRelay.power : link.start.antennaTransmit.power; double signalStrength = 1 - ((link.start.position - link.end.position).magnitude / Math.Sqrt(antennaPower * link.end.antennaRelay.power)); signalStrength = (3 - (2 * signalStrength)) * Math.Pow(signalStrength, 2); string name = Lib.Ellipsis(Localizer.Format(link.end.name).Replace("Kerbin", "DSN"), 35); string value = Lib.HumanReadablePerc(Math.Ceiling(signalStrength * 10000) / 10000, "F2"); string tooltip = "Distance: " + Lib.HumanReadableRange((link.start.position - link.end.position).magnitude) + "\nMax Distance: " + Lib.HumanReadableRange(Math.Sqrt((link.start.antennaTransmit.power + link.start.antennaRelay.power) * link.end.antennaRelay.power)); control_path.Add(new string[] { name, value, tooltip }); } if (linked) { } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselDockMsgData msgData)) { return; } LunaLog.Log("Docking message received!"); //Add the new vessel data to the store VesselsProtoStore.HandleVesselProtoData(msgData.FinalVesselData, msgData.NumBytes, msgData.DominantVesselId); if (FlightGlobals.ActiveVessel?.id == msgData.WeakVesselId) { LunaLog.Log($"Docking NOT detected. We DON'T OWN the dominant vessel. Switching to {msgData.DominantVesselId}"); SystemsContainer.Get <VesselRemoveSystem>().AddToKillList(FlightGlobals.ActiveVessel.id); SystemsContainer.Get <VesselSwitcherSystem>().SwitchToVessel(msgData.DominantVesselId); WarpSystem.WarpIfSubspaceIsMoreAdvanced(msgData.SubspaceId); } if (FlightGlobals.ActiveVessel?.id == msgData.DominantVesselId && !VesselCommon.IsSpectating) { var newProto = VesselSerializer.DeserializeVessel(msgData.FinalVesselData, msgData.NumBytes); /* This is a strange case were we didn't detect the docking on time and the weak vessel send the new definition... * Usually it happens when a vessel in a future subspace docks with a vessel in the past and the vessel in the past is the dominant vessel * The reason why is bad is because the ModuleDockingNode sent by the WEAK vessel will tell us that we are * NOT the dominant (because we received the vesselproto from the WEAK vessel) so we won't be able to undock properly... * This will be fixed if we go to the space center and reload again the vessel... */ LunaLog.Log("Docking NOT detected. We OWN the dominant vessel"); if (FlightGlobals.FindVessel(msgData.WeakVesselId) != null) { LunaLog.Log($"Weak vessel {msgData.WeakVesselId} still exists in our game. Removing it now"); SystemsContainer.Get <VesselRemoveSystem>().AddToKillList(msgData.WeakVesselId); SystemsContainer.Get <VesselRemoveSystem>().KillVessel(msgData.WeakVesselId); } /* We own the dominant vessel and dind't detected the docking event so we need to reload our OWN vessel * so if we send our own protovessel later, we send the updated definition */ LunaLog.Log($"Creating the missing parts in our own vessel. Current: {FlightGlobals.ActiveVessel.parts.Count} Expected: {newProto.protoPartSnapshots.Count}"); //ProtoToVesselRefresh.CreateMissingPartsInCurrentProtoVessel(FlightGlobals.ActiveVessel, newProto); VesselLoader.ReloadVessel(newProto); LunaLog.Log("Force sending the new proto vessel"); SystemsContainer.Get <VesselProtoSystem>().MessageSender.SendVesselMessage(FlightGlobals.ActiveVessel, true); WarpSystem.WarpIfSubspaceIsMoreAdvanced(msgData.SubspaceId); return; } //Some other 2 players docked so just remove the weak vessel. SystemsContainer.Get <VesselRemoveSystem>().AddToKillList(msgData.WeakVesselId); }
void focusVessel() { var vsl = FlightGlobals.FindVessel(vessel.id); if (vsl != null) { toMapView(vsl.mapObject); } }
/// <summary> /// Specifies the vessel that we should switch to /// </summary> public void SwitchToVessel(Guid vesselId) { VesselToSwitchTo = FlightGlobals.FindVessel(vesselId); if (VesselToSwitchTo != null) { LunaLog.Log($"[LMP]: Switching to vessel {vesselId}"); Client.Singleton.StartCoroutine(SwitchToVessel()); } }
/// <summary> /// Find the vessel using the lock name /// </summary> private void UpdateVesselColorsFromLockVesselId(Guid vesselId) { var vessel = FlightGlobals.FindVessel(vesselId); if (vessel != null) { System.SetVesselOrbitColor(vessel); } }
public static void Failman(this Panel p, Vessel v) { // avoid corner-case when this is called in a lambda after scene changes v = FlightGlobals.FindVessel(v.id); // if vessel doesn't exist anymore, leave the panel empty if (v == null) { return; } // get data VesselData vd = v.KerbalismData(); // if not a valid vessel, leave the panel empty if (!vd.IsSimulated) { return; } // set metadata p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(20)), " ", Lib.Color("Quality Management", Lib.Kolor.LightGrey))); p.Width(Styles.ScaleWidthFloat(355.0f)); p.paneltype = Panel.PanelType.failures; string section = string.Empty; // get devices List <ReliabilityInfo> devices = vd.ReliabilityStatus(); int deviceCount = 0; // for each device foreach (var ri in devices) { if (section != Group2Section(ri.group)) { section = Group2Section(ri.group); p.AddSection(section); } string status = StatusString(ri); // render device entry p.AddContent( label: ri.title, value: status, hover: () => Highlighter.Set(ri.partId, Color.blue)); deviceCount++; } // no devices case if (deviceCount == 0) { p.AddContent("<i>no quality info</i>"); } }
/// <summary> /// Check vessels that must be loaded /// </summary> public void CheckVesselsToLoad() { if (HighLogic.LoadedScene < GameScenes.SPACECENTER) { return; } try { foreach (var keyVal in VesselProtos) { if (keyVal.Value.TryPeek(out var vesselProto) && vesselProto.GameTime <= TimeSyncSystem.UniversalTime) { keyVal.Value.TryDequeue(out _); if (VesselRemoveSystem.VesselWillBeKilled(vesselProto.VesselId)) { continue; } var forceReload = vesselProto.ForceReload; var protoVessel = vesselProto.CreateProtoVessel(); keyVal.Value.Recycle(vesselProto); if (protoVessel == null || protoVessel.HasInvalidParts(!VesselsUnableToLoad.Contains(vesselProto.VesselId))) { VesselsUnableToLoad.Add(vesselProto.VesselId); continue; } VesselsUnableToLoad.Remove(vesselProto.VesselId); var existingVessel = FlightGlobals.FindVessel(vesselProto.VesselId); if (existingVessel == null) { if (VesselLoader.LoadVessel(protoVessel, forceReload)) { LunaLog.Log($"[LMP]: Vessel {protoVessel.vesselID} loaded"); VesselLoadEvent.onLmpVesselLoaded.Fire(protoVessel.vesselRef); } } else { if (VesselLoader.LoadVessel(protoVessel, forceReload)) { LunaLog.Log($"[LMP]: Vessel {protoVessel.vesselID} reloaded"); VesselReloadEvent.onLmpVesselReloaded.Fire(protoVessel.vesselRef); } } } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in CheckVesselsToLoad {e}"); } }